@inceptionbg/iui 2.0.8 → 2.0.10

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 (138) hide show
  1. package/dist/icons/index.d.ts +2 -2
  2. package/dist/icons/index.js +1 -1
  3. package/dist/index.d.ts +286 -259
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/iui.css +1 -1
  7. package/idea/GridTable/GridTable.tsx +119 -0
  8. package/idea/GridTable/gridTable.scss +42 -0
  9. package/{src/components → idea}/Table/Components/Print/CustomTablePrint.tsx +2 -2
  10. package/{src/components → idea}/Table/Components/Print/TablePrint.tsx +2 -2
  11. package/{src/components → idea}/Table/Components/SetTableFilter.tsx +1 -1
  12. package/{src/components → idea}/Table/Components/TableOptions.tsx +4 -4
  13. package/idea/{Table2 → Table}/Table.tsx +151 -281
  14. package/idea/Table/hooks/useDefaultTemplate.ts +20 -0
  15. package/{src/components → idea}/Table/hooks/useTableKeyboard.ts +1 -2
  16. package/idea/Table/hooks/useTableSelect.ts +11 -0
  17. package/package.json +1 -1
  18. package/src/assets/icons/index.ts +1 -1
  19. package/src/assets/icons/light/faClipboardCheck.ts +15 -0
  20. package/src/assets/icons/light/faHouse.ts +15 -15
  21. package/src/assets/icons/light/faIdBadge.ts +15 -15
  22. package/src/assets/icons/light/faPen.ts +15 -0
  23. package/src/components/Button/IconButton.tsx +3 -1
  24. package/src/components/Dialog/Dialog.tsx +59 -123
  25. package/src/components/Dialog/components/DialogFooter.tsx +92 -0
  26. package/src/components/Dialog/hooks/useDialogKeyboard.ts +6 -5
  27. package/src/components/Header/Header.tsx +1 -1
  28. package/src/components/Inputs/DateInput/DateInput.tsx +108 -102
  29. package/src/components/Inputs/DateInput/components/DatePartInput.tsx +7 -3
  30. package/src/components/Inputs/InputWrapper.tsx +6 -1
  31. package/src/components/Inputs/SearchInput.tsx +9 -4
  32. package/src/components/Inputs/Select2/Select.tsx +65 -30
  33. package/src/components/Inputs/Select2/select.scss +13 -14
  34. package/src/components/Inputs/Selects/components/SelectWrapper.tsx +4 -2
  35. package/src/components/Inputs/Selects/utils/selectStyles.ts +9 -12
  36. package/src/components/Menu/Menu.tsx +10 -2
  37. package/src/components/Menu/MenuItem.tsx +11 -10
  38. package/src/components/Menu/hooks/useMenuPosition.tsx +23 -6
  39. package/src/components/Pullover/Pullover.tsx +122 -59
  40. package/src/components/Table/Table.tsx +78 -342
  41. package/src/components/Table/components/edit/TableEditRow.tsx +69 -0
  42. package/src/components/Table/components/filters/FilterItem.tsx +15 -0
  43. package/src/components/Table/components/filters/TableFilters.tsx +125 -0
  44. package/src/components/Table/components/footer/TableFooter.tsx +128 -0
  45. package/src/components/Table/components/header/TableHeader.tsx +42 -0
  46. package/src/components/Table/components/header/TableHeaderRow.tsx +47 -0
  47. package/src/components/Table/components/items/TableItemActions.tsx +66 -0
  48. package/src/components/Table/components/select/TableSelect.tsx +49 -0
  49. package/src/components/Table/components/sort/TableSort.tsx +52 -0
  50. package/src/components/Table/contexts/TableContext.tsx +123 -0
  51. package/src/components/Table/hooks/localHooks/useLocalTableColumns.tsx +73 -0
  52. package/src/components/Table/hooks/localHooks/useLocalTableData.tsx +78 -0
  53. package/src/components/Table/hooks/localHooks/useLocalTableKeyboard.ts +173 -0
  54. package/src/components/Table/hooks/localHooks/useLocalTablePagination.ts +12 -0
  55. package/src/components/Table/hooks/useTableEdit.tsx +111 -0
  56. package/src/components/Table/hooks/useTableFilterFields.tsx +150 -0
  57. package/src/components/Table/hooks/useTablePagination.ts +16 -0
  58. package/src/components/Table/hooks/useTableSearch.ts +29 -0
  59. package/src/components/Table/hooks/useTableSort.ts +8 -0
  60. package/src/components/Tooltip/Tooltip.tsx +1 -1
  61. package/src/components/Wrappers/PageLayout.tsx +9 -12
  62. package/src/hooks/useGetFocusableElements.ts +42 -0
  63. package/src/hooks/useLocalPopoverControl.ts +38 -0
  64. package/src/hooks/usePopupControl.ts +13 -0
  65. package/src/index.ts +53 -39
  66. package/src/styles/components/_accordions.scss +1 -1
  67. package/src/styles/components/_badge.scss +4 -3
  68. package/src/styles/components/_card.scss +1 -1
  69. package/src/styles/components/_dialog.scss +8 -8
  70. package/src/styles/components/_input.scss +1 -1
  71. package/src/styles/components/_inputCheckbox.scss +1 -1
  72. package/src/styles/components/_inputDateTime.scss +2 -2
  73. package/src/styles/components/_inputRadio.scss +1 -1
  74. package/src/styles/components/_inputSelect.scss +6 -4
  75. package/src/styles/components/_menu-v2.scss +1 -1
  76. package/src/styles/components/_menu.scss +23 -15
  77. package/src/styles/components/_pullover.scss +74 -18
  78. package/src/styles/components/_table.scss +151 -142
  79. package/src/styles/components/_widget.scss +1 -1
  80. package/src/styles/variables/_bp.scss +1 -0
  81. package/src/styles/variables/_variables.scss +4 -2
  82. package/src/types/IKeyboard.ts +2 -1
  83. package/src/types/IMenu.ts +1 -0
  84. package/src/types/ISelect.ts +1 -0
  85. package/src/types/ITable.ts +87 -80
  86. package/src/utils/fileUtils.ts +3 -3
  87. package/src/utils/i18n/i18nIUICyrilic.ts +4 -0
  88. package/src/utils/i18n/i18nIUILatin.ts +3 -1
  89. package/src/utils/i18n/i18nIUIMe.ts +4 -0
  90. package/src/utils/{ObjectUtils.ts → objectUtils.ts} +8 -8
  91. package/src/utils/popupUtils.ts +82 -0
  92. package/src/utils/{TableUtils.ts → tableUtils.ts} +5 -5
  93. package/src/utils/{Toasts.ts → toasts.ts} +6 -6
  94. package/src/utils/{UrlUtils.ts → urlUtils.ts} +4 -4
  95. package/idea/Table2/Components/Columns/ColumnsList.tsx +0 -56
  96. package/idea/Table2/Components/Columns/SetColumnsList.tsx +0 -107
  97. package/idea/Table2/Components/Edit/ItemActionsMenu.tsx +0 -87
  98. package/idea/Table2/Components/Edit/ItemEditOptionsButtons.tsx +0 -32
  99. package/idea/Table2/Components/Edit/TableEditRow.tsx +0 -56
  100. package/idea/Table2/Components/FilterItem.tsx +0 -20
  101. package/idea/Table2/Components/Header/TableHeader.tsx +0 -35
  102. package/idea/Table2/Components/Header/TableHeaderRow.tsx +0 -37
  103. package/idea/Table2/Components/Print/CustomTablePrint.tsx +0 -119
  104. package/idea/Table2/Components/Print/TablePrint.tsx +0 -208
  105. package/idea/Table2/Components/SetSortList.tsx +0 -33
  106. package/idea/Table2/Components/SetTableFilter.tsx +0 -90
  107. package/idea/Table2/Components/TableFooter.tsx +0 -107
  108. package/idea/Table2/Components/TableOptions.tsx +0 -211
  109. package/idea/Table2/Components/Templates/TemplateCreate.tsx +0 -75
  110. package/idea/Table2/Components/Templates/TemplateCreateDefault.tsx +0 -45
  111. package/idea/Table2/Components/Templates/TemplateList.tsx +0 -167
  112. package/idea/Table2/Components/Templates/repo/TemplateRepo.ts +0 -51
  113. package/idea/Table2/_table.scss +0 -300
  114. package/idea/Table2/hooks/useDefaultTemplate.ts +0 -22
  115. package/idea/Table2/hooks/useTableKeyboard.ts +0 -115
  116. package/src/assets/icons/light/faPenField.ts +0 -15
  117. package/src/assets/icons/solid/faMagnifyingGlass.ts +0 -15
  118. package/src/components/Dialog/DeleteItemDialog.tsx +0 -52
  119. package/src/components/Dialog/hooks/useDialogObserver.ts +0 -21
  120. /package/{src/components → idea}/Table/Components/Columns/ColumnsList.tsx +0 -0
  121. /package/{src/components → idea}/Table/Components/Columns/SetColumnsList.tsx +0 -0
  122. /package/{src/components → idea}/Table/Components/Edit/ItemActionsMenu.tsx +0 -0
  123. /package/{src/components → idea}/Table/Components/Edit/ItemEditOptionsButtons.tsx +0 -0
  124. /package/{src/components → idea}/Table/Components/Edit/TableEditRow.tsx +0 -0
  125. /package/{src/components → idea}/Table/Components/FilterItem.tsx +0 -0
  126. /package/{src/components → idea}/Table/Components/Header/TableHeader.tsx +0 -0
  127. /package/{src/components → idea}/Table/Components/Header/TableHeaderRow.tsx +0 -0
  128. /package/{src/components → idea}/Table/Components/SetSortList.tsx +0 -0
  129. /package/{src/components → idea}/Table/Components/TableFooter.tsx +0 -0
  130. /package/{src/components → idea}/Table/Components/Templates/TemplateCreate.tsx +0 -0
  131. /package/{src/components → idea}/Table/Components/Templates/TemplateCreateDefault.tsx +0 -0
  132. /package/{src/components → idea}/Table/Components/Templates/TemplateList.tsx +0 -0
  133. /package/{src/components → idea}/Table/Components/Templates/repo/TemplateRepo.ts +0 -0
  134. /package/src/utils/{DateUtils.ts → dateUtils.ts} +0 -0
  135. /package/src/utils/{LocalStorageHelper.ts → localStorageHelper.ts} +0 -0
  136. /package/src/utils/{NumberUtils.ts → numberUtils.ts} +0 -0
  137. /package/src/utils/{RootDir.ts → rootDir.ts} +0 -0
  138. /package/src/utils/{StringUtils.ts → stringUtils.ts} +0 -0
