@controleonline/ui-default 1.0.263 → 1.0.265
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.
- package/AGENTS.md +47 -45
- package/package.json +20 -20
- package/src/react/components/errors/DefaultErrors.js +307 -325
- package/src/react/components/files/DefaultFile.js +46 -46
- package/src/react/components/filters/CompactFilterSelector.js +78 -24
- package/src/react/components/filters/CompactFilterSelector.styles.js +17 -5
- package/src/react/components/filters/DefaultColumnFilter.js +191 -57
- package/src/react/components/filters/DefaultExternalFilters.js +245 -182
- package/src/react/components/filters/DefaultSearch.js +131 -92
- package/src/react/components/filters/DefaultSearch.styles.js +65 -70
- package/src/react/components/form/DefaultForm.js +172 -151
- package/src/react/components/form/DefaultForm.styles.js +71 -66
- package/src/react/components/help/DefaultTooltip.js +87 -87
- package/src/react/components/help/DefaultTooltip.styles.js +61 -61
- package/src/react/components/inputs/DefaultDateInput.js +150 -0
- package/src/react/components/inputs/DefaultInput.js +162 -127
- package/src/react/components/inputs/DefaultInput.styles.js +6 -0
- package/src/react/components/inputs/DefaultSelect.js +320 -152
- package/src/react/components/inputs/defaultInputUtils.js +40 -19
- package/src/react/components/map/DefaultGoogleMap.styles.js +115 -9
- package/src/react/components/map/DefaultGoogleMap.web.js +560 -446
- package/src/react/components/map/DefaultMap.native.js +73 -71
- package/src/react/components/map/DefaultMap.styles.js +16 -16
- package/src/react/components/map/DefaultMap.web.js +68 -66
- package/src/react/components/map/DefaultNativeMap.native.js +307 -183
- package/src/react/components/map/DefaultNativeMap.shared.js +439 -340
- package/src/react/components/map/DefaultNativeMap.styles.js +156 -122
- package/src/react/components/table/DefaultColumnMenu.js +108 -0
- package/src/react/components/table/DefaultDebug.js +233 -0
- package/src/react/components/table/DefaultFiltersModal.js +142 -0
- package/src/react/components/table/DefaultModalButton.js +18 -0
- package/src/react/components/table/DefaultSearchModal.js +49 -0
- package/src/react/components/table/DefaultTable.js +345 -1846
- package/src/react/components/table/DefaultTable.styles.js +247 -136
- package/src/react/components/table/DefaultTable.utils.js +502 -0
- package/src/react/components/table/DefaultTableBody.js +26 -0
- package/src/react/components/table/DefaultTableCards.js +171 -0
- package/src/react/components/table/DefaultTableControls.js +208 -0
- package/src/react/components/table/DefaultTableEmptyState.js +22 -0
- package/src/react/components/table/DefaultTableFooter.js +172 -0
- package/src/react/components/table/DefaultTableInput.js +145 -0
- package/src/react/components/table/DefaultTableRows.js +340 -0
- package/src/react/components/table/DefaultTableSearch.js +100 -0
- package/src/react/components/table/DefaultTableToolbar.js +98 -0
- package/src/react/components/table/DefaultToolbarAction.js +56 -0
- package/src/react/components/table/useDefaultTablePagination.js +370 -0
- package/src/react/components/table/useDefaultTableSorting.js +126 -0
- package/src/react/components/table/useDefaultTableTheme.js +58 -0
- package/src/react/index.js +10 -10
- package/src/react/utils/tableVisibleColumnsPreferences.js +239 -211
- package/src/store/default/actions.js +51 -13
- package/src/store/default/getters.js +10 -8
- package/src/store/default/mutation_types.js +4 -2
- package/src/store/default/mutations.js +10 -1
- package/src/tests/react/components/errors/DefaultErrors.test.js +162 -162
- package/src/tests/react/components/files/DefaultFile.test.js +80 -80
- package/src/tests/react/components/form/DefaultForm.test.js +81 -0
- package/src/tests/react/components/inputs/DefaultSelect.test.js +185 -0
- package/src/tests/react/components/table/DefaultTable.test.js +1183 -0
- package/src/tests/react/store/defaultActions.test.js +59 -0
- package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +247 -168
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
getColumnKey,
|
|
4
|
+
isDateLikeColumn,
|
|
5
|
+
} from '../inputs/defaultInputUtils';
|
|
6
|
+
import {
|
|
7
|
+
normalizeCollectionItems,
|
|
8
|
+
resolveDateRangeQuery,
|
|
9
|
+
resolveFilterQueryValue,
|
|
10
|
+
resolveHasMore,
|
|
11
|
+
stableSerialize,
|
|
12
|
+
} from './DefaultTable.utils';
|
|
13
|
+
|
|
14
|
+
const buildQueryFromState = ({
|
|
15
|
+
append,
|
|
16
|
+
columnsForTable,
|
|
17
|
+
filters,
|
|
18
|
+
page,
|
|
19
|
+
pageSizeNumber,
|
|
20
|
+
requestParams,
|
|
21
|
+
sort,
|
|
22
|
+
}) => {
|
|
23
|
+
const query = {
|
|
24
|
+
...requestParams,
|
|
25
|
+
itemsPerPage: pageSizeNumber,
|
|
26
|
+
page,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (sort?.field && sort?.direction) {
|
|
30
|
+
query[`order[${sort.field}]`] = sort.direction;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Object.entries(filters || {}).forEach(([fieldName, value]) => {
|
|
34
|
+
if (!fieldName) return;
|
|
35
|
+
|
|
36
|
+
const column = columnsForTable.find(item => getColumnKey(item) === fieldName);
|
|
37
|
+
|
|
38
|
+
if (isDateLikeColumn(column)) {
|
|
39
|
+
const dateRange = resolveDateRangeQuery(value);
|
|
40
|
+
if (dateRange.after) {
|
|
41
|
+
query[`${fieldName}[after]`] = dateRange.after;
|
|
42
|
+
}
|
|
43
|
+
if (dateRange.before) {
|
|
44
|
+
query[`${fieldName}[before]`] = dateRange.before;
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const normalizedValue = resolveFilterQueryValue(value);
|
|
50
|
+
if (Array.isArray(normalizedValue)) {
|
|
51
|
+
if (normalizedValue.length > 0) {
|
|
52
|
+
query[fieldName] = normalizedValue;
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (normalizedValue !== '') {
|
|
58
|
+
query[fieldName] = normalizedValue;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (append) {
|
|
63
|
+
query.append = true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return query;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const useAutoPageLoader = ({
|
|
70
|
+
autoMode,
|
|
71
|
+
autoQuerySignature,
|
|
72
|
+
buildRequestQuery,
|
|
73
|
+
endReachedLockRef,
|
|
74
|
+
pageSizeNumber,
|
|
75
|
+
resolvedActions,
|
|
76
|
+
showError,
|
|
77
|
+
storeName,
|
|
78
|
+
}) => {
|
|
79
|
+
const [autoHasLoaded, setAutoHasLoaded] = useState(false);
|
|
80
|
+
const [autoLoading, setAutoLoading] = useState(false);
|
|
81
|
+
const [autoLoadingMore, setAutoLoadingMore] = useState(false);
|
|
82
|
+
const [autoLastPageCount, setAutoLastPageCount] = useState(0);
|
|
83
|
+
const autoRequestIdRef = useRef(0);
|
|
84
|
+
const autoLoadedQueryKeyRef = useRef('');
|
|
85
|
+
const autoErroredQueryKeyRef = useRef('');
|
|
86
|
+
const autoPageRef = useRef(0);
|
|
87
|
+
|
|
88
|
+
const loadAutoPage = useCallback(
|
|
89
|
+
(page, { append = false } = {}) => {
|
|
90
|
+
if (!autoMode || typeof resolvedActions.getItems !== 'function') {
|
|
91
|
+
return Promise.resolve([]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const requestId = autoRequestIdRef.current + 1;
|
|
95
|
+
autoRequestIdRef.current = requestId;
|
|
96
|
+
|
|
97
|
+
if (append) {
|
|
98
|
+
setAutoLoadingMore(true);
|
|
99
|
+
} else {
|
|
100
|
+
setAutoLoading(true);
|
|
101
|
+
setAutoHasLoaded(false);
|
|
102
|
+
setAutoLastPageCount(0);
|
|
103
|
+
autoPageRef.current = 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const query = buildRequestQuery(page, append);
|
|
107
|
+
|
|
108
|
+
return Promise.resolve(resolvedActions.getItems(query))
|
|
109
|
+
.then(response => {
|
|
110
|
+
if (autoRequestIdRef.current !== requestId) {
|
|
111
|
+
return response;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const pageItems = normalizeCollectionItems(response);
|
|
115
|
+
autoPageRef.current = page;
|
|
116
|
+
autoLoadedQueryKeyRef.current = autoQuerySignature;
|
|
117
|
+
autoErroredQueryKeyRef.current = '';
|
|
118
|
+
setAutoHasLoaded(true);
|
|
119
|
+
setAutoLastPageCount(pageItems.length);
|
|
120
|
+
return pageItems;
|
|
121
|
+
})
|
|
122
|
+
.catch(error => {
|
|
123
|
+
if (autoRequestIdRef.current === requestId) {
|
|
124
|
+
autoErroredQueryKeyRef.current = autoQuerySignature;
|
|
125
|
+
showError?.(
|
|
126
|
+
error?.message || global.t?.t(storeName, 'error', 'load'),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return [];
|
|
131
|
+
})
|
|
132
|
+
.finally(() => {
|
|
133
|
+
if (autoRequestIdRef.current === requestId) {
|
|
134
|
+
setAutoLoading(false);
|
|
135
|
+
setAutoLoadingMore(false);
|
|
136
|
+
endReachedLockRef.current = false;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
[
|
|
141
|
+
autoMode,
|
|
142
|
+
autoQuerySignature,
|
|
143
|
+
buildRequestQuery,
|
|
144
|
+
endReachedLockRef,
|
|
145
|
+
resolvedActions,
|
|
146
|
+
showError,
|
|
147
|
+
storeName,
|
|
148
|
+
],
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
autoErroredQueryKeyRef,
|
|
153
|
+
autoHasLoaded,
|
|
154
|
+
autoLastPageCount,
|
|
155
|
+
autoLoadedQueryKeyRef,
|
|
156
|
+
autoLoading,
|
|
157
|
+
autoLoadingMore,
|
|
158
|
+
autoPageRef,
|
|
159
|
+
loadAutoPage,
|
|
160
|
+
pageSizeNumber,
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const useAutoPageEffect = ({
|
|
165
|
+
autoErroredQueryKeyRef,
|
|
166
|
+
autoLoadedQueryKeyRef,
|
|
167
|
+
autoLoading,
|
|
168
|
+
autoLoadingMore,
|
|
169
|
+
autoMode,
|
|
170
|
+
autoQuerySignature,
|
|
171
|
+
endReachedLockRef,
|
|
172
|
+
isFocused,
|
|
173
|
+
loadAutoPage,
|
|
174
|
+
resolvedActions,
|
|
175
|
+
}) => {
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
if (!autoMode || !isFocused) return;
|
|
178
|
+
if (typeof resolvedActions.getItems !== 'function') return;
|
|
179
|
+
if (
|
|
180
|
+
autoLoading ||
|
|
181
|
+
autoLoadingMore ||
|
|
182
|
+
autoLoadedQueryKeyRef.current === autoQuerySignature ||
|
|
183
|
+
autoErroredQueryKeyRef.current === autoQuerySignature
|
|
184
|
+
) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
endReachedLockRef.current = false;
|
|
189
|
+
loadAutoPage(1, { append: false });
|
|
190
|
+
}, [
|
|
191
|
+
autoErroredQueryKeyRef,
|
|
192
|
+
autoLoadedQueryKeyRef,
|
|
193
|
+
autoLoading,
|
|
194
|
+
autoLoadingMore,
|
|
195
|
+
autoMode,
|
|
196
|
+
autoQuerySignature,
|
|
197
|
+
endReachedLockRef,
|
|
198
|
+
isFocused,
|
|
199
|
+
loadAutoPage,
|
|
200
|
+
resolvedActions,
|
|
201
|
+
]);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export const useDefaultTablePagination = ({
|
|
205
|
+
autoMode,
|
|
206
|
+
columnsForTable,
|
|
207
|
+
data,
|
|
208
|
+
filters,
|
|
209
|
+
hasMore,
|
|
210
|
+
isFocused,
|
|
211
|
+
isLoading,
|
|
212
|
+
onEndReached,
|
|
213
|
+
pageSize,
|
|
214
|
+
requestParams,
|
|
215
|
+
resolvedActions,
|
|
216
|
+
resolvedSort,
|
|
217
|
+
resolvedTotalItems,
|
|
218
|
+
showError,
|
|
219
|
+
store,
|
|
220
|
+
storeName,
|
|
221
|
+
}) => {
|
|
222
|
+
const endReachedLockRef = useRef(false);
|
|
223
|
+
const previousPaginationStateRef = useRef({
|
|
224
|
+
dataLength: Array.isArray(data) ? data.length : 0,
|
|
225
|
+
filtersKey: JSON.stringify(filters || {}),
|
|
226
|
+
sortDirection: resolvedSort?.direction,
|
|
227
|
+
sortField: resolvedSort?.field,
|
|
228
|
+
});
|
|
229
|
+
const pageSizeNumber = Number(requestParams.itemsPerPage || pageSize || 50) || 50;
|
|
230
|
+
const buildRequestQuery = useCallback(
|
|
231
|
+
(page, append = false) =>
|
|
232
|
+
buildQueryFromState({
|
|
233
|
+
append,
|
|
234
|
+
columnsForTable,
|
|
235
|
+
filters,
|
|
236
|
+
page,
|
|
237
|
+
pageSizeNumber,
|
|
238
|
+
requestParams,
|
|
239
|
+
sort: resolvedSort,
|
|
240
|
+
}),
|
|
241
|
+
[columnsForTable, filters, pageSizeNumber, requestParams, resolvedSort],
|
|
242
|
+
);
|
|
243
|
+
const autoQuerySignature = useMemo(
|
|
244
|
+
() =>
|
|
245
|
+
stableSerialize({
|
|
246
|
+
filters,
|
|
247
|
+
pageSize: pageSizeNumber,
|
|
248
|
+
requestParams,
|
|
249
|
+
sort: resolvedSort,
|
|
250
|
+
}),
|
|
251
|
+
[filters, pageSizeNumber, requestParams, resolvedSort],
|
|
252
|
+
);
|
|
253
|
+
const {
|
|
254
|
+
autoErroredQueryKeyRef,
|
|
255
|
+
autoHasLoaded,
|
|
256
|
+
autoLastPageCount,
|
|
257
|
+
autoLoadedQueryKeyRef,
|
|
258
|
+
autoLoading,
|
|
259
|
+
autoLoadingMore,
|
|
260
|
+
autoPageRef,
|
|
261
|
+
loadAutoPage,
|
|
262
|
+
} = useAutoPageLoader({
|
|
263
|
+
autoMode,
|
|
264
|
+
autoQuerySignature,
|
|
265
|
+
buildRequestQuery,
|
|
266
|
+
endReachedLockRef,
|
|
267
|
+
pageSizeNumber,
|
|
268
|
+
resolvedActions,
|
|
269
|
+
showError,
|
|
270
|
+
storeName,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
useAutoPageEffect({
|
|
274
|
+
autoErroredQueryKeyRef,
|
|
275
|
+
autoLoadedQueryKeyRef,
|
|
276
|
+
autoLoading,
|
|
277
|
+
autoLoadingMore,
|
|
278
|
+
autoMode,
|
|
279
|
+
autoQuerySignature,
|
|
280
|
+
endReachedLockRef,
|
|
281
|
+
isFocused,
|
|
282
|
+
loadAutoPage,
|
|
283
|
+
resolvedActions,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const resolvedIsLoading = autoMode
|
|
287
|
+
? (autoLoading || autoLoadingMore)
|
|
288
|
+
: Boolean(isLoading);
|
|
289
|
+
const resolvedData = autoMode
|
|
290
|
+
? (autoHasLoaded && Array.isArray(store?.getters?.items) ? store.getters.items : [])
|
|
291
|
+
: (Array.isArray(data) ? data : []);
|
|
292
|
+
const resolvedHasMore = useMemo(
|
|
293
|
+
() => {
|
|
294
|
+
if (autoMode) {
|
|
295
|
+
if (Number.isFinite(Number(resolvedTotalItems)) && Number(resolvedTotalItems) > 0) {
|
|
296
|
+
return resolvedData.length < Number(resolvedTotalItems);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return autoLastPageCount >= pageSizeNumber && resolvedData.length > 0;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return resolveHasMore({
|
|
303
|
+
hasMore,
|
|
304
|
+
dataLength: resolvedData.length,
|
|
305
|
+
totalItems: resolvedTotalItems,
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
[autoLastPageCount, autoMode, hasMore, pageSizeNumber, resolvedData.length, resolvedTotalItems],
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
useEffect(() => {
|
|
312
|
+
const nextPaginationState = {
|
|
313
|
+
dataLength: resolvedData.length,
|
|
314
|
+
filtersKey: stableSerialize(filters || {}),
|
|
315
|
+
sortDirection: resolvedSort?.direction,
|
|
316
|
+
sortField: resolvedSort?.field,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const previousPaginationState = previousPaginationStateRef.current;
|
|
320
|
+
const didPaginationStateChange =
|
|
321
|
+
previousPaginationState.dataLength !== nextPaginationState.dataLength ||
|
|
322
|
+
previousPaginationState.filtersKey !== nextPaginationState.filtersKey ||
|
|
323
|
+
previousPaginationState.sortDirection !== nextPaginationState.sortDirection ||
|
|
324
|
+
previousPaginationState.sortField !== nextPaginationState.sortField;
|
|
325
|
+
|
|
326
|
+
if (didPaginationStateChange) {
|
|
327
|
+
endReachedLockRef.current = false;
|
|
328
|
+
previousPaginationStateRef.current = nextPaginationState;
|
|
329
|
+
}
|
|
330
|
+
}, [filters, resolvedData.length, resolvedSort?.direction, resolvedSort?.field]);
|
|
331
|
+
|
|
332
|
+
const handleEndReached = useCallback(() => {
|
|
333
|
+
if (
|
|
334
|
+
!resolvedHasMore ||
|
|
335
|
+
resolvedIsLoading ||
|
|
336
|
+
endReachedLockRef.current === true
|
|
337
|
+
) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
endReachedLockRef.current = true;
|
|
342
|
+
|
|
343
|
+
if (autoMode) {
|
|
344
|
+
const nextPage = autoPageRef.current + 1;
|
|
345
|
+
loadAutoPage(nextPage, { append: true });
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (typeof onEndReached === 'function') {
|
|
350
|
+
onEndReached();
|
|
351
|
+
}
|
|
352
|
+
}, [
|
|
353
|
+
autoMode,
|
|
354
|
+
autoPageRef,
|
|
355
|
+
loadAutoPage,
|
|
356
|
+
onEndReached,
|
|
357
|
+
resolvedHasMore,
|
|
358
|
+
resolvedIsLoading,
|
|
359
|
+
]);
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
buildRequestQuery,
|
|
363
|
+
currentPage: autoPageRef.current,
|
|
364
|
+
handleEndReached,
|
|
365
|
+
pageSizeNumber,
|
|
366
|
+
resolvedData,
|
|
367
|
+
resolvedHasMore,
|
|
368
|
+
resolvedIsLoading,
|
|
369
|
+
};
|
|
370
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
getSortField,
|
|
4
|
+
isSortableColumn,
|
|
5
|
+
normalizeSortText,
|
|
6
|
+
resolveDefaultSort,
|
|
7
|
+
resolveSortComparable,
|
|
8
|
+
sanitizeStoredSortPreference,
|
|
9
|
+
stableSerialize,
|
|
10
|
+
} from './DefaultTable.utils';
|
|
11
|
+
import {
|
|
12
|
+
persistTableSortPreference,
|
|
13
|
+
resolveStoredTableSortPreference,
|
|
14
|
+
} from '../../utils/tableVisibleColumnsPreferences';
|
|
15
|
+
|
|
16
|
+
export const useDefaultTableSortState = ({
|
|
17
|
+
autoMode,
|
|
18
|
+
columnsForTable,
|
|
19
|
+
onSortChange,
|
|
20
|
+
sort,
|
|
21
|
+
tablePreferenceScope,
|
|
22
|
+
}) => {
|
|
23
|
+
const defaultSortSeed = useMemo(
|
|
24
|
+
() => resolveDefaultSort(columnsForTable),
|
|
25
|
+
[columnsForTable],
|
|
26
|
+
);
|
|
27
|
+
const storedSortSeed = useMemo(
|
|
28
|
+
() =>
|
|
29
|
+
sanitizeStoredSortPreference({
|
|
30
|
+
columns: columnsForTable,
|
|
31
|
+
fallbackSort: sort || defaultSortSeed || null,
|
|
32
|
+
sort: resolveStoredTableSortPreference(tablePreferenceScope),
|
|
33
|
+
}),
|
|
34
|
+
[columnsForTable, defaultSortSeed, sort, tablePreferenceScope],
|
|
35
|
+
);
|
|
36
|
+
const storedSortSeedSignature = useMemo(
|
|
37
|
+
() => stableSerialize(storedSortSeed),
|
|
38
|
+
[storedSortSeed],
|
|
39
|
+
);
|
|
40
|
+
const [autoSort, setAutoSort] = useState(() => storedSortSeed);
|
|
41
|
+
const appliedSortSeedSignatureRef = useRef(storedSortSeedSignature);
|
|
42
|
+
const resolvedSort = autoMode ? autoSort : sort;
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!autoMode) return;
|
|
46
|
+
if (appliedSortSeedSignatureRef.current === storedSortSeedSignature) return;
|
|
47
|
+
|
|
48
|
+
appliedSortSeedSignatureRef.current = storedSortSeedSignature;
|
|
49
|
+
setAutoSort(prev =>
|
|
50
|
+
stableSerialize(prev) === storedSortSeedSignature
|
|
51
|
+
? prev
|
|
52
|
+
: storedSortSeed,
|
|
53
|
+
);
|
|
54
|
+
}, [autoMode, storedSortSeed, storedSortSeedSignature]);
|
|
55
|
+
|
|
56
|
+
const requestSort = useCallback(column => {
|
|
57
|
+
if (!isSortableColumn(column)) return;
|
|
58
|
+
|
|
59
|
+
const fieldName = getSortField(column);
|
|
60
|
+
const nextDirection =
|
|
61
|
+
resolvedSort?.field === fieldName && resolvedSort?.direction === 'asc'
|
|
62
|
+
? 'desc'
|
|
63
|
+
: 'asc';
|
|
64
|
+
const nextSort = {
|
|
65
|
+
direction: nextDirection,
|
|
66
|
+
field: fieldName,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
persistTableSortPreference(tablePreferenceScope, nextSort);
|
|
70
|
+
|
|
71
|
+
if (autoMode) {
|
|
72
|
+
setAutoSort(nextSort);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
onSortChange?.(nextSort);
|
|
77
|
+
}, [
|
|
78
|
+
autoMode,
|
|
79
|
+
onSortChange,
|
|
80
|
+
resolvedSort?.direction,
|
|
81
|
+
resolvedSort?.field,
|
|
82
|
+
tablePreferenceScope,
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
requestSort,
|
|
87
|
+
resolvedSort,
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const useDefaultTableSortedData = ({
|
|
92
|
+
resolvedData,
|
|
93
|
+
resolvedSort,
|
|
94
|
+
storeName,
|
|
95
|
+
tableColumns,
|
|
96
|
+
}) =>
|
|
97
|
+
useMemo(() => {
|
|
98
|
+
const items = Array.isArray(resolvedData) ? [...resolvedData] : [];
|
|
99
|
+
const sortField = resolvedSort?.field;
|
|
100
|
+
const sortDirection = resolvedSort?.direction === 'desc' ? 'desc' : 'asc';
|
|
101
|
+
const sortColumn = tableColumns.find(column => getSortField(column) === sortField);
|
|
102
|
+
|
|
103
|
+
if (!sortField || !sortColumn) return items;
|
|
104
|
+
|
|
105
|
+
return items.sort((left, right) => {
|
|
106
|
+
const leftValue = resolveSortComparable({
|
|
107
|
+
column: sortColumn,
|
|
108
|
+
columns: tableColumns,
|
|
109
|
+
row: left,
|
|
110
|
+
storeName,
|
|
111
|
+
});
|
|
112
|
+
const rightValue = resolveSortComparable({
|
|
113
|
+
column: sortColumn,
|
|
114
|
+
columns: tableColumns,
|
|
115
|
+
row: right,
|
|
116
|
+
storeName,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const comparison =
|
|
120
|
+
typeof leftValue === 'number' && typeof rightValue === 'number'
|
|
121
|
+
? leftValue - rightValue
|
|
122
|
+
: normalizeSortText(leftValue).localeCompare(normalizeSortText(rightValue));
|
|
123
|
+
|
|
124
|
+
return sortDirection === 'desc' ? comparison * -1 : comparison;
|
|
125
|
+
});
|
|
126
|
+
}, [resolvedData, resolvedSort?.direction, resolvedSort?.field, storeName, tableColumns]);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useStore } from '@store';
|
|
3
|
+
import { resolveThemePalette } from '@controleonline/../../src/styles/branding';
|
|
4
|
+
import { colors } from '@controleonline/../../src/styles/colors';
|
|
5
|
+
|
|
6
|
+
const useDefaultTableTheme = (accentColor = null) => {
|
|
7
|
+
const themeStore = useStore('theme');
|
|
8
|
+
const baseColors = themeStore?.getters?.colors || {};
|
|
9
|
+
const themeTokens = useMemo(
|
|
10
|
+
() => ({ ...baseColors }),
|
|
11
|
+
[baseColors],
|
|
12
|
+
);
|
|
13
|
+
const palette = useMemo(
|
|
14
|
+
() => resolveThemePalette(themeTokens, colors) || {},
|
|
15
|
+
[themeTokens],
|
|
16
|
+
);
|
|
17
|
+
const themeColors = palette.colors || baseColors || colors || {};
|
|
18
|
+
const resolvedAccentColor = accentColor || palette.primary || themeColors.primary || '#0EA5E9';
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
palette,
|
|
22
|
+
resolvedAccentColor,
|
|
23
|
+
themeColors,
|
|
24
|
+
themeTokens,
|
|
25
|
+
checkboxBorderColor: themeColors.checkboxBorder,
|
|
26
|
+
checkboxSelectedMarkColor: themeColors.checkboxSelectedMark,
|
|
27
|
+
modalColors: {
|
|
28
|
+
backgroundColor: themeColors.modalBackground,
|
|
29
|
+
borderColor: themeColors.modalBorder,
|
|
30
|
+
closeIconColor: themeColors.modalCloseIcon,
|
|
31
|
+
headerTextColor: themeColors.modalHeaderText,
|
|
32
|
+
overlayColor: themeColors.modalOverlay,
|
|
33
|
+
textColor: themeColors.modalText,
|
|
34
|
+
},
|
|
35
|
+
tableButtonColors: {
|
|
36
|
+
backgroundColor: themeColors.buttonBackground,
|
|
37
|
+
borderColor: themeColors.buttonBorder,
|
|
38
|
+
iconColor: themeColors.buttonIcon,
|
|
39
|
+
pressedBackgroundColor: themeColors.buttonPressedBackground,
|
|
40
|
+
pressedBorderColor: themeColors.buttonPressedBorder,
|
|
41
|
+
pressedIconColor: themeColors.buttonPressedIcon,
|
|
42
|
+
textColor: themeColors.buttonText,
|
|
43
|
+
},
|
|
44
|
+
tableActionColors: {
|
|
45
|
+
backgroundColor: themeColors.tableActionBackground,
|
|
46
|
+
borderColor: themeColors.tableActionBorder,
|
|
47
|
+
textColor: themeColors.tableActionIcon,
|
|
48
|
+
},
|
|
49
|
+
toolbarColors: {
|
|
50
|
+
backgroundColor: themeColors.toolbarBackground,
|
|
51
|
+
borderColor: themeColors.toolbarBorder,
|
|
52
|
+
countBackgroundColor: themeColors.badgeBackground,
|
|
53
|
+
countTextColor: themeColors.badgeText,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default useDefaultTableTheme;
|
package/src/react/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// React entrypoint kept after Vue removal.
|
|
2
|
-
import DefaultFile from './components/files/DefaultFile';
|
|
3
|
-
|
|
4
|
-
const moduleEntry = {
|
|
5
|
-
DefaultFile,
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export {DefaultFile};
|
|
9
|
-
|
|
10
|
-
export default moduleEntry;
|
|
1
|
+
// React entrypoint kept after Vue removal.
|
|
2
|
+
import DefaultFile from './components/files/DefaultFile';
|
|
3
|
+
|
|
4
|
+
const moduleEntry = {
|
|
5
|
+
DefaultFile,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export {DefaultFile};
|
|
9
|
+
|
|
10
|
+
export default moduleEntry;
|