aio-table 12.0.1 → 13.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 +245 -0
  2. package/index.css +26 -15
  3. package/index.d.ts +85 -17
  4. package/index.js +703 -43
  5. package/package.json +4 -2
package/filter.css ADDED
@@ -0,0 +1,245 @@
1
+ .aio-filter-modal-size>.aio-popup {
2
+ padding: 12px;
3
+ width: 100vw;
4
+ max-width: 772px;
5
+ max-height: 100vh;
6
+ }
7
+
8
+ .aio-filter-add-button {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: 3px;
12
+ border: none;
13
+ background: none;
14
+ height: 24px;
15
+ font-size: 12px;
16
+ cursor: pointer;
17
+ }
18
+
19
+ .aio-filter-icon-button {
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ width: 36px;
24
+ height: 36px;
25
+ border-radius: 4px;
26
+ border: none;
27
+ cursor: pointer;
28
+ }
29
+ .aio-filter-remove-button{
30
+ background:none;
31
+ flex-shrink:0;
32
+ }
33
+ .aio-filter-button {
34
+ background: none;
35
+ border: none;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ flex-shrink: 0;
40
+ height: 30px;
41
+ border-radius: 4px;
42
+ color: #0069ff;
43
+ gap: 6px;
44
+ padding: 0 12px;
45
+ cursor: pointer;
46
+ position: relative;
47
+ }
48
+
49
+ .aio-filter-badge {
50
+ background: orange;
51
+ color: #fff;
52
+ min-width: 16px;
53
+ height: 12px;
54
+ border-radius: 12px;
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ font-size: 10px;
59
+ position: absolute;
60
+ top: -6px;
61
+ right: -3px;
62
+ }
63
+
64
+ .aio-filter-modal .aio-popup-header {
65
+ height: 36px;
66
+ }
67
+
68
+ .aio-filter-body {
69
+ padding: 6px;
70
+ gap: 12px;
71
+ display: flex;
72
+ flex-direction: column;
73
+ }
74
+ .aio-filter-body-rtl{
75
+ direction:rtl;
76
+ }
77
+
78
+ .aio-filter-body .af-current-filters {
79
+ display: flex;
80
+ flex-direction: column;
81
+ }
82
+ .aio-filter-body .af-current-filters .aio-input{
83
+ min-height:36px;
84
+ }
85
+
86
+ .aio-filter-body .af-filter-collections {
87
+ width: 100%;
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: 6px;
91
+ height: 100%;
92
+ }
93
+
94
+ .aio-filter-body .af-filter-collections .af-collection {
95
+ display: flex;
96
+ flex-direction: column;
97
+ background: #f8f8f8;
98
+ flex-shrink: 0;
99
+ border: 1px solid #f4f4f4;
100
+ border-radius: 6px;
101
+ position: relative;
102
+ color: #333;
103
+ }
104
+
105
+ .aio-filter-button:disabled {
106
+ opacity: 0.5;
107
+ cursor: not-allowed;
108
+ }
109
+
110
+ .aio-filter-active-button {
111
+ background: #0069ff;
112
+ color: #fff;
113
+ }
114
+
115
+ .aio-filter-panel {
116
+ position: relative;
117
+ padding: 6px;
118
+ display: flex;
119
+ flex-direction: column;
120
+ border: 1px solid #ddd;
121
+ border-radius: 6px;
122
+ }
123
+ .aio-filter-panel button{
124
+ color:inherit;
125
+ }
126
+
127
+ .af-collections-empty {
128
+ font-size: 12px;
129
+ width: 100%;
130
+ display: flex;
131
+ justify-content: center;
132
+ }
133
+
134
+ .aio-filter-panel-header {
135
+ display: flex;
136
+ align-items: center;
137
+ }
138
+
139
+ .aio-filter-panel-label {
140
+ flex: 1;
141
+ font-weight: bold;
142
+ font-size: 12px;
143
+ margin-bottom:12px;
144
+ }
145
+
146
+ .aio-filter-row {
147
+ display: flex;
148
+ align-items: center;
149
+ gap: 3px;
150
+ padding:3px;
151
+ background:#f2f2f2;
152
+ border-radius:6px;
153
+ position: relative;
154
+ margin-bottom:6px;
155
+ overflow-x: hidden;
156
+ }
157
+
158
+ .aio-filter-row .aio-input {
159
+ flex: 1;
160
+ padding:0 12px;
161
+ }
162
+ .aio-filter-row .aio-input.aio-filter-operator-select{
163
+ flex:none;
164
+ width:108px;
165
+ }
166
+
167
+ .aio-filter-toolbar {
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ gap: 6px;
172
+ }
173
+
174
+
175
+ .aio-filter-save-modal {
176
+ padding: 12px;
177
+ display: flex;
178
+ flex-direction: column;
179
+ gap: 12px;
180
+ }
181
+
182
+ .aio-filter-save-modal-footer {
183
+ display: flex;
184
+ gap: 6px;
185
+ }
186
+
187
+
188
+ .aio-filter-backdrop {
189
+ background: rgba(0, 0, 0, 0.7);
190
+ }
191
+
192
+
193
+
194
+
195
+ .aio-filter-row .aio-input{
196
+ border:none;
197
+ }
198
+
199
+ /*******************************tags**************************************/
200
+ /*************************************************************************/
201
+ /*******************************saved filter******************************/
202
+ .af-collection {
203
+ display: flex;
204
+ flex-direction: column;
205
+ background: #f8f8f8;
206
+ flex-shrink: 0;
207
+ border: 1px solid #f4f4f4;
208
+ border-radius: 6px;
209
+ position: relative;
210
+ color: #333;
211
+ }
212
+
213
+ .af-collection-header {
214
+ height: 36px;
215
+ display: flex;
216
+ align-items: center;
217
+ gap: 6px;
218
+ padding: 0 12px;
219
+ }
220
+
221
+ .af-collection-remove {
222
+ position: absolute;
223
+ background: #fff;
224
+ width: 24px;
225
+ border: 1px solid #ddd;
226
+ height: 24px;
227
+ display: flex;
228
+ align-items: center;
229
+ justify-content: center;
230
+ border-radius: 100%;
231
+ top: -6px;
232
+ cursor:pointer;
233
+ }
234
+
235
+ .af-collection-body {
236
+ display: flex;
237
+ gap: 6px;
238
+ padding: 6px;
239
+ }
240
+
241
+ .af-collection-name {
242
+ flex: 1;
243
+ padding-inline-start: 16px;
244
+ }
245
+ /*************************************************************************/
package/index.css CHANGED
@@ -1,3 +1,4 @@
1
+ @import './filter.css';
1
2
  :root {
2
3
  --aio-table-color: #0069ff;
3
4
  --aio-table-transition: 0.3s;
@@ -91,6 +92,7 @@
91
92
  .aio-table-row {
92
93
  display: flex;
93
94
  min-width: fit-content;
95
+ height:40px;
94
96
  }
95
97
  .aio-table-cell {
96
98
  padding: 6px 12px;
@@ -181,22 +183,12 @@
181
183
  align-items: center;
182
184
  justify-content: center;
183
185
  width: 36px;
184
- border: none;
185
- background: none;
186
- }
187
- .aio-table-toolbar .aio-filter-icon-button{
188
- border:none;
189
- background: none;
190
- }
191
- .aio-table-toolbar-button .aio-input{
192
- border:none;
193
- background: none;
194
- width:100%;
195
- height:100%;
196
- padding:0;
186
+ border: 1px solid #ddd;
187
+ background:#fff;
188
+ border-radius:100%;
189
+ width:36px;
190
+ padding:0 !important;
197
191
  }
198
-
199
-
200
192
  .aio-table-remove {
201
193
  border: none;
202
194
  width: 36px;
@@ -236,3 +228,22 @@
236
228
  min-height: 30px;
237
229
  }
238
230
 
231
+ .aio-filter-inline-label{
232
+ flex:1;
233
+ padding:0 12px;
234
+ box-sizing: border-box;
235
+ }
236
+ .aio-filter-label{
237
+ top:0;
238
+ z-index:10;
239
+ padding:0 12px;
240
+ font-size:12px;
241
+ box-sizing: border-box;
242
+ }
243
+ .aio-filter-modal .aio-popup{
244
+ background:#ddd;
245
+ max-width: 772px !important;
246
+ }
247
+ .af-current-filters .aio-input{
248
+ min-width:168px;
249
+ }
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- import * as UT from 'aio-utils';
2
+ import { I_AIOInput,I_formInput } from "aio-input";
3
3
  import "./index.css";
4
4
  type I_rowOption<T, R> = (p: I_rowDetail<T>) => R;
5
5
  type I_cellOption<T, R> = ((p: I_cellDetail<T>) => R) | string;
@@ -14,23 +14,11 @@ type I_cellDetail<T> = I_rowDetail<T> & {
14
14
  change: (newRow: T) => void;
15
15
  date: number[];
16
16
  };
17
- export type I_table_paging = UT.I_paging;
18
- export type I_table_sort<T> = UT.I_sort<T>;
19
- export type I_table_filter = UT.I_filter;
20
- export type I_table_filter_item = UT.I_filter_item;
21
- export type I_table_filter_saved_item = UT.I_filter_collection;
22
17
  export type I_table_column<T> = {
18
+ jalali?: boolean;
23
19
  title?: any;
24
20
  sort?: true | I_table_sort<T>;
25
- jalali?: boolean;
26
- filter?: {
27
- operators?: UT.I_filter_operator[];
28
- options?: {
29
- text: string;
30
- value: any;
31
- }[];
32
- type?: I_table_column<any>["type"];
33
- };
21
+ filter?: boolean;
34
22
  search?: boolean;
35
23
  id: string;
36
24
  width?: any;
@@ -48,7 +36,12 @@ export type I_table_column<T> = {
48
36
  titleAttrs?: {
49
37
  [attrs: string]: any;
50
38
  };
51
- type?: 'text' | 'number' | 'date';
39
+ type?: 'text' | 'number' | 'date' | 'select' | 'multiSelect' | 'checkbox';
40
+ filterInput?: I_AIOInput & {
41
+ type: I_table_column<any>["type"];
42
+ label?: string;
43
+ };
44
+ filterOperators?: ('less' | 'lessequal' | 'more' | 'moreequal' | 'equal' | 'notEqual' | 'contain' | 'notContain')[];
52
45
  show?: boolean;
53
46
  pattern?: string;
54
47
  data?: any;
@@ -102,7 +95,8 @@ export type I_table<T> = {
102
95
  style?: any;
103
96
  attrs?: any;
104
97
  placeholder?: ReactNode;
105
- filter?: I_table_filter;
98
+ columnsFilter?: I_table_columns_filter;
99
+ formFilter?: I_table_form_filter;
106
100
  gap?: [number, number];
107
101
  striped?: [string, string];
108
102
  columnOption?: {
@@ -112,3 +106,77 @@ export type I_table<T> = {
112
106
  };
113
107
  declare const AIOTable: <T>(props: I_table<T>) => import("react/jsx-runtime").JSX.Element;
114
108
  export default AIOTable;
109
+ export type I_table_sort<T> = {
110
+ active?: boolean;
111
+ dir?: 'dec' | 'inc';
112
+ title?: ReactNode;
113
+ sortId: string;
114
+ getValue?: (row: T) => any;
115
+ };
116
+ export declare const useSort: <T>(p: {
117
+ fa?: boolean;
118
+ sorts: I_table_sort<T>[];
119
+ rows: any[];
120
+ onChangeRows?: (rows: any) => void;
121
+ onChangeSort?: (sorts: I_table_sort<T>[]) => Promise<boolean | undefined>;
122
+ }) => {
123
+ sorts: I_table_sort<T>[];
124
+ setSorts: import("react").Dispatch<import("react").SetStateAction<I_table_sort<T>[]>>;
125
+ renderSortButton: (attrs?: any, limitTo?: string) => import("react/jsx-runtime").JSX.Element;
126
+ getSortedRows: (rows: T[]) => T[];
127
+ changeSort: (sortId: string, changeObject: Partial<I_table_sort<T>>) => void;
128
+ changeSorts: (sorts: I_table_sort<T>[]) => Promise<void>;
129
+ };
130
+ export type I_table_paging = {
131
+ serverSide?: boolean;
132
+ number: number;
133
+ size: number;
134
+ length?: number;
135
+ sizes?: number[];
136
+ };
137
+ export type I_pagingHook<T> = {
138
+ render: () => ReactNode;
139
+ getPagedRows: (rows: T[]) => T[];
140
+ changePaging: (obj: Partial<I_table_paging>) => void;
141
+ };
142
+ export declare const usePaging: <T>(p: {
143
+ rows: T[];
144
+ paging?: I_table_paging;
145
+ onChange?: (newPaging: I_table_paging) => void;
146
+ }) => I_pagingHook<T>;
147
+ export type I_table_filter_saved = {
148
+ name: string;
149
+ data: any;
150
+ };
151
+ export type I_table_columns_filter = {
152
+ onChange?: (newFilters: I_table_columns_filter_item[]) => boolean;
153
+ getSavedItems?: () => Promise<{
154
+ name: string;
155
+ data: any;
156
+ }[]>;
157
+ setSavedItems?: (savedItems: {
158
+ name: string;
159
+ data: any;
160
+ }[]) => Promise<boolean>;
161
+ items?: I_table_columns_filter_item[];
162
+ after?: () => ReactNode;
163
+ };
164
+ export type I_table_form_filter = {
165
+ onChange?: (obj: any) => boolean;
166
+ getSavedItems?: () => Promise<{
167
+ name: string;
168
+ data: any;
169
+ }[]>;
170
+ setSavedItems?: (saved: {
171
+ name: string;
172
+ data: any;
173
+ }[]) => Promise<boolean>;
174
+ items?: I_formInput<any>[];
175
+ value?: any;
176
+ };
177
+ export type I_table_columns_filter_item = {
178
+ columnId: string;
179
+ value: any;
180
+ operator?: 'less' | 'lessequal' | 'more' | 'moreequal' | 'equal' | 'notEqual' | 'contain' | 'notContain';
181
+ id: string;
182
+ };
package/index.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
11
  import { createContext, createRef, Fragment, useContext, useEffect, useRef, useState } from "react";
12
- import AIOInput, { AISelect } from "aio-input";
12
+ import AIOInput, { AICheckbox, AIFormInput, AINumber, AIRadio, AISelect, AIText, AITime, SuggestionInput, useForm } 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";
@@ -19,7 +19,7 @@ const Provider = (p) => _jsx(Context.Provider, { value: p.value, children: p.chi
19
19
  const useProvider = () => useContext(Context);
20
20
  const AIOTable = (props) => {
21
21
  const popup = usePopup();
22
- let [dom] = useState(createRef());
22
+ const fileClass = new UT.FileClass();
23
23
  let [searchValue, setSearchValue] = useState('');
24
24
  const [searchColumns, setSearchColumns] = useState([]);
25
25
  const [excelColumns, setExcelColumns] = useState([]);
@@ -32,7 +32,7 @@ const AIOTable = (props) => {
32
32
  const getRowsIndexDic = () => rowsIndexDicRef.current;
33
33
  const propsRef = useRef(props);
34
34
  propsRef.current = props;
35
- const pagingHook = UT.usePaging({ rows: props.value, paging: props.paging, onChange: props.onChangePaging });
35
+ const pagingHook = usePaging({ rows: props.value, paging: props.paging, onChange: props.onChangePaging });
36
36
  const getColumnOption = (key, cellDetails) => {
37
37
  if (key === 'id') {
38
38
  return cellDetails.column.id;
@@ -104,27 +104,13 @@ const AIOTable = (props) => {
104
104
  }
105
105
  return sorts;
106
106
  };
107
- const sortHook = UT.useSort({
107
+ const sortHook = useSort({
108
108
  fa: props.fa,
109
109
  sorts: [],
110
110
  rows: propsRef.current.value,
111
111
  onChangeRows: props.onChange,
112
112
  onChangeSort: props.onChangeSort,
113
113
  });
114
- const filterHook = UT.useFilter({
115
- columns: filterColumns,
116
- filter: props.filter || { onChange: () => { } },
117
- fa: props.fa,
118
- columnOption: {
119
- text: (column) => getColumnOption('title', tableHook.getCellDetail({ column })),
120
- id: (column) => getColumnOption('id', tableHook.getCellDetail({ column })),
121
- type: (column) => getColumnOption('type', tableHook.getCellDetail({ column })) || 'text',
122
- options: (column) => {
123
- const filter = getColumnOption('filter', tableHook.getCellDetail({ column }));
124
- return filter === null || filter === void 0 ? void 0 : filter.options;
125
- }
126
- }
127
- });
128
114
  function getColumns() {
129
115
  let { columns = [] } = props;
130
116
  let searchColumns = [], excelColumns = [], filterColumns = [], toggleColumns = [];
@@ -225,7 +211,7 @@ const AIOTable = (props) => {
225
211
  list.push(json);
226
212
  }
227
213
  }
228
- UT.ExportToExcel(list, { promptText: typeof props.excel === 'string' ? props.excel : 'Inter Excel File Name' });
214
+ fileClass.ExportToExcel(list, { promptText: typeof props.excel === 'string' ? props.excel : 'Inter Excel File Name' });
229
215
  }
230
216
  function getSearchedRows(rows) {
231
217
  if (props.onSearch !== true) {
@@ -271,15 +257,22 @@ const AIOTable = (props) => {
271
257
  }
272
258
  }
273
259
  let ROWS = getRows();
274
- const { gap = [0, 1] } = props;
275
- let attrs = UT.AddToAttrs(props.attrs, { className: ['aio-table', props.className], style: Object.assign({ gap: gap[1] }, props.style), attrs: { ref: dom } });
276
260
  const context = {
277
- rootProps: props, excelColumns, filterColumns, tableHook, sortHook, ROWS, toggleColumns, filterHook,
261
+ rootProps: props, excelColumns, filterColumns, tableHook, sortHook, ROWS, toggleColumns, pagingHook,
278
262
  getRowsIndexDic, add, remove, search, exportToExcel, DragColumns, getIcon, popup, getColumnOption
279
263
  };
280
- return (_jsxs(Provider, { value: context, children: [_jsxs("div", Object.assign({}, attrs, { children: [_jsx(TableToolbar, {}), !!props.filter && filterHook.renderTags(), _jsxs("div", { className: 'aio-table-unit aio-table-scroll', style: { gap: gap[1] }, children: [_jsx(TableHeader, {}), _jsx(TableRows, {})] }), pagingHook.render()] })), popup.render()] }));
264
+ return (_jsxs(Provider, { value: context, children: [_jsx(AIOTableComponent, Object.assign({}, props)), popup.render()] }));
281
265
  };
282
266
  export default AIOTable;
267
+ const AIOTableComponent = (props) => {
268
+ const { pagingHook, rootProps } = useProvider();
269
+ const { formFilter, columnsFilter } = rootProps;
270
+ let [dom] = useState(createRef());
271
+ const { gap = [0, 1] } = props;
272
+ let attrs = UT.AddToAttrs(props.attrs, { className: ['aio-table', props.className], style: Object.assign({ gap: gap[1] }, props.style), attrs: { ref: dom } });
273
+ 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()] })));
275
+ };
283
276
  const TableRows = () => {
284
277
  let { ROWS, rootProps } = useProvider();
285
278
  let { rowOption = {}, rowsTemplate, placeholder = 'there is not any items' } = rootProps;
@@ -317,13 +310,13 @@ const TableRows = () => {
317
310
  const { gap = [0, 1] } = rootProps;
318
311
  return _jsx("div", { className: 'aio-table-rows', style: { gap: gap[1] }, children: content });
319
312
  };
320
- const TableToolbar = () => {
321
- let { add, exportToExcel, search, rootProps, excelColumns, toggleColumns, getIcon, sortHook, getColumnOption, tableHook, filterHook } = useProvider();
322
- let { toolbarAttrs, toolbar, onAdd, onSearch, value, onChangeColumns, columns = [] } = rootProps;
313
+ 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;
323
316
  const columnsRef = useRef(columns);
324
317
  columnsRef.current = columns;
325
318
  toolbarAttrs = UT.AddToAttrs(toolbarAttrs, { className: 'aio-table-toolbar' });
326
- if (!onAdd && !toolbar && !onSearch && !sortHook.sorts.length && !excelColumns.length && !toggleColumns.length && !rootProps.filter) {
319
+ if (!onAdd && !toolbar && !onSearch && !sortHook.sorts.length && !excelColumns.length && !toggleColumns.length && !rootProps.columnsFilter && !rootProps.formFilter) {
327
320
  return null;
328
321
  }
329
322
  function getAddText() {
@@ -338,21 +331,23 @@ const TableToolbar = () => {
338
331
  const column = columns.find((o) => o.id === columnId);
339
332
  return getColumnOption(key, tableHook.getCellDetail({ column }));
340
333
  };
341
- return (_jsxs("div", Object.assign({}, toolbarAttrs, { children: [toolbar && _jsx("div", { className: 'aio-table-toolbar-content', children: typeof toolbar === 'function' ? toolbar() : toolbar }), !!rootProps.filter && filterHook.renderButton(), !!onSearch &&
342
- _jsx("div", { className: 'aio-table-search', children: _jsx(AIOInput, { type: 'text', onChange: (value) => search(value), after: getIcon('mdiMagnify', 0.7) }) }), !!sortHook.sorts.length &&
343
- _jsx("div", { className: 'aio-table-toolbar-button aio-table-sort-button', children: sortHook.renderSortButton() }), !!excelColumns.length && _jsx("div", { className: 'aio-table-toolbar-button aio-table-excel-button', onClick: () => exportToExcel(), children: getIcon('mdiFileExcel', 0.8) }), !!toggleColumns.length &&
344
- _jsx("div", { className: 'aio-table-toolbar-button aio-table-toggle-button', children: _jsx(AISelect, { text: getIcon('mdiEye', 0.8), justify: true, hideTags: true, options: toggleColumns.map((o) => (Object.assign(Object.assign({}, o), { show: true }))), caret: false, option: {
345
- text: (column) => getColumnOptionWrapper(column.id, 'title'),
346
- checked: (column) => getColumnOptionWrapper(column.id, 'show'),
347
- onClick: (column) => {
348
- if (!onChangeColumns) {
349
- return;
350
- }
351
- const columns = columnsRef.current || [];
352
- onChangeColumns(columns.map((o) => column.id === o.id ? Object.assign(Object.assign({}, o), { show: !getColumnOptionWrapper(o.id, 'show') }) : o));
353
- },
354
- close: () => false
355
- } }) }), !!onAdd && _jsx("div", { className: 'aio-table-toolbar-button aio-table-add-button', onClick: () => add(), children: getAddText() })] })));
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 &&
335
+ _jsx(AISelect, { popover: {
336
+ header: { title: fa ? 'نمایش ستون ها' : 'Show Columns', onClose: false },
337
+ headerAttrs: { className: 'aio-table-dropdown-header' },
338
+ 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'),
342
+ onClick: (column) => {
343
+ if (!onChangeColumns) {
344
+ return;
345
+ }
346
+ const columns = columnsRef.current || [];
347
+ onChangeColumns(columns.map((o) => column.id === o.id ? Object.assign(Object.assign({}, o), { show: !getColumnOptionWrapper(o.id, 'show') }) : o));
348
+ },
349
+ close: () => false
350
+ } }), !!onAdd && _jsx("div", { className: 'aio-table-toolbar-button aio-table-add-button', onClick: () => add(), children: getAddText() })] })));
356
351
  };
357
352
  const TableHeader = () => {
358
353
  let { rootProps, getColumnOption, tableHook } = useProvider();
@@ -509,7 +504,7 @@ const useTable = (getProps, getPaging, getColumnOption) => {
509
504
  const res = Object.assign({ column: {}, row: {}, rowIndex: 0, isFirst: false, isLast: false, date: [], change: () => { } }, v);
510
505
  const value = getColumnOption('value', res);
511
506
  const jalali = getColumnOption('jalali', res);
512
- const date = res.column.type === 'date' ? new AIODate().toArray(getCellValue(res, value), jalali) : [];
507
+ const date = res.column.type === 'date' ? new AIODate().toArray(getCellValue(res, value, jalali)) : [];
513
508
  return Object.assign(Object.assign(Object.assign({}, res), { date }), v);
514
509
  }
515
510
  const getCellAttrs = (cellDetail, cellValue, isOdd, striped) => {
@@ -555,3 +550,668 @@ const useTable = (getProps, getPaging, getColumnOption) => {
555
550
  };
556
551
  return { getCellValue, getCellAttrs, getTitleAttrs, getRowAttrs, changeCell, getCellDetail };
557
552
  };
553
+ export const useSort = (p) => {
554
+ let [sorts, setSorts] = useState(p.sorts);
555
+ const getIconRef = useRef(new UT.GetSvg().getIcon);
556
+ const isInitSortExecutedRef = useRef(false);
557
+ const getSortedRows = (rows) => {
558
+ if (isInitSortExecutedRef.current) {
559
+ return rows;
560
+ }
561
+ if (p.onChangeSort) {
562
+ return rows;
563
+ }
564
+ let activeSorts = sorts.filter((sort) => sort.active !== false);
565
+ if (!activeSorts.length || !rows.length) {
566
+ return rows;
567
+ }
568
+ isInitSortExecutedRef.current = true;
569
+ let sortedRows = sortRows(rows, activeSorts);
570
+ if (p.onChangeRows) {
571
+ p.onChangeRows(sortedRows);
572
+ }
573
+ return sortedRows;
574
+ };
575
+ const sortRows = (rows, sorts) => {
576
+ if (!rows) {
577
+ return [];
578
+ }
579
+ if (!sorts || !sorts.length) {
580
+ return rows;
581
+ }
582
+ return rows.sort((a, b) => {
583
+ for (let i = 0; i < sorts.length; i++) {
584
+ let { dir, getValue } = sorts[i];
585
+ if (!getValue) {
586
+ return 0;
587
+ }
588
+ let aValue = getValue(a), bValue = getValue(b);
589
+ if (aValue < bValue) {
590
+ return -1 * (dir === 'dec' ? -1 : 1);
591
+ }
592
+ if (aValue > bValue) {
593
+ return 1 * (dir === 'dec' ? -1 : 1);
594
+ }
595
+ if (i === sorts.length - 1) {
596
+ return 0;
597
+ }
598
+ }
599
+ return 0;
600
+ });
601
+ };
602
+ const changeSort = (sortId, changeObject) => {
603
+ let newSorts = sorts.map((sort) => {
604
+ if (sort.sortId === sortId) {
605
+ let newSort = Object.assign(Object.assign({}, sort), changeObject);
606
+ return newSort;
607
+ }
608
+ return sort;
609
+ });
610
+ changeSorts(newSorts);
611
+ };
612
+ const changeSorts = (sorts) => __awaiter(void 0, void 0, void 0, function* () {
613
+ if (p.onChangeSort) {
614
+ let res = yield p.onChangeSort(sorts);
615
+ if (res !== false) {
616
+ setSorts(sorts);
617
+ }
618
+ }
619
+ else {
620
+ setSorts(sorts);
621
+ let activeSorts = sorts.filter((sort) => sort.active !== false);
622
+ if (activeSorts.length && !!p.onChangeRows) {
623
+ p.onChangeRows(sortRows(p.rows, activeSorts));
624
+ }
625
+ }
626
+ });
627
+ const renderSortArrow = (option) => {
628
+ let { dir = 'dec', sortId } = option;
629
+ return (_jsx("div", { className: 'aio-sort-arrow', onClick: (e) => {
630
+ e.stopPropagation();
631
+ if (!sortId) {
632
+ return;
633
+ }
634
+ changeSort(sortId, { dir: dir === 'dec' ? 'inc' : 'dec' });
635
+ }, children: getIconRef.current(dir === 'dec' ? 'mdiArrowDown' : 'mdiArrowUp', 0.8) }));
636
+ };
637
+ const renderSortButton = (attrs, limitTo) => {
638
+ if (!sorts.length) {
639
+ return null;
640
+ }
641
+ const Attrs = UT.AddToAttrs(attrs, { className: 'aio-sort-button' });
642
+ return (_jsx(AISelect, { caret: false, options: sorts, justify: true, option: {
643
+ text: (option) => option.title, checked: (option) => !!option.active, close: () => false, value: (option) => option.sortId,
644
+ after: (option) => renderSortArrow(option),
645
+ onClick: (option) => changeSort(option.sortId, { active: !option.active })
646
+ }, popover: {
647
+ header: { title: p.fa ? 'مرتب سازی' : 'Sort', onClose: false },
648
+ headerAttrs: { className: 'aio-sort-header' },
649
+ limitTo: limitTo || '.aio-table'
650
+ }, attrs: Attrs, text: getIconRef.current('mdiSort', 0.7), onSwap: (newSorts) => changeSorts(newSorts) }, 'sortbutton'));
651
+ };
652
+ return { sorts, setSorts, renderSortButton, getSortedRows, changeSort, changeSorts };
653
+ };
654
+ export const usePaging = (p) => {
655
+ const timeoutRef = useRef(undefined);
656
+ const startRef = useRef(undefined);
657
+ const endRef = useRef(undefined);
658
+ const pagesRef = useRef(undefined);
659
+ const getPaging = (paging) => {
660
+ return paging ? fix(paging) : undefined;
661
+ };
662
+ function fix(paging) {
663
+ if (typeof p.onChange !== 'function') {
664
+ alert('aio-table error => in type table you set paging but forget to set onChangePaging function prop to aio input');
665
+ return { number: 0, size: 0 };
666
+ }
667
+ let { number, size = 20, length = 0, sizes = [1, 5, 10, 15, 20, 30, 50, 70, 100], serverSide } = paging;
668
+ if (!serverSide) {
669
+ length = p.rows.length;
670
+ }
671
+ if (sizes.indexOf(size) === -1) {
672
+ size = sizes[0];
673
+ }
674
+ let pages = Math.ceil(length / size);
675
+ number = number > pages ? pages : number;
676
+ number = number < 1 ? 1 : number;
677
+ let start = number - 3, end = number + 3;
678
+ startRef.current = start;
679
+ endRef.current = end;
680
+ pagesRef.current = pages;
681
+ return Object.assign(Object.assign({}, paging), { length, number, size, sizes });
682
+ }
683
+ const changePaging = (obj) => {
684
+ const paging = getPaging(p.paging);
685
+ if (!paging) {
686
+ return;
687
+ }
688
+ let newPaging = fix(Object.assign(Object.assign({}, paging), obj));
689
+ if (p.onChange) {
690
+ if (newPaging.serverSide) {
691
+ clearTimeout(timeoutRef.current);
692
+ timeoutRef.current = setTimeout(() => {
693
+ //be khatere fahme payine typescript majbooram dobare in shart ro bezanam
694
+ if (p.onChange) {
695
+ p.onChange(newPaging);
696
+ }
697
+ }, 800);
698
+ }
699
+ else {
700
+ p.onChange(newPaging);
701
+ }
702
+ }
703
+ };
704
+ const getPagedRows = (rows) => {
705
+ const paging = getPaging(p.paging);
706
+ if (!paging || paging.serverSide) {
707
+ return rows;
708
+ }
709
+ const { size, number } = paging;
710
+ return rows.slice((number - 1) * size, number * size);
711
+ };
712
+ function changeSizeButton(sizes, size) {
713
+ if (!sizes.length) {
714
+ return null;
715
+ }
716
+ return (_jsx(AISelect, { attrs: { className: 'aio-paging-button aio-paging-size' }, value: size, options: sizes, option: { text: 'option', value: 'option' }, justify: true, onChange: (value) => changePaging({ size: value }), popover: { fitHorizontal: true } }));
717
+ }
718
+ const render = () => {
719
+ const paging = getPaging(p.paging);
720
+ if (!paging) {
721
+ return null;
722
+ }
723
+ if (!p.rows.length) {
724
+ return null;
725
+ }
726
+ let { number, size, sizes } = paging;
727
+ let buttons = [];
728
+ let isFirst = true;
729
+ for (let i = startRef.current; i <= endRef.current; i++) {
730
+ if (i < 1 || i > pagesRef.current) {
731
+ buttons.push(_jsx("button", { className: 'aio-paging-button aio-paging-button-hidden', children: i }, i));
732
+ }
733
+ else {
734
+ let index;
735
+ if (isFirst) {
736
+ index = 1;
737
+ isFirst = false;
738
+ }
739
+ else if (i === Math.min(endRef.current, pagesRef.current)) {
740
+ index = pagesRef.current;
741
+ }
742
+ else {
743
+ index = i;
744
+ }
745
+ buttons.push(_jsx("button", { className: 'aio-paging-button' + (index === number ? ' active' : ''), onClick: () => changePaging({ number: index }), children: index }, index));
746
+ }
747
+ }
748
+ return (_jsxs("div", { className: 'aio-paging', children: [buttons, changeSizeButton(sizes || [], size)] }));
749
+ };
750
+ return { render, getPagedRows, changePaging };
751
+ };
752
+ const FilterContext = createContext({});
753
+ const FilterContextProvider = (props) => _jsx(FilterContext.Provider, { value: props.value, children: props.children });
754
+ const useFilterContext = () => useContext(FilterContext);
755
+ const useFilter = () => {
756
+ const { rootProps } = useProvider();
757
+ const { formFilter, columnsFilter } = rootProps;
758
+ const { value = {}, items = [], onChange = () => { } } = formFilter || {};
759
+ const trans = (key) => {
760
+ const { fa } = rootProps;
761
+ const dic = {
762
+ 'less': fa ? 'کوچک تر از' : 'less than',
763
+ 'lessequal': fa ? 'کوچک تر مساوی' : 'equal or less than',
764
+ 'more': fa ? 'بزرگتر از' : 'more than',
765
+ 'moreequal': fa ? 'بزرگتر مساوی' : 'equal or more than',
766
+ 'equal': fa ? 'برابر' : 'equal',
767
+ 'notEqual': fa ? 'مخالف' : 'not equal',
768
+ 'contain': fa ? 'شامل باشد' : 'contain',
769
+ 'notContain': fa ? 'شامل نباشد' : 'not contain',
770
+ 'add': fa ? 'افزودن' : 'Add',
771
+ 'save': fa ? 'ذخیره' : 'Save',
772
+ 'edit': fa ? 'ویرایش' : 'Edit',
773
+ 'filters': fa ? 'افزودن فیلتر' : 'Add Filter',
774
+ 'remove': fa ? 'حذف' : 'Remove',
775
+ 'activate': fa ? 'اعمال' : 'Activate',
776
+ 'saved filters': fa ? 'مجموعه فیلتر های ذخیره شده' : 'Saved Filters',
777
+ 'current filters': fa ? 'فیلتر های جاری' : 'Current Filter',
778
+ 'remove saved filter': fa ? 'حذف فیلتر ذخیره شده' : 'Remove saved filter',
779
+ 'remove confirm': fa ? 'از حذف این آیتم اطمینان دارید؟' : 'are you sure to remove this item?',
780
+ 'cansel': fa ? 'لغو' : 'Cansel',
781
+ 'activate saved filter': fa ? 'اعمال فیلتر ذخیره شده' : 'activate saved filter',
782
+ 'activate confirm': fa ? 'از فعالسازی این آیتم اطمینان دارید؟' : 'are you sure to activate this item?',
783
+ 'saved empty': fa ? "مجموعه فیلتر ذخیره شده ای موجود نیست" : "There is not any saved filters",
784
+ 'inter filter name': fa ? 'نام فیلتر را برای ذخیره وارد کنید' : 'please inter filter name',
785
+ 'save filter': fa ? 'ذخیره فیلتر' : 'Save Filter'
786
+ };
787
+ return dic[key];
788
+ };
789
+ const popup = usePopup({ rtl: !!rootProps.fa });
790
+ 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
+ const renderButton = (attrs) => {
800
+ return (_jsxs(FilterContextProvider, { value: { trans, popup, filterDataHook, form, type }, children: [_jsx(FilterButton, { attrs: attrs }), popup.render()] }));
801
+ };
802
+ 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()] }));
804
+ };
805
+ return { renderButton, renderTags };
806
+ };
807
+ const FilterButton = ({ attrs }) => {
808
+ const { popup, trans } = useFilterContext();
809
+ const openModal = () => {
810
+ popup.addModal({
811
+ header: { title: trans('filters') },
812
+ position: 'fullscreen', body: _jsx(FilterModal, {}),
813
+ backdropAttrs: { className: 'aio-filter-modal aio-filter-modal-size' }
814
+ });
815
+ };
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) })));
818
+ };
819
+ const FilterColumnsTags = ({ filterItems, remove, wrap }) => {
820
+ const { filterDataHook } = useFilterContext();
821
+ const { filterColumns } = useProvider();
822
+ const getTags = () => {
823
+ var _a, _b, _c;
824
+ const res = [];
825
+ for (let i = 0; i < filterItems.length; i++) {
826
+ const filterItem = filterItems[i];
827
+ const { columnId, value } = filterItem;
828
+ if (value === undefined || value === '' || !columnId) {
829
+ continue;
830
+ }
831
+ const column = filterColumns.find((o) => o.id === columnId);
832
+ if (!column) {
833
+ continue;
834
+ }
835
+ const { type = 'text' } = column;
836
+ let valuePresent = value;
837
+ const options = ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.options) || [];
838
+ if (type === 'multiSelect') {
839
+ if (!value || !value.length) {
840
+ continue;
841
+ }
842
+ const texts = options.filter((o) => value.indexOf(o.value) !== -1).map((o) => o.text);
843
+ valuePresent = texts.join(' | ');
844
+ }
845
+ else if (type === 'select') {
846
+ const option = options.find((o) => o.value === value);
847
+ valuePresent = (option === null || option === void 0 ? void 0 : option.text) || '';
848
+ }
849
+ else if (type === 'date') {
850
+ 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;
852
+ if (dateUnit === 'month') {
853
+ valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}', jalali);
854
+ }
855
+ else if (dateUnit === 'day') {
856
+ valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}/{day}', jalali);
857
+ }
858
+ else if (dateUnit === 'hour') {
859
+ valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}/{day} {hour}:00 }', jalali);
860
+ }
861
+ else if (dateUnit === 'minute') {
862
+ valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}/{day} {hour}:{minute}', jalali);
863
+ }
864
+ }
865
+ else if (type === 'number') {
866
+ valuePresent = UT.SplitNumber(valuePresent);
867
+ }
868
+ else if (type === 'checkbox') {
869
+ valuePresent = '';
870
+ }
871
+ res.push(_jsx(FilterTag, { column: column, filterItem: filterItem, valuePresent: valuePresent, onRemove: remove ? () => filterDataHook.removeFilterItem(filterItem) : undefined }, filterItem.id));
872
+ }
873
+ return res;
874
+ };
875
+ if (!filterItems.length) {
876
+ return null;
877
+ }
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 }));
883
+ };
884
+ const FilterTag = ({ filterItem, valuePresent, column, onRemove }) => {
885
+ var _a;
886
+ const { trans } = useFilterContext();
887
+ 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)] }));
889
+ };
890
+ const SaveConfirm = ({ onSubmit }) => {
891
+ 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') })] })] }));
907
+ };
908
+ const FilterSaves = () => {
909
+ const { trans, filterDataHook } = useFilterContext();
910
+ const saves = filterDataHook.getSaves();
911
+ if (!saves.length) {
912
+ return (_jsx("div", { className: "af-collections-empty", children: trans('saved empty') }));
913
+ }
914
+ return (_jsx("div", { className: "af-filter-collections", children: saves.map((o) => _jsx(FilterSave, { item: o }, o.name)) }));
915
+ };
916
+ const FilterSave = ({ item }) => {
917
+ const { rootProps } = useProvider();
918
+ const { trans, filterDataHook, type } = useFilterContext();
919
+ const { fa } = rootProps;
920
+ if (!item.name) {
921
+ return null;
922
+ }
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 });
925
+ const remove_layout = () => {
926
+ const attrs = { className: "af-collection-remove", onClick: () => filterDataHook.removeSave(item), style: { [fa ? 'right' : 'left']: -4 } };
927
+ return (_jsx("div", Object.assign({}, attrs, { children: _jsx(FilterRemoveIcon, {}) })));
928
+ };
929
+ const activate_layout = () => {
930
+ return (_jsxs("div", { className: "aio-filter-add-button", onClick: () => filterDataHook.activeSave(item), children: [_jsx(FilterActiveIcon, {}), " ", trans('activate')] }));
931
+ };
932
+ 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
+ }
939
+ };
940
+ return (_jsxs("div", { className: "af-collection", children: [header_layout(), " ", body_layout()] }));
941
+ };
942
+ const FilterModal = () => {
943
+ const { rootProps } = useProvider();
944
+ const { trans } = useFilterContext();
945
+ const { fa, columnsFilter, formFilter } = rootProps;
946
+ const { getSavedItems } = columnsFilter || formFilter || {};
947
+ 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, {})] }));
949
+ };
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()] }));
951
+ };
952
+ const CurrentFilters = () => {
953
+ const { rootProps } = useProvider();
954
+ const { filterDataHook, trans, form, type } = useFilterContext();
955
+ const { columnsFilter, formFilter } = rootProps;
956
+ const canSave = (!!columnsFilter && !!columnsFilter.setSavedItems) || (!!formFilter && !!formFilter.setSavedItems);
957
+ 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] }));
960
+ };
961
+ const CurrentFilter = ({ filterItem }) => {
962
+ const { operator, columnId, value } = filterItem;
963
+ const { filterDataHook, trans } = useFilterContext();
964
+ const { filterColumns } = useProvider();
965
+ const [column] = useState(getColumn);
966
+ const [operators, setOperators] = useState(getOperators);
967
+ function getColumn() { return filterColumns.find((o) => o.id === columnId); }
968
+ useEffect(() => {
969
+ setOperators(getOperators());
970
+ }, [JSON.stringify(filterItem.columnId)]);
971
+ function getOperators() {
972
+ if (!column) {
973
+ return [];
974
+ }
975
+ const res = [];
976
+ const operators = ['less', 'more', 'equal', 'notEqual', 'contain', 'notContain'];
977
+ const dic = {
978
+ text: { contain: true, notContain: true, equal: true, notEqual: true },
979
+ number: { less: true, more: true, lessequal: true, moreequal: true, equal: true, notEqual: true },
980
+ date: { less: true, more: true, lessequal: true, moreequal: true, equal: true, notEqual: true },
981
+ select: { equal: true, notEqual: true },
982
+ multiSelect: { contain: true, notContain: true },
983
+ checkbox: {}
984
+ };
985
+ for (let i = 0; i < operators.length; i++) {
986
+ const o = operators[i];
987
+ if (!dic[column.type || 'text'][o]) {
988
+ continue;
989
+ }
990
+ res.push(operators[i]);
991
+ }
992
+ return res;
993
+ }
994
+ const changeValue = (newValue) => {
995
+ filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'value', value: newValue, column });
996
+ };
997
+ const getValueInput = () => {
998
+ if (!column) {
999
+ return null;
1000
+ }
1001
+ let { type = 'text' } = column;
1002
+ if (type === 'select') {
1003
+ return (_jsx(AISelect, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true })));
1004
+ }
1005
+ if (type === 'multiSelect') {
1006
+ return (_jsx(AIRadio, Object.assign({ multiple: true }, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true })));
1007
+ }
1008
+ if (type === 'text') {
1009
+ return _jsx(AIText, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true }));
1010
+ }
1011
+ if (type === 'checkbox') {
1012
+ return _jsx(AICheckbox, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true }));
1013
+ }
1014
+ if (type === 'number') {
1015
+ return _jsx(AINumber, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true, inputAttrs: { style: { letterSpacing: 4 } }, justify: true }));
1016
+ }
1017
+ if (type === 'date') {
1018
+ return _jsx(TimeInput, Object.assign({}, column.filterInput, { filterItem: filterItem, onChange: (value) => changeValue(value), column: column }));
1019
+ }
1020
+ };
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, {}) })] }) }));
1024
+ };
1025
+ const TimeInput = ({ filterItem, onChange, column }) => {
1026
+ var _a;
1027
+ const [unit] = useState(getUnit);
1028
+ function getUnit() {
1029
+ const { dateUnit = 'day' } = column.filterInput || {};
1030
+ const res = { year: true, month: true };
1031
+ if (dateUnit !== 'month') {
1032
+ res.day = true;
1033
+ if (dateUnit !== 'day') {
1034
+ res.hour = true;
1035
+ if (dateUnit !== 'hour') {
1036
+ res.minute = true;
1037
+ }
1038
+ }
1039
+ }
1040
+ return res;
1041
+ }
1042
+ const DATE = new AIODate();
1043
+ const jalali = column.jalali || ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.jalali);
1044
+ return (_jsx(AITime, { jalali: jalali, timeUnit: unit, value: filterItem.value, deSelect: true, onChange: (value) => onChange(value ? DATE.getTime(value) : undefined) }));
1045
+ };
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);
1050
+ const useFilterData = (popup, trans) => {
1051
+ const [activeName, setActiveName] = useState();
1052
+ const { filterColumns, rootProps } = useProvider();
1053
+ const { columnsFilter, formFilter } = rootProps;
1054
+ const [saves, setSaves] = useState([]);
1055
+ const savesRef = useRef(saves);
1056
+ savesRef.current = saves;
1057
+ const getSaves = () => savesRef.current;
1058
+ const [data, setData] = useState(getInitialData);
1059
+ function getInitialData() {
1060
+ if (columnsFilter) {
1061
+ return columnsFilter.items || [];
1062
+ }
1063
+ if (formFilter) {
1064
+ return {};
1065
+ }
1066
+ }
1067
+ const getData = () => dataRef.current;
1068
+ const dataRef = useRef(data);
1069
+ dataRef.current = data;
1070
+ 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);
1079
+ if (res === false) {
1080
+ return false;
1081
+ }
1082
+ }
1083
+ setData(newData);
1084
+ return true;
1085
+ });
1086
+ const changeSaves = (newSaves) => __awaiter(void 0, void 0, void 0, function* () {
1087
+ const { setSavedItems } = columnsFilter || formFilter || {};
1088
+ if (!setSavedItems) {
1089
+ return false;
1090
+ }
1091
+ const res = yield setSavedItems(newSaves);
1092
+ if (res === false) {
1093
+ return false;
1094
+ }
1095
+ setSaves(newSaves);
1096
+ return true;
1097
+ });
1098
+ const save = () => {
1099
+ popup.addModal({
1100
+ header: { title: trans('save filter') }, position: 'center',
1101
+ body: (_jsx(SaveConfirm, { onSubmit: (name) => __awaiter(void 0, void 0, void 0, function* () {
1102
+ if (!name) {
1103
+ return;
1104
+ }
1105
+ const data = dataRef.current;
1106
+ const saves = savesRef.current;
1107
+ const newSave = { name, data };
1108
+ const isExist = !!saves.find((o) => o.name === name);
1109
+ let newSaves = [];
1110
+ if (isExist) {
1111
+ newSaves = saves.map((o) => o.name === name ? newSave : o);
1112
+ }
1113
+ else {
1114
+ newSaves = [...saves, newSave];
1115
+ }
1116
+ const res = yield changeSaves(newSaves);
1117
+ if (res) {
1118
+ popup.removeModal();
1119
+ }
1120
+ }) })),
1121
+ backdropAttrs: { className: 'aio-filter-modal' }
1122
+ });
1123
+ };
1124
+ const removeSave = (saveItem) => {
1125
+ popup.addConfirm({
1126
+ title: trans('remove saved filter'),
1127
+ text: trans('remove confirm'),
1128
+ submitText: trans('remove'),
1129
+ 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' },
1133
+ onSubmit: () => __awaiter(void 0, void 0, void 0, function* () { return yield changeSaves(savesRef.current.filter((o) => o.name !== saveItem.name)); })
1134
+ });
1135
+ };
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 fetchSaves = () => __awaiter(void 0, void 0, void 0, function* () {
1160
+ const { getSavedItems } = columnsFilter || formFilter || {};
1161
+ if (!getSavedItems) {
1162
+ return;
1163
+ }
1164
+ const saves = yield getSavedItems();
1165
+ if (saves) {
1166
+ setSaves(saves);
1167
+ }
1168
+ });
1169
+ useEffect(() => { fetchSaves(); }, []);
1170
+ const getDefaultFilter = (column) => {
1171
+ const { type = 'text' } = column;
1172
+ const { options } = (column === null || column === void 0 ? void 0 : column.filterInput) || {};
1173
+ let value = '';
1174
+ if (type === 'select' && !!options && !!options.length) {
1175
+ value = options[0].value;
1176
+ }
1177
+ const operatorDic = {
1178
+ text: 'contain', number: 'equal', date: 'equal', select: 'equal', multiSelect: 'contain', checkbox: false
1179
+ };
1180
+ const operator = column ? (operatorDic[type] === false ? undefined : operatorDic[type]) : undefined;
1181
+ return { value, operator, columnId: column === null || column === void 0 ? void 0 : column.id, id: 'a' + UT.GetRandomNumber(10000000, 99999999) };
1182
+ };
1183
+ const changeColumnsFilterItem = (p) => {
1184
+ const { key, value, filterItem, column } = p;
1185
+ const columnsFilterItems = dataRef.current;
1186
+ let newFilterItem;
1187
+ if (!!column && key === 'columnId') {
1188
+ const defaultFilter = getDefaultFilter(column);
1189
+ if (defaultFilter === false) {
1190
+ return;
1191
+ }
1192
+ newFilterItem = Object.assign(Object.assign({}, defaultFilter), { [key]: value });
1193
+ }
1194
+ else {
1195
+ newFilterItem = Object.assign(Object.assign({}, filterItem), { [key]: value });
1196
+ }
1197
+ const newFilterItems = columnsFilterItems.map((o) => o.id === filterItem.id ? newFilterItem : o);
1198
+ changeData(newFilterItems);
1199
+ };
1200
+ const addColumnsFilterItem = () => {
1201
+ const column = filterColumns[0];
1202
+ if (!column) {
1203
+ return;
1204
+ }
1205
+ const defaultFilter = getDefaultFilter(column);
1206
+ if (defaultFilter === false) {
1207
+ return;
1208
+ }
1209
+ const columnsFilterItems = dataRef.current;
1210
+ changeData([...columnsFilterItems, defaultFilter]);
1211
+ };
1212
+ const removeFilterItem = (filterItem) => {
1213
+ const columnsFilterItems = dataRef.current;
1214
+ changeData(columnsFilterItems.filter((o) => !!o && (o.id !== filterItem.id)));
1215
+ };
1216
+ return { getSaves, getData, save, removeSave, removeFilterItem, changeColumnsFilterItem, activeName, activeSave, addColumnsFilterItem };
1217
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aio-table",
3
- "version": "12.0.1",
3
+ "version": "13.0.0",
4
4
  "description": "all in one table. tree mode , simple mode , tree mode, gantt mode , groupby mode, freeze mode.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -19,7 +19,9 @@
19
19
  "homepage": "https://github.com/mohammadFeiz/aio-table#readme",
20
20
  "dependencies": {
21
21
  "aio-input": "latest",
22
- "aio-utils": "latest"
22
+ "aio-utils": "latest",
23
+ "aio-popup":"latest",
24
+ "aio-date":"latest"
23
25
  },
24
26
  "devDependencies": {
25
27
  "react-scripts": "latest"