@@ -0,0 +1,73 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { ITable, ITableColumn } from '../../../../types/ITable';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { Checkbox } from '../../../Inputs/Checkbox';
5
+
6
+ interface Props {
7
+ initialColumns: ITableColumn[];
8
+ hasSelect: boolean;
9
+ data: ITable['data'];
10
+ rowSelect: ITable['rowSelect'];
11
+ hasItemActions?: boolean;
12
+ }
13
+
14
+ export const useLocalTableColumns = ({
15
+ initialColumns,
16
+ hasSelect,
17
+ data,
18
+ rowSelect,
19
+ hasItemActions,
20
+ }: Props) => {
21
+ const [columns, setColumns] = useState<ITableColumn[]>([]);
22
+ const { t } = useTranslation();
23
+
24
+ useEffect(() => {
25
+ const activeColumns = initialColumns.filter(e => !e.hidden && !e.unavailable);
26
+
27
+ let newCols: ITableColumn[] = [];
28
+
29
+ // Select Column
30
+ if (hasSelect && rowSelect) {
31
+ const selectableData = data.filter(e => !e.disableSelect);
32
+ const selectedSome =
33
+ !!rowSelect.selectedRows.size &&
34
+ selectableData.some(e => !rowSelect.selectedRows.has(e.uuid));
35
+ const selectedAll = !!rowSelect.selectedRows.size && !selectedSome;
36
+
37
+ const selectColumn: ITableColumn = {
38
+ id: 'select',
39
+ label: (
40
+ <Checkbox
41
+ value={selectedSome ? 'middle' : selectedAll}
42
+ setValue={() => {
43
+ selectedAll
44
+ ? rowSelect.setSelectedRows(new Set<string>())
45
+ : rowSelect.setSelectedRows(oldValue => {
46
+ let newSet = new Set(oldValue);
47
+ selectableData.forEach(e => newSet.add(e.uuid!));
48
+ return newSet;
49
+ });
50
+ }}
51
+ />
52
+ ),
53
+ align: 'center',
54
+ className: 'select-col',
55
+ };
56
+
57
+ newCols.push(selectColumn);
58
+ }
59
+
60
+ newCols = newCols.concat(activeColumns);
61
+ hasItemActions &&
62
+ newCols.push({
63
+ id: 'actions',
64
+ label: t('Actions'),
65
+ align: 'center',
66
+ className: 'actions-col',
67
+ });
68
+
69
+ setColumns(newCols);
70
+ }, [initialColumns, hasSelect, data, rowSelect, hasItemActions, t]);
71
+
72
+ return { columns, setColumns };
73
+ };
@@ -0,0 +1,78 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { IPaginationControl, ITable, ITableDataItem } from '../../../../types/ITable';
3
+ import { Checkbox } from '../../../Inputs/Checkbox';
4
+ import { TableItemActions } from '../../components/items/TableItemActions';
5
+
6
+ interface Props {
7
+ initialData: ITableDataItem[];
8
+ controledPagination: boolean;
9
+ localPagination: IPaginationControl;
10
+ dataActions?: ITable['dataActions'];
11
+ rowSelect: ITable['rowSelect'];
12
+ }
13
+
14
+ export const useLocalTableData = ({
15
+ initialData,
16
+ controledPagination,
17
+ localPagination,
18
+ dataActions,
19
+ rowSelect,
20
+ }: Props) => {
21
+ const [data, setData] = useState<ITableDataItem[]>(initialData);
22
+
23
+ useEffect(() => {
24
+ const newData =
25
+ controledPagination || localPagination.limit <= 0
26
+ ? initialData
27
+ : initialData.slice(
28
+ localPagination.offset * localPagination.limit,
29
+ localPagination.offset * localPagination.limit + localPagination.limit
30
+ );
31
+
32
+ const additionalDataActions = dataActions?.actions?.filter(e => e.hasAccess) ?? [];
33
+ const withActions = Boolean(
34
+ dataActions?.edit?.hasAccess ||
35
+ dataActions?.delete?.hasAccess ||
36
+ additionalDataActions.length
37
+ );
38
+
39
+ const withAdditionalColumns = Boolean(rowSelect || withActions);
40
+ const finalData = !withAdditionalColumns
41
+ ? newData
42
+ : newData.map(e => {
43
+ if (rowSelect) {
44
+ e.cells.select = {
45
+ value: (
46
+ <Checkbox
47
+ value={rowSelect.selectedRows.has(e.uuid!)}
48
+ setValue={checked => {
49
+ rowSelect.setSelectedRows(oldSet => {
50
+ const newSet = new Set(oldSet);
51
+ checked ? newSet.add(e.uuid!) : newSet.delete(e.uuid!);
52
+ return newSet;
53
+ });
54
+ }}
55
+ disabled={e.disableSelect}
56
+ />
57
+ ),
58
+ unclickable: true,
59
+ };
60
+ }
61
+ if (dataActions) {
62
+ e.cells.actions = { value: <TableItemActions tableDataItem={e} /> };
63
+ }
64
+ return e;
65
+ });
66
+
67
+ setData(finalData);
68
+ }, [
69
+ controledPagination,
70
+ initialData,
71
+ localPagination.limit,
72
+ localPagination.offset,
73
+ rowSelect,
74
+ dataActions,
75
+ ]);
76
+
77
+ return { data };
78
+ };
@@ -0,0 +1,173 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { ITableDataItem } from '../../../../types/ITable';
3
+ import { IKeyboardAction } from '../../../../types/IKeyboard';
4
+ import { scrollToRow } from '../../../../utils/tableUtils';
5
+ import { useTableContext } from '../../contexts/TableContext';
6
+
7
+ export const useLocalTableKeyboard = () => {
8
+ const [focusedRow, setFocusedRow] = useState<ITableDataItem | null>(null);
9
+
10
+ const { keyboard, data, editable, dataActions, rowSelect, footer } = useTableContext();
11
+
12
+ useEffect(() => {
13
+ if (keyboard?.enabled) {
14
+ const isEditing = !!editable?.selectedItem;
15
+ const isAdding = !!editable?.isAdding;
16
+ const isEditDisabled = !editable || keyboard?.actions.editDisabled;
17
+ const isAddDisabled = !!editable?.addDisabled;
18
+ const isMoveDisabled = !!keyboard?.actions?.moveDisabled;
19
+ const isBulkAction =
20
+ dataActions?.hasItemActions &&
21
+ rowSelect?.selectedRows &&
22
+ rowSelect.selectedRows.size > 0;
23
+
24
+ const handleKeyDown = (event: KeyboardEvent) => {
25
+ const rowIndex = focusedRow
26
+ ? data.findIndex(row => row.uuid === focusedRow.uuid)
27
+ : -1;
28
+
29
+ const allActions: IKeyboardAction[] = [
30
+ {
31
+ code: 'ArrowDown',
32
+ disabled: isEditing || isAdding || isMoveDisabled,
33
+ onAction: () => {
34
+ const nextRow = rowIndex + 1;
35
+ if (nextRow < data.length) {
36
+ // rowIndex will be -1 if no row is selected so the next row will be 0
37
+ setFocusedRow(data[nextRow]);
38
+ scrollToRow(data[nextRow].uuid);
39
+ }
40
+ },
41
+ },
42
+ {
43
+ code: 'ArrowUp',
44
+ disabled: isEditing || isAdding || isMoveDisabled,
45
+ onAction: () => {
46
+ if (rowIndex !== 0) {
47
+ const prevRow = rowIndex > 0 ? rowIndex - 1 : data.length - 1;
48
+ setFocusedRow(data[prevRow]);
49
+ scrollToRow(data[prevRow].uuid);
50
+ }
51
+ },
52
+ },
53
+ {
54
+ code: 'KeyE',
55
+ ctrl: true,
56
+ disabled: isEditing || isEditDisabled || !focusedRow,
57
+ onAction: () => {
58
+ editable?.setSelectedItem(focusedRow?.item ?? null);
59
+ },
60
+ },
61
+ {
62
+ code: 'Enter',
63
+ disabled: isEditing || isAdding || !focusedRow?.onRowClick,
64
+ onAction: focusedRow?.onRowClick!,
65
+ },
66
+ {
67
+ code: 'Escape',
68
+ disabled: !focusedRow && !isAdding && !isEditing,
69
+ onAction: () =>
70
+ isAdding
71
+ ? editable?.setIsAdding(false)
72
+ : editable?.selectedItem
73
+ ? editable?.setSelectedItem?.(null)
74
+ : setFocusedRow(null),
75
+ },
76
+ {
77
+ code: 'Insert',
78
+ disabled: isAddDisabled || isAdding || isEditing,
79
+ onAction: () => {
80
+ editable?.setIsAdding(true);
81
+ setFocusedRow(null);
82
+ },
83
+ },
84
+ {
85
+ code: 'Delete',
86
+ disabled: isEditing || !keyboard?.actions.delete?.enabled || !focusedRow,
87
+ onAction: () =>
88
+ keyboard?.actions.delete?.onAction ??
89
+ keyboard?.actions.delete?.setItemToDeleteUuids(
90
+ isBulkAction ? Array.from(rowSelect.selectedRows) : [focusedRow!.uuid]
91
+ ),
92
+ },
93
+ {
94
+ code: 'ArrowLeft',
95
+ ctrl: true,
96
+ disabled: isEditing || isAdding,
97
+ onAction: () =>
98
+ footer!.paginationControl!.offset > 0 &&
99
+ footer!.paginationControl!.setOffset(footer!.paginationControl!.offset - 1),
100
+ },
101
+ {
102
+ code: 'ArrowRight',
103
+ ctrl: true,
104
+ disabled: isEditing || isAdding,
105
+ onAction: () => {
106
+ if (
107
+ footer?.noTotalRows
108
+ ? footer!.paginationControl!.limit <= footer!.totalRows!
109
+ : footer!.paginationControl!.offset + 1 <
110
+ Math.ceil(footer!.totalRows! / footer!.paginationControl!.limit)
111
+ ) {
112
+ footer!.paginationControl!.setOffset(
113
+ footer!.paginationControl!.offset + 1
114
+ );
115
+ }
116
+ },
117
+ },
118
+ {
119
+ code: 'Space',
120
+ disabled: !dataActions?.hasItemActions && !!focusedRow?.uuid,
121
+ onAction: () => {
122
+ const rowUuid = focusedRow?.uuid!;
123
+ const isRowSelected = rowSelect?.selectedRows.has(rowUuid);
124
+ rowSelect?.setSelectedRows(oldSet => {
125
+ const newSet = new Set(oldSet);
126
+ newSet[isRowSelected ? 'delete' : 'add'](rowUuid);
127
+ return newSet;
128
+ });
129
+ },
130
+ },
131
+ ];
132
+
133
+ allActions.forEach(action => {
134
+ if (
135
+ !action.disabled &&
136
+ action.code === event.code &&
137
+ !!action.ctrl === (event.ctrlKey || event.metaKey)
138
+ ) {
139
+ event.preventDefault();
140
+ event.stopPropagation();
141
+ if (
142
+ action.onBulkAction &&
143
+ dataActions?.hasItemActions &&
144
+ rowSelect?.selectedRows &&
145
+ rowSelect.selectedRows.size > 0
146
+ ) {
147
+ action.onBulkAction(Array.from(rowSelect.selectedRows));
148
+ } else {
149
+ action.onAction();
150
+ }
151
+ }
152
+ });
153
+ };
154
+
155
+ document.addEventListener('keydown', handleKeyDown);
156
+ return () => {
157
+ document.removeEventListener('keydown', handleKeyDown);
158
+ };
159
+ }
160
+ }, [
161
+ data,
162
+ editable,
163
+ keyboard,
164
+ dataActions?.hasItemActions,
165
+ focusedRow,
166
+ footer,
167
+ rowSelect,
168
+ ]);
169
+ return {
170
+ focusedRow,
171
+ // handleKeyDown,
172
+ };
173
+ };
@@ -0,0 +1,12 @@
1
+ import { useState } from 'react';
2
+
3
+ interface Props {
4
+ defaultLimit?: number;
5
+ }
6
+
7
+ export const useLocalTablePagination = ({ defaultLimit }: Props) => {
8
+ const [limit, setLimit] = useState(defaultLimit ?? 5);
9
+ const [offset, setOffset] = useState(0);
10
+
11
+ return { limit, offset, setLimit, setOffset };
12
+ };
@@ -0,0 +1,111 @@
1
+ import { useState } from 'react';
2
+ import { ITableEdit } from '../../../types/ITable';
3
+ import { deleteProps, hasValue } from '../../../utils/objectUtils';
4
+ import { Select } from '../../Inputs/Selects/Select';
5
+ import { TextInput } from '../../Inputs/TextInput';
6
+ import { DateInput } from '../../Inputs/DateInput/DateInput';
7
+
8
+ interface BaseItemProps<T> {
9
+ id: keyof T;
10
+ placeholder?: string;
11
+ required?: boolean;
12
+ additionalClearIds?: (keyof T)[];
13
+ }
14
+ interface SelectProps<T> extends BaseItemProps<T> {
15
+ options: readonly (string | boolean)[] | (string | boolean)[];
16
+ formatOption: (value: string | boolean) => {
17
+ value: string | boolean;
18
+ label: string;
19
+ };
20
+ }
21
+
22
+ export const useTableEdit = <T extends Record<string, any>>() => {
23
+ const [selectedItem, setSelectedItem] = useState<T | null>(null);
24
+ const [editData, setEditData] = useState<Partial<T>>({});
25
+
26
+ // Text
27
+ const textEditCell = ({
28
+ placeholder,
29
+ required,
30
+ id,
31
+ additionalClearIds = [],
32
+ }: BaseItemProps<T>) => ({
33
+ value: (
34
+ <TextInput
35
+ placeholder={placeholder}
36
+ required={required}
37
+ value={editData[id]}
38
+ setValue={e =>
39
+ setEditData(e ? { ...editData, [id]: e } : deleteProps(editData as T, [id]))
40
+ }
41
+ onClear={() => deleteProps(editData as T, [id, ...additionalClearIds])}
42
+ />
43
+ ),
44
+ });
45
+
46
+ // Date
47
+ const dateEditCell = ({
48
+ id,
49
+ required,
50
+ additionalClearIds,
51
+ }: Omit<BaseItemProps<T>, 'placeholder'>) => ({
52
+ value: (
53
+ <DateInput
54
+ required={required}
55
+ date={editData[id]}
56
+ setDate={e => setEditData({ ...editData, [id]: e })}
57
+ onClear={
58
+ additionalClearIds
59
+ ? () => setEditData(deleteProps(editData as T, additionalClearIds))
60
+ : undefined
61
+ }
62
+ />
63
+ ),
64
+ });
65
+
66
+ // Select
67
+ const selectEditCell = ({
68
+ id,
69
+ placeholder,
70
+ required,
71
+ options,
72
+ formatOption,
73
+ additionalClearIds = [],
74
+ }: SelectProps<T>) => ({
75
+ value: (
76
+ <Select
77
+ required={required}
78
+ placeholder={placeholder}
79
+ value={hasValue(editData[id]) ? formatOption(editData[id]!) : null}
80
+ options={options.map(formatOption)}
81
+ minWidth={150}
82
+ onChange={e => {
83
+ e
84
+ ? setEditData({
85
+ ...editData,
86
+ [id]: e.value,
87
+ })
88
+ : setEditData(deleteProps(editData as T, [id, ...additionalClearIds]));
89
+ }}
90
+ isClearable
91
+ />
92
+ ),
93
+ });
94
+
95
+ const returnEditable: Pick<
96
+ ITableEdit<T>,
97
+ 'selectedItem' | 'setSelectedItem' | 'editData' | 'setEditData'
98
+ > = {
99
+ selectedItem,
100
+ setSelectedItem,
101
+ editData,
102
+ setEditData,
103
+ };
104
+
105
+ return {
106
+ editable: returnEditable,
107
+ textEditCell,
108
+ dateEditCell,
109
+ selectEditCell,
110
+ };
111
+ };
@@ -0,0 +1,150 @@
1
+ import type { Dispatch, SetStateAction } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Select } from '../../Inputs/Selects/Select';
4
+ import { deleteProps } from '../../../utils/objectUtils';
5
+ import { TextInput } from '../../Inputs/TextInput';
6
+ import { DateInput } from '../../Inputs/DateInput/DateInput';
7
+
8
+ interface Props<T> {
9
+ searchData: T;
10
+ setSearchData: Dispatch<SetStateAction<Partial<T>>>;
11
+ }
12
+
13
+ interface BaseItemField<T> {
14
+ id: keyof T;
15
+ additionalClearIds?: (keyof T)[];
16
+ }
17
+ interface BaseItemProps<T> extends BaseItemField<T> {
18
+ label: string;
19
+ }
20
+ interface DateFilterProps<T> {
21
+ label: string;
22
+ from: BaseItemField<T>;
23
+ to: BaseItemField<T>;
24
+ }
25
+ interface SelectProps<T> extends BaseItemProps<T> {
26
+ options: readonly string[] | string[];
27
+ formatOption: (value: string) => {
28
+ value: string;
29
+ label: string;
30
+ };
31
+ }
32
+ interface BooleanSelectProps<T> extends BaseItemProps<T> {
33
+ labelTrue?: string;
34
+ labelFalse?: string;
35
+ }
36
+
37
+ export const useTableFilterFields = <T extends Record<string, any>>({
38
+ searchData,
39
+ setSearchData,
40
+ }: Props<T>) => {
41
+ const { t } = useTranslation();
42
+
43
+ // Text
44
+ const textFilter = ({ label, id, additionalClearIds = [] }: BaseItemProps<T>) => ({
45
+ label,
46
+ field: (
47
+ <TextInput
48
+ placeholder={t('AddInput') + '...'}
49
+ value={searchData[id]}
50
+ setValue={e => setSearchData({ ...searchData, [id]: e })}
51
+ onClear={() =>
52
+ setSearchData(deleteProps(searchData, [id, ...additionalClearIds]))
53
+ }
54
+ />
55
+ ),
56
+ });
57
+
58
+ // Date From - To
59
+ const dateFilter = ({ label, from, to }: DateFilterProps<T>) => ({
60
+ label,
61
+ field: (
62
+ <div className="flex center full-width gap-2">
63
+ <DateInput
64
+ date={searchData[from.id]}
65
+ setDate={e => setSearchData({ ...searchData, [from.id]: e })}
66
+ onClear={() =>
67
+ setSearchData(
68
+ deleteProps(searchData, [from.id, ...(from.additionalClearIds ?? [])])
69
+ )
70
+ }
71
+ />
72
+ <p>{t('to')}</p>
73
+ <DateInput
74
+ date={searchData[to.id]}
75
+ setDate={e => setSearchData({ ...searchData, [to.id]: e })}
76
+ onClear={() =>
77
+ setSearchData(
78
+ deleteProps(searchData, [to.id, ...(to.additionalClearIds ?? [])])
79
+ )
80
+ }
81
+ calendarPlacement="bottom-right"
82
+ />
83
+ </div>
84
+ ),
85
+ });
86
+
87
+ // Select
88
+ const selectFilter = ({ label, id, options, formatOption }: SelectProps<T>) => ({
89
+ label,
90
+ field: (
91
+ <Select
92
+ placeholder={t('Choose')}
93
+ isClearable
94
+ value={searchData[id] ? formatOption(searchData[id]) : null}
95
+ options={options.map(formatOption)}
96
+ onChange={data => {
97
+ data
98
+ ? setSearchData({
99
+ ...searchData,
100
+ [id]: data.value,
101
+ })
102
+ : setSearchData(deleteProps(searchData, [id]));
103
+ }}
104
+ />
105
+ ),
106
+ });
107
+
108
+ // Select Boolean
109
+ const booleanSelectFilter = ({
110
+ label,
111
+ id,
112
+ labelFalse,
113
+ labelTrue,
114
+ }: BooleanSelectProps<T>) => ({
115
+ label,
116
+ field: (
117
+ <Select
118
+ placeholder={t('Choose')}
119
+ isClearable
120
+ value={
121
+ searchData[id] !== undefined
122
+ ? {
123
+ value: searchData[id],
124
+ label: searchData[id] ? (labelTrue ?? t('Yes')) : (labelFalse ?? t('No')),
125
+ }
126
+ : null
127
+ }
128
+ options={[true, false].map(e => ({
129
+ value: e,
130
+ label: e ? (labelTrue ?? t('Yes')) : (labelFalse ?? t('No')),
131
+ }))}
132
+ onChange={data => {
133
+ data
134
+ ? setSearchData({
135
+ ...searchData,
136
+ [id]: data.value,
137
+ })
138
+ : setSearchData(deleteProps(searchData, [id]));
139
+ }}
140
+ />
141
+ ),
142
+ });
143
+
144
+ return {
145
+ textFilter,
146
+ dateFilter,
147
+ selectFilter,
148
+ booleanSelectFilter,
149
+ };
150
+ };
@@ -0,0 +1,16 @@
1
+ import { useState } from 'react';
2
+ import { IPagination, IPaginationControl } from '../../../types/ITable';
3
+
4
+ export const useTablePagination = (defaultLimit: number = 5) => {
5
+ const [limit, setLimit] = useState(defaultLimit);
6
+ const [offset, setOffset] = useState(0);
7
+
8
+ const pagination: IPagination = { limit, offset };
9
+ const paginationControl: IPaginationControl = {
10
+ ...pagination,
11
+ setLimit,
12
+ setOffset,
13
+ };
14
+
15
+ return { pagination, paginationControl };
16
+ };
@@ -0,0 +1,29 @@
1
+ import { Dispatch, SetStateAction, useState } from 'react';
2
+
3
+ export interface ITableSearchProps<T> {
4
+ setOffset: Dispatch<SetStateAction<number>>;
5
+ resetSelectedRows?: () => void;
6
+ defaultSearch?: T;
7
+ }
8
+
9
+ export const useTableSearch = <T>({
10
+ setOffset,
11
+ resetSelectedRows,
12
+ defaultSearch = {} as T,
13
+ }: ITableSearchProps<T>) => {
14
+ const [search, setSearch] = useState<T>(defaultSearch);
15
+ const [searchData, setSearchData] = useState<T>(defaultSearch);
16
+
17
+ const onSearch = (filters: T) => {
18
+ setOffset(0);
19
+ resetSelectedRows?.();
20
+ setSearch(filters);
21
+ };
22
+
23
+ return {
24
+ search,
25
+ searchData,
26
+ setSearchData,
27
+ onSearch,
28
+ };
29
+ };
@@ -0,0 +1,8 @@
1
+ import { useState } from 'react';
2
+ import { ITableSort } from '../../../types/ITable';
3
+
4
+ export const useTableSort = (sortOptions: ITableSort[]) => {
5
+ const [sort, setSort] = useState('');
6
+
7
+ return { sort, setSort, sortOptions };
8
+ };
@@ -11,7 +11,7 @@ import {
11
11
  useState,
12
12
  } from 'react';
13
13
  import { createPortal } from 'react-dom';
14
- import { rootDir } from '../../utils/RootDir';
14
+ import { rootDir } from '../../utils/rootDir';
15
15
 
16
16
  export type TooltipPosition = 'left' | 'right' | 'top' | 'bottom';
17
17