@controleonline/ui-default 1.0.266 → 1.0.267
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/package.json +1 -1
- package/src/react/components/inputs/DefaultInput.js +71 -33
- package/src/react/components/inputs/DefaultInput.styles.js +36 -4
- package/src/react/components/inputs/DefaultSelect.js +83 -35
- package/src/react/components/inputs/defaultInputUtils.js +173 -26
- package/src/react/components/table/DefaultTable.js +6 -4
- package/src/react/components/table/DefaultTable.styles.js +54 -51
- package/src/react/components/table/DefaultTableCards.js +18 -9
- package/src/react/components/table/DefaultTableFooter.js +10 -1
- package/src/react/components/table/DefaultTableRows.js +29 -6
- package/src/react/components/table/DefaultTableToolbar.js +8 -2
- package/src/react/components/table/useDefaultTableTheme.js +65 -16
- package/src/tests/react/inputs/defaultInputUtils.test.js +80 -9
package/package.json
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { Text, TextInput, TouchableOpacity, View } from 'react-native';
|
|
2
|
+
import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native';
|
|
3
3
|
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
buildReadPresentationStyles,
|
|
5
6
|
getColumnKey,
|
|
6
7
|
isDateLikeColumn,
|
|
7
8
|
isEditableColumn,
|
|
8
|
-
normalizeText,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
normalizeText,
|
|
10
|
+
resolveCellPresentation,
|
|
11
|
+
resolveCellText,
|
|
12
|
+
resolveEditValue,
|
|
11
13
|
} from './defaultInputUtils';
|
|
12
14
|
import DefaultDateInput from './DefaultDateInput';
|
|
13
15
|
import DefaultSelect from './DefaultSelect';
|
|
14
|
-
import styles from './DefaultInput.styles';
|
|
15
|
-
|
|
16
|
-
const DefaultInput = ({
|
|
16
|
+
import styles from './DefaultInput.styles';
|
|
17
|
+
|
|
18
|
+
const DefaultInput = ({
|
|
17
19
|
accentColor = '#2563EB',
|
|
18
20
|
autoFocus = true,
|
|
19
21
|
autoSave = true,
|
|
@@ -48,8 +50,19 @@ const DefaultInput = ({
|
|
|
48
50
|
[column, row, value],
|
|
49
51
|
);
|
|
50
52
|
const [draftValue, setDraftValue] = useState(editValue);
|
|
51
|
-
const resolvedLabel =
|
|
52
|
-
displayValue ?? resolveCellText({ column, columns, row, storeName, value });
|
|
53
|
+
const resolvedLabel =
|
|
54
|
+
displayValue ?? resolveCellText({ column, columns, row, storeName, value });
|
|
55
|
+
const readPresentation = useMemo(
|
|
56
|
+
() => resolveCellPresentation({ column, columns, row, storeName, value }),
|
|
57
|
+
[column, columns, row, storeName, value],
|
|
58
|
+
);
|
|
59
|
+
const readPresentationStyles = useMemo(
|
|
60
|
+
() => buildReadPresentationStyles({
|
|
61
|
+
...readPresentation,
|
|
62
|
+
label: resolvedLabel,
|
|
63
|
+
}),
|
|
64
|
+
[readPresentation, resolvedLabel],
|
|
65
|
+
);
|
|
53
66
|
|
|
54
67
|
useEffect(() => {
|
|
55
68
|
setDraftValue(editValue);
|
|
@@ -128,31 +141,56 @@ const DefaultInput = ({
|
|
|
128
141
|
if (!autoSave) onChangeValue?.(nextValue);
|
|
129
142
|
};
|
|
130
143
|
|
|
131
|
-
if (!editing && !isForm) {
|
|
132
|
-
return (
|
|
133
|
-
<View style={[styles.wrap, containerStyle]}>
|
|
134
|
-
{showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
|
|
135
|
-
<TouchableOpacity
|
|
144
|
+
if (!editing && !isForm) {
|
|
145
|
+
return (
|
|
146
|
+
<View style={[styles.wrap, containerStyle]}>
|
|
147
|
+
{showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
|
|
148
|
+
<TouchableOpacity
|
|
136
149
|
style={styles.readButton}
|
|
137
150
|
activeOpacity={canEdit ? 0.78 : 1}
|
|
138
|
-
disabled={!canEdit}
|
|
139
|
-
onPress={() => onStartEditing?.()}
|
|
140
|
-
>
|
|
141
|
-
<
|
|
142
|
-
style={[
|
|
143
|
-
styles.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
]}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
disabled={!canEdit}
|
|
152
|
+
onPress={() => onStartEditing?.()}
|
|
153
|
+
>
|
|
154
|
+
<View
|
|
155
|
+
style={[
|
|
156
|
+
styles.readValueWrap,
|
|
157
|
+
readPresentationStyles.hasDecoration ? styles.readBadge : null,
|
|
158
|
+
readPresentationStyles.badgeStyle,
|
|
159
|
+
]}
|
|
160
|
+
>
|
|
161
|
+
{readPresentation.image ? (
|
|
162
|
+
<Image
|
|
163
|
+
source={readPresentation.image}
|
|
164
|
+
style={styles.readImage}
|
|
165
|
+
resizeMode="contain"
|
|
166
|
+
/>
|
|
167
|
+
) : null}
|
|
168
|
+
{readPresentationStyles.hasDecoration && readPresentation.icon && readPresentationStyles.color ? (
|
|
169
|
+
<Icon
|
|
170
|
+
style={styles.readBadgeIcon}
|
|
171
|
+
name={readPresentation.icon}
|
|
172
|
+
size={12}
|
|
173
|
+
color={readPresentationStyles.color}
|
|
174
|
+
/>
|
|
175
|
+
) : null}
|
|
176
|
+
<Text
|
|
177
|
+
style={[
|
|
178
|
+
styles.readText,
|
|
179
|
+
readPresentationStyles.hasDecoration ? styles.readBadgeText : null,
|
|
180
|
+
resolvedLabel === '-' ? styles.mutedText : null,
|
|
181
|
+
readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
|
|
182
|
+
readTextStyle,
|
|
183
|
+
]}
|
|
184
|
+
numberOfLines={numberOfLines}
|
|
185
|
+
>
|
|
186
|
+
{column?.prefix || ''}
|
|
187
|
+
{resolvedLabel || '-'}
|
|
188
|
+
{column?.sufix || column?.suffix || ''}
|
|
189
|
+
</Text>
|
|
190
|
+
</View>
|
|
191
|
+
{saving ? (
|
|
192
|
+
<Text style={[styles.savingText, { color: accentColor }]}>Salvando</Text>
|
|
193
|
+
) : canEdit ? (
|
|
156
194
|
<Icon style={styles.editIcon} name="edit-2" size={13} color="#64748B" />
|
|
157
195
|
) : null}
|
|
158
196
|
</TouchableOpacity>
|
|
@@ -13,6 +13,38 @@ const styles = StyleSheet.create({
|
|
|
13
13
|
alignItems: 'center',
|
|
14
14
|
gap: 6,
|
|
15
15
|
},
|
|
16
|
+
readValueWrap: {
|
|
17
|
+
flex: 1,
|
|
18
|
+
minWidth: 0,
|
|
19
|
+
maxWidth: '100%',
|
|
20
|
+
flexDirection: 'row',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
gap: 5,
|
|
23
|
+
},
|
|
24
|
+
readBadge: {
|
|
25
|
+
flex: 0,
|
|
26
|
+
alignSelf: 'flex-start',
|
|
27
|
+
minHeight: 22,
|
|
28
|
+
maxWidth: '100%',
|
|
29
|
+
borderWidth: 1,
|
|
30
|
+
borderRadius: 6,
|
|
31
|
+
paddingHorizontal: 7,
|
|
32
|
+
paddingVertical: 2,
|
|
33
|
+
},
|
|
34
|
+
readBadgeText: {
|
|
35
|
+
flex: 0,
|
|
36
|
+
flexShrink: 1,
|
|
37
|
+
fontSize: 11,
|
|
38
|
+
fontWeight: '800',
|
|
39
|
+
},
|
|
40
|
+
readBadgeIcon: {
|
|
41
|
+
flexShrink: 0,
|
|
42
|
+
},
|
|
43
|
+
readImage: {
|
|
44
|
+
width: 16,
|
|
45
|
+
height: 16,
|
|
46
|
+
flexShrink: 0,
|
|
47
|
+
},
|
|
16
48
|
readButtonForm: {
|
|
17
49
|
minHeight: 34,
|
|
18
50
|
borderWidth: 1,
|
|
@@ -25,8 +57,8 @@ const styles = StyleSheet.create({
|
|
|
25
57
|
flex: 1,
|
|
26
58
|
minWidth: 0,
|
|
27
59
|
color: '#0F172A',
|
|
28
|
-
fontSize:
|
|
29
|
-
fontWeight: '
|
|
60
|
+
fontSize: 13,
|
|
61
|
+
fontWeight: '600',
|
|
30
62
|
},
|
|
31
63
|
mutedText: {
|
|
32
64
|
color: '#94A3B8',
|
|
@@ -62,8 +94,8 @@ const styles = StyleSheet.create({
|
|
|
62
94
|
borderRadius: 8,
|
|
63
95
|
paddingHorizontal: 8,
|
|
64
96
|
color: '#0F172A',
|
|
65
|
-
fontSize:
|
|
66
|
-
fontWeight: '
|
|
97
|
+
fontSize: 13,
|
|
98
|
+
fontWeight: '600',
|
|
67
99
|
backgroundColor: '#FFFFFF',
|
|
68
100
|
},
|
|
69
101
|
formInput: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
Modal,
|
|
4
|
-
|
|
3
|
+
Modal,
|
|
4
|
+
Image,
|
|
5
|
+
ScrollView,
|
|
5
6
|
Text,
|
|
6
7
|
TextInput,
|
|
7
8
|
TouchableOpacity,
|
|
@@ -10,12 +11,14 @@ import {
|
|
|
10
11
|
import Icon from 'react-native-vector-icons/Feather';
|
|
11
12
|
import { getAllStores, useStore } from '@store';
|
|
12
13
|
import {
|
|
14
|
+
buildReadPresentationStyles,
|
|
13
15
|
buildOptionsFromColumn,
|
|
14
16
|
getColumnKey,
|
|
15
17
|
isEditableColumn,
|
|
16
18
|
mapOptions,
|
|
17
19
|
normalizeOptionKey,
|
|
18
20
|
normalizeText,
|
|
21
|
+
resolveCellPresentation,
|
|
19
22
|
resolveCellText,
|
|
20
23
|
resolveEditValue,
|
|
21
24
|
resolveStoreNameFromList,
|
|
@@ -140,11 +143,22 @@ const DefaultSelect = ({
|
|
|
140
143
|
];
|
|
141
144
|
}, [column, getOptionsForColumn, loadedItems, storeName]);
|
|
142
145
|
const selected = options.find(option => option.key === selectedKey);
|
|
143
|
-
const resolvedLabel =
|
|
144
|
-
displayValue ??
|
|
145
|
-
selected?.label ??
|
|
146
|
-
resolveCellText({ column, columns, row, storeName, value });
|
|
147
|
-
const
|
|
146
|
+
const resolvedLabel =
|
|
147
|
+
displayValue ??
|
|
148
|
+
selected?.label ??
|
|
149
|
+
resolveCellText({ column, columns, row, storeName, value });
|
|
150
|
+
const readPresentation = useMemo(
|
|
151
|
+
() => resolveCellPresentation({ column, columns, row, storeName, value }),
|
|
152
|
+
[column, columns, row, storeName, value],
|
|
153
|
+
);
|
|
154
|
+
const readPresentationStyles = useMemo(
|
|
155
|
+
() => buildReadPresentationStyles({
|
|
156
|
+
...readPresentation,
|
|
157
|
+
label: resolvedLabel,
|
|
158
|
+
}),
|
|
159
|
+
[readPresentation, resolvedLabel],
|
|
160
|
+
);
|
|
161
|
+
const canEdit = isEditableColumn(column) && typeof onStartEditing === 'function';
|
|
148
162
|
const isForm = variant === 'form';
|
|
149
163
|
const filteredOptions = useMemo(() => {
|
|
150
164
|
const query = normalizeText(searchText).toLowerCase();
|
|
@@ -281,20 +295,45 @@ const DefaultSelect = ({
|
|
|
281
295
|
activeOpacity={canEdit || isForm ? 0.78 : 1}
|
|
282
296
|
disabled={!canEdit && !isForm}
|
|
283
297
|
onPress={open}
|
|
284
|
-
>
|
|
285
|
-
<
|
|
286
|
-
style={[
|
|
287
|
-
inputStyles.
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
]}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
+
>
|
|
299
|
+
<View
|
|
300
|
+
style={[
|
|
301
|
+
inputStyles.readValueWrap,
|
|
302
|
+
readPresentationStyles.hasDecoration ? inputStyles.readBadge : null,
|
|
303
|
+
readPresentationStyles.badgeStyle,
|
|
304
|
+
]}
|
|
305
|
+
>
|
|
306
|
+
{readPresentation.image ? (
|
|
307
|
+
<Image
|
|
308
|
+
source={readPresentation.image}
|
|
309
|
+
style={inputStyles.readImage}
|
|
310
|
+
resizeMode="contain"
|
|
311
|
+
/>
|
|
312
|
+
) : null}
|
|
313
|
+
{readPresentationStyles.hasDecoration && readPresentation.icon && readPresentationStyles.color ? (
|
|
314
|
+
<Icon
|
|
315
|
+
style={inputStyles.readBadgeIcon}
|
|
316
|
+
name={readPresentation.icon}
|
|
317
|
+
size={12}
|
|
318
|
+
color={readPresentationStyles.color}
|
|
319
|
+
/>
|
|
320
|
+
) : null}
|
|
321
|
+
<Text
|
|
322
|
+
style={[
|
|
323
|
+
inputStyles.readText,
|
|
324
|
+
readPresentationStyles.hasDecoration ? inputStyles.readBadgeText : null,
|
|
325
|
+
resolvedLabel === '-' ? inputStyles.mutedText : null,
|
|
326
|
+
readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
|
|
327
|
+
readTextStyle,
|
|
328
|
+
]}
|
|
329
|
+
numberOfLines={numberOfLines}
|
|
330
|
+
>
|
|
331
|
+
{resolvedLabel || '-'}
|
|
332
|
+
</Text>
|
|
333
|
+
</View>
|
|
334
|
+
{saving ? (
|
|
335
|
+
<Text style={[inputStyles.savingText, { color: accentColor }]}>Salvando</Text>
|
|
336
|
+
) : canEdit || isForm ? (
|
|
298
337
|
<Icon style={inputStyles.editIcon} name="chevron-down" size={14} color="#64748B" />
|
|
299
338
|
) : null}
|
|
300
339
|
</TouchableOpacity>
|
|
@@ -322,24 +361,33 @@ const DefaultSelect = ({
|
|
|
322
361
|
|
|
323
362
|
<ScrollView keyboardShouldPersistTaps="handled">
|
|
324
363
|
{filteredOptions.length > 0 ? (
|
|
325
|
-
filteredOptions.map(option => {
|
|
326
|
-
const isSelected = option.key === selectedKey;
|
|
327
|
-
return (
|
|
328
|
-
<TouchableOpacity
|
|
329
|
-
key={`${option.key}_${option.label}`}
|
|
364
|
+
filteredOptions.map(option => {
|
|
365
|
+
const isSelected = option.key === selectedKey;
|
|
366
|
+
return (
|
|
367
|
+
<TouchableOpacity
|
|
368
|
+
key={`${option.key}_${option.label}`}
|
|
330
369
|
style={styles.optionRow}
|
|
331
370
|
activeOpacity={0.78}
|
|
332
371
|
onPress={() => selectOption(option)}
|
|
333
372
|
>
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
373
|
+
{option.image ? (
|
|
374
|
+
<Image
|
|
375
|
+
source={option.image}
|
|
376
|
+
style={inputStyles.readImage}
|
|
377
|
+
resizeMode="contain"
|
|
378
|
+
/>
|
|
379
|
+
) : null}
|
|
380
|
+
{isSelected || (option.icon && option.color) ? (
|
|
381
|
+
<Icon
|
|
382
|
+
name={isSelected ? 'check-circle' : option.icon}
|
|
383
|
+
size={15}
|
|
384
|
+
color={isSelected ? accentColor : option.color}
|
|
385
|
+
/>
|
|
386
|
+
) : null}
|
|
387
|
+
<Text style={[styles.optionText, option.color ? { color: option.color } : null]}>
|
|
388
|
+
{option.label}
|
|
389
|
+
</Text>
|
|
390
|
+
</TouchableOpacity>
|
|
343
391
|
);
|
|
344
392
|
})
|
|
345
393
|
) : (
|
|
@@ -128,7 +128,7 @@ export const resolveOptionLabel = (column, option, storeName = '') => {
|
|
|
128
128
|
export const resolveStoreNameFromList = list =>
|
|
129
129
|
typeof list === 'string' ? normalizeText(list).split('/')[0] || '' : '';
|
|
130
130
|
|
|
131
|
-
const filterItemsByListRequestParams = (items = [], column = null) => {
|
|
131
|
+
const filterItemsByListRequestParams = (items = [], column = null) => {
|
|
132
132
|
const requestParams =
|
|
133
133
|
column?.listRequestParams &&
|
|
134
134
|
typeof column.listRequestParams === 'object' &&
|
|
@@ -148,14 +148,17 @@ const filterItemsByListRequestParams = (items = [], column = null) => {
|
|
|
148
148
|
|
|
149
149
|
return normalizeText(item?.[key]) === normalizeText(expectedValue);
|
|
150
150
|
}),
|
|
151
|
-
);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const normalizeObject = value =>
|
|
155
|
+
value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
156
|
+
|
|
157
|
+
export const mapOptions = (column, items = [], storeName = '') => {
|
|
158
|
+
const seenKeys = new Set();
|
|
159
|
+
const options = [];
|
|
160
|
+
|
|
161
|
+
(Array.isArray(items) ? items : []).forEach(item => {
|
|
159
162
|
const formatted =
|
|
160
163
|
typeof column?.formatList === 'function'
|
|
161
164
|
? column.formatList(item, null, column)
|
|
@@ -166,12 +169,31 @@ export const mapOptions = (column, items = [], storeName = '') => {
|
|
|
166
169
|
if (dedupeKey && seenKeys.has(dedupeKey)) return;
|
|
167
170
|
if (dedupeKey) seenKeys.add(dedupeKey);
|
|
168
171
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
const formattedMeta = normalizeObject(formatted);
|
|
173
|
+
const itemMeta = normalizeObject(item);
|
|
174
|
+
const color = formattedMeta.color ?? itemMeta.color;
|
|
175
|
+
const icon =
|
|
176
|
+
formattedMeta.icon ??
|
|
177
|
+
formattedMeta.iconName ??
|
|
178
|
+
itemMeta.icon ??
|
|
179
|
+
itemMeta.iconName;
|
|
180
|
+
const image =
|
|
181
|
+
formattedMeta.image ??
|
|
182
|
+
formattedMeta.logo ??
|
|
183
|
+
formattedMeta.source ??
|
|
184
|
+
itemMeta.image ??
|
|
185
|
+
itemMeta.logo ??
|
|
186
|
+
itemMeta.source;
|
|
187
|
+
|
|
188
|
+
options.push({
|
|
189
|
+
...(color ? { color } : {}),
|
|
190
|
+
...(icon ? { icon } : {}),
|
|
191
|
+
...(image ? { image } : {}),
|
|
192
|
+
key,
|
|
193
|
+
label: resolveOptionLabel(column, item, storeName) || '-',
|
|
194
|
+
raw: item,
|
|
195
|
+
});
|
|
196
|
+
});
|
|
175
197
|
|
|
176
198
|
return options;
|
|
177
199
|
};
|
|
@@ -197,23 +219,148 @@ export const buildOptionsFromColumn = (column, getOptionsForColumn = null, store
|
|
|
197
219
|
);
|
|
198
220
|
};
|
|
199
221
|
|
|
200
|
-
export const resolveCellText = ({ column, columns = [], row, storeName, value }) => {
|
|
201
|
-
const fieldName = getColumnKey(column);
|
|
202
|
-
const rawValue = value ?? row?.[fieldName];
|
|
203
|
-
const formattedValue = formatStoreColumnValue({
|
|
222
|
+
export const resolveCellText = ({ column, columns = [], row, storeName, value }) => {
|
|
223
|
+
const fieldName = getColumnKey(column);
|
|
224
|
+
const rawValue = value ?? row?.[fieldName];
|
|
225
|
+
const formattedValue = formatStoreColumnValue({
|
|
204
226
|
columns: columns.length ? columns : [column],
|
|
205
227
|
fieldName,
|
|
206
228
|
row,
|
|
207
229
|
storeName,
|
|
208
230
|
value: rawValue,
|
|
209
231
|
});
|
|
210
|
-
|
|
211
|
-
return normalizeText(formattedValue) || '-';
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
232
|
+
|
|
233
|
+
return normalizeText(formattedValue) || '-';
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const resolveFormattedListMeta = (column, rawValue, row) => {
|
|
237
|
+
if (typeof column?.formatList !== 'function') {
|
|
238
|
+
return {};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const formatted = column.formatList(rawValue, row, column);
|
|
242
|
+
return normalizeObject(formatted);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const resolveStyleMeta = (column, row) => {
|
|
246
|
+
if (typeof column?.style !== 'function') {
|
|
247
|
+
return normalizeObject(column?.style);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return normalizeObject(column.style(row));
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export const resolveCellPresentation = ({
|
|
254
|
+
column,
|
|
255
|
+
columns = [],
|
|
256
|
+
row = {},
|
|
257
|
+
storeName = '',
|
|
258
|
+
value,
|
|
259
|
+
} = {}) => {
|
|
260
|
+
const fieldName = getColumnKey(column);
|
|
261
|
+
const rawValue = value ?? row?.[fieldName];
|
|
262
|
+
const rawMeta = normalizeObject(rawValue);
|
|
263
|
+
const formattedMeta = resolveFormattedListMeta(column, rawValue, row);
|
|
264
|
+
const styleMeta = resolveStyleMeta(column, row);
|
|
265
|
+
const label = resolveCellText({
|
|
266
|
+
column,
|
|
267
|
+
columns,
|
|
268
|
+
row,
|
|
269
|
+
storeName,
|
|
270
|
+
value,
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
backgroundColor:
|
|
275
|
+
formattedMeta.backgroundColor ??
|
|
276
|
+
formattedMeta.bgColor ??
|
|
277
|
+
rawMeta.backgroundColor ??
|
|
278
|
+
rawMeta.bgColor ??
|
|
279
|
+
styleMeta.backgroundColor ??
|
|
280
|
+
styleMeta.bgColor,
|
|
281
|
+
borderColor:
|
|
282
|
+
formattedMeta.borderColor ??
|
|
283
|
+
rawMeta.borderColor ??
|
|
284
|
+
styleMeta.borderColor,
|
|
285
|
+
color:
|
|
286
|
+
formattedMeta.color ??
|
|
287
|
+
rawMeta.color ??
|
|
288
|
+
rawMeta.statusColor ??
|
|
289
|
+
rawMeta.categoryColor ??
|
|
290
|
+
styleMeta.color,
|
|
291
|
+
icon:
|
|
292
|
+
formattedMeta.icon ??
|
|
293
|
+
formattedMeta.iconName ??
|
|
294
|
+
rawMeta.icon ??
|
|
295
|
+
rawMeta.iconName ??
|
|
296
|
+
styleMeta.icon ??
|
|
297
|
+
styleMeta.iconName,
|
|
298
|
+
image:
|
|
299
|
+
formattedMeta.image ??
|
|
300
|
+
formattedMeta.logo ??
|
|
301
|
+
formattedMeta.source ??
|
|
302
|
+
rawMeta.image ??
|
|
303
|
+
rawMeta.logo ??
|
|
304
|
+
rawMeta.source ??
|
|
305
|
+
styleMeta.image ??
|
|
306
|
+
styleMeta.logo ??
|
|
307
|
+
styleMeta.source,
|
|
308
|
+
label,
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const resolveAlphaColor = (color, opacity = 0.12) => {
|
|
313
|
+
const normalized = normalizeText(color);
|
|
314
|
+
const hex = normalized.match(/^#?([a-f\d]{6})$/i)?.[1];
|
|
315
|
+
|
|
316
|
+
if (!hex) return normalized || undefined;
|
|
317
|
+
|
|
318
|
+
const red = parseInt(hex.slice(0, 2), 16);
|
|
319
|
+
const green = parseInt(hex.slice(2, 4), 16);
|
|
320
|
+
const blue = parseInt(hex.slice(4, 6), 16);
|
|
321
|
+
|
|
322
|
+
return `rgba(${red}, ${green}, ${blue}, ${opacity})`;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export const buildReadPresentationStyles = presentation => {
|
|
326
|
+
const color = normalizeText(presentation?.color);
|
|
327
|
+
const icon = normalizeText(presentation?.icon);
|
|
328
|
+
const hasDecoration = Boolean(
|
|
329
|
+
color ||
|
|
330
|
+
normalizeText(presentation?.backgroundColor) ||
|
|
331
|
+
normalizeText(presentation?.borderColor) ||
|
|
332
|
+
(icon && color),
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
if (!hasDecoration || presentation?.label === '-') {
|
|
336
|
+
return {
|
|
337
|
+
badgeStyle: null,
|
|
338
|
+
color: null,
|
|
339
|
+
hasDecoration: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const backgroundColor =
|
|
344
|
+
presentation.backgroundColor ||
|
|
345
|
+
(color ? resolveAlphaColor(color, 0.1) : undefined);
|
|
346
|
+
const borderColor =
|
|
347
|
+
presentation.borderColor ||
|
|
348
|
+
presentation.backgroundColor ||
|
|
349
|
+
(color ? resolveAlphaColor(color, 0.32) : undefined);
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
badgeStyle: {
|
|
353
|
+
backgroundColor,
|
|
354
|
+
borderColor,
|
|
355
|
+
},
|
|
356
|
+
color: color || undefined,
|
|
357
|
+
hasDecoration: true,
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
export const resolveEditValue = (column, row, value) => {
|
|
362
|
+
const rawValue = value ?? row?.[getColumnKey(column)];
|
|
363
|
+
if (column?.list) {
|
|
217
364
|
return normalizeOptionKey(
|
|
218
365
|
typeof column?.formatList === 'function'
|
|
219
366
|
? column.formatList(rawValue, row, column)
|
|
@@ -96,10 +96,11 @@ const DefaultTable = ({
|
|
|
96
96
|
const isFocused = useIsFocused();
|
|
97
97
|
const configsSignatureRef = useRef('');
|
|
98
98
|
const { showError } = useMessage() || {};
|
|
99
|
-
const { themeColors } = useDefaultTableTheme(accentColor);
|
|
99
|
+
const { tableBorderColors, themeColors } = useDefaultTableTheme(accentColor);
|
|
100
|
+
const tablePanelBorderColor = tableBorderColors.containerBorderColor;
|
|
100
101
|
const floatingAddBackgroundColor =
|
|
101
|
-
themeColors.buttonBackground || themeColors.primary || accentColor
|
|
102
|
-
const floatingAddIconColor = themeColors.buttonText
|
|
102
|
+
themeColors.buttonBackground || themeColors.primary || accentColor;
|
|
103
|
+
const floatingAddIconColor = themeColors.buttonText;
|
|
103
104
|
const tablePreferenceScope = useMemo(
|
|
104
105
|
() =>
|
|
105
106
|
resolveDefaultTablePreferenceScope({
|
|
@@ -400,7 +401,8 @@ const DefaultTable = ({
|
|
|
400
401
|
style={[
|
|
401
402
|
styles.wrap,
|
|
402
403
|
{
|
|
403
|
-
|
|
404
|
+
borderWidth: tablePanelBorderColor ? 1 : 0,
|
|
405
|
+
borderColor: tablePanelBorderColor,
|
|
404
406
|
backgroundColor: themeColors.panelBackground,
|
|
405
407
|
},
|
|
406
408
|
]}
|
|
@@ -16,15 +16,14 @@ const styles = StyleSheet.create({
|
|
|
16
16
|
flex: 1,
|
|
17
17
|
width: '100%',
|
|
18
18
|
minHeight: 0,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
overflow: 'visible',
|
|
19
|
+
borderRadius: 8,
|
|
20
|
+
overflow: 'hidden',
|
|
22
21
|
position: 'relative',
|
|
23
22
|
},
|
|
24
23
|
toolbar: {
|
|
25
|
-
minHeight:
|
|
26
|
-
paddingHorizontal:
|
|
27
|
-
paddingVertical:
|
|
24
|
+
minHeight: 52,
|
|
25
|
+
paddingHorizontal: 16,
|
|
26
|
+
paddingVertical: 10,
|
|
28
27
|
borderBottomWidth: 1,
|
|
29
28
|
flexDirection: 'row',
|
|
30
29
|
flexWrap: 'nowrap',
|
|
@@ -51,7 +50,7 @@ const styles = StyleSheet.create({
|
|
|
51
50
|
flexDirection: 'row',
|
|
52
51
|
flexWrap: 'nowrap',
|
|
53
52
|
alignItems: 'center',
|
|
54
|
-
gap:
|
|
53
|
+
gap: 8,
|
|
55
54
|
flexShrink: 0,
|
|
56
55
|
marginLeft: 'auto',
|
|
57
56
|
},
|
|
@@ -76,8 +75,8 @@ const styles = StyleSheet.create({
|
|
|
76
75
|
marginLeft: 0,
|
|
77
76
|
},
|
|
78
77
|
toolbarSearch: {
|
|
79
|
-
width:
|
|
80
|
-
maxWidth:
|
|
78
|
+
width: 260,
|
|
79
|
+
maxWidth: 360,
|
|
81
80
|
flexShrink: 1,
|
|
82
81
|
},
|
|
83
82
|
toolbarSearchButton: {
|
|
@@ -111,10 +110,10 @@ const styles = StyleSheet.create({
|
|
|
111
110
|
fontWeight: '900',
|
|
112
111
|
},
|
|
113
112
|
toolbarButton: {
|
|
114
|
-
minWidth:
|
|
115
|
-
height:
|
|
116
|
-
borderRadius:
|
|
117
|
-
paddingHorizontal:
|
|
113
|
+
minWidth: 36,
|
|
114
|
+
height: 36,
|
|
115
|
+
borderRadius: 8,
|
|
116
|
+
paddingHorizontal: 10,
|
|
118
117
|
borderWidth: 1,
|
|
119
118
|
flexDirection: 'row',
|
|
120
119
|
alignItems: 'center',
|
|
@@ -124,8 +123,8 @@ const styles = StyleSheet.create({
|
|
|
124
123
|
toolbarButtonActive: {
|
|
125
124
|
},
|
|
126
125
|
toolbarAddButton: {
|
|
127
|
-
minWidth:
|
|
128
|
-
width:
|
|
126
|
+
minWidth: 36,
|
|
127
|
+
width: 36,
|
|
129
128
|
paddingHorizontal: 0,
|
|
130
129
|
},
|
|
131
130
|
floatingAddButton: {
|
|
@@ -283,8 +282,8 @@ const styles = StyleSheet.create({
|
|
|
283
282
|
minWidth: '100%',
|
|
284
283
|
minHeight: 0,
|
|
285
284
|
},
|
|
286
|
-
headerRow: {
|
|
287
|
-
minHeight:
|
|
285
|
+
headerRow: {
|
|
286
|
+
minHeight: 40,
|
|
288
287
|
width: '100%',
|
|
289
288
|
flexDirection: 'row',
|
|
290
289
|
alignItems: 'center',
|
|
@@ -292,8 +291,8 @@ const styles = StyleSheet.create({
|
|
|
292
291
|
borderBottomWidth: 1,
|
|
293
292
|
borderBottomColor: '#E2E8F0',
|
|
294
293
|
},
|
|
295
|
-
filterRow: {
|
|
296
|
-
minHeight:
|
|
294
|
+
filterRow: {
|
|
295
|
+
minHeight: 46,
|
|
297
296
|
width: '100%',
|
|
298
297
|
flexDirection: 'row',
|
|
299
298
|
alignItems: 'stretch',
|
|
@@ -301,25 +300,24 @@ const styles = StyleSheet.create({
|
|
|
301
300
|
borderBottomWidth: 1,
|
|
302
301
|
borderBottomColor: '#E2E8F0',
|
|
303
302
|
},
|
|
304
|
-
row: {
|
|
305
|
-
minHeight:
|
|
303
|
+
row: {
|
|
304
|
+
minHeight: 48,
|
|
306
305
|
width: '100%',
|
|
307
306
|
flexDirection: 'row',
|
|
308
307
|
alignItems: 'stretch',
|
|
309
308
|
borderBottomWidth: 1,
|
|
310
309
|
borderBottomColor: '#EEF2F7',
|
|
311
310
|
},
|
|
312
|
-
cell: {
|
|
313
|
-
minWidth: 118,
|
|
314
|
-
flexBasis: 118,
|
|
311
|
+
cell: {
|
|
312
|
+
minWidth: 118,
|
|
313
|
+
flexBasis: 118,
|
|
315
314
|
flexGrow: 1,
|
|
316
315
|
flexShrink: 0,
|
|
317
|
-
paddingHorizontal:
|
|
318
|
-
paddingVertical:
|
|
319
|
-
justifyContent: 'center',
|
|
320
|
-
borderRightWidth:
|
|
321
|
-
|
|
322
|
-
},
|
|
316
|
+
paddingHorizontal: 14,
|
|
317
|
+
paddingVertical: 10,
|
|
318
|
+
justifyContent: 'center',
|
|
319
|
+
borderRightWidth: 0,
|
|
320
|
+
},
|
|
323
321
|
identityCell: {
|
|
324
322
|
minWidth: 76,
|
|
325
323
|
flexBasis: 76,
|
|
@@ -377,13 +375,12 @@ const styles = StyleSheet.create({
|
|
|
377
375
|
flexBasis: 132,
|
|
378
376
|
flexGrow: 0.9,
|
|
379
377
|
},
|
|
380
|
-
headerText: {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
},
|
|
378
|
+
headerText: {
|
|
379
|
+
fontSize: 11,
|
|
380
|
+
fontWeight: '800',
|
|
381
|
+
letterSpacing: 0,
|
|
382
|
+
textTransform: 'uppercase',
|
|
383
|
+
},
|
|
387
384
|
sortableHeader: {
|
|
388
385
|
flexDirection: 'row',
|
|
389
386
|
alignItems: 'center',
|
|
@@ -404,11 +401,10 @@ const styles = StyleSheet.create({
|
|
|
404
401
|
fontSize: 11,
|
|
405
402
|
fontWeight: '700',
|
|
406
403
|
},
|
|
407
|
-
cellText: {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
},
|
|
404
|
+
cellText: {
|
|
405
|
+
fontSize: 13,
|
|
406
|
+
fontWeight: '600',
|
|
407
|
+
},
|
|
412
408
|
mutedCellText: {
|
|
413
409
|
color: '#94A3B8',
|
|
414
410
|
},
|
|
@@ -491,23 +487,30 @@ const styles = StyleSheet.create({
|
|
|
491
487
|
flexGrow: 1,
|
|
492
488
|
width: '100%',
|
|
493
489
|
},
|
|
494
|
-
cardItem: {
|
|
495
|
-
position: 'relative',
|
|
496
|
-
},
|
|
490
|
+
cardItem: {
|
|
491
|
+
position: 'relative',
|
|
492
|
+
},
|
|
493
|
+
cardItemWithActions: {
|
|
494
|
+
flexDirection: 'row',
|
|
495
|
+
alignItems: 'center',
|
|
496
|
+
gap: 8,
|
|
497
|
+
},
|
|
498
|
+
cardContent: {
|
|
499
|
+
flex: 1,
|
|
500
|
+
minWidth: 0,
|
|
501
|
+
},
|
|
497
502
|
cardActions: {
|
|
498
|
-
position: 'absolute',
|
|
499
|
-
right: 10,
|
|
500
|
-
bottom: 10,
|
|
501
503
|
flexDirection: 'row',
|
|
502
504
|
alignItems: 'center',
|
|
505
|
+
justifyContent: 'flex-end',
|
|
503
506
|
gap: 6,
|
|
507
|
+
flexShrink: 0,
|
|
504
508
|
},
|
|
505
509
|
cardActionGroup: {
|
|
506
|
-
position: 'absolute',
|
|
507
|
-
right: 8,
|
|
508
|
-
top: 8,
|
|
509
510
|
flexDirection: 'row',
|
|
510
511
|
alignItems: 'center',
|
|
512
|
+
justifyContent: 'flex-end',
|
|
513
|
+
alignSelf: 'flex-end',
|
|
511
514
|
gap: 6,
|
|
512
515
|
},
|
|
513
516
|
defaultCard: {
|
|
@@ -81,15 +81,24 @@ const DefaultTableCards = ({ storeName }) => {
|
|
|
81
81
|
|
|
82
82
|
if (typeof configs.renderCard === 'function') {
|
|
83
83
|
return (
|
|
84
|
-
<View
|
|
85
|
-
{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
84
|
+
<View
|
|
85
|
+
key={row?.['@id'] || row?.id}
|
|
86
|
+
style={[
|
|
87
|
+
styles.cardItem,
|
|
88
|
+
hasRowActions ? styles.cardItemWithActions : null,
|
|
89
|
+
rowStyleValue,
|
|
90
|
+
]}
|
|
91
|
+
>
|
|
92
|
+
<View style={styles.cardContent}>
|
|
93
|
+
{configs.renderCard({
|
|
94
|
+
item: row,
|
|
95
|
+
openEdit: () => configs.onEditRow?.(row),
|
|
96
|
+
openRow: hasRowPress ? () => configs.onRowPress(row) : null,
|
|
97
|
+
renderField,
|
|
98
|
+
renderValue,
|
|
99
|
+
row,
|
|
100
|
+
})}
|
|
101
|
+
</View>
|
|
93
102
|
{hasRowActions ? (
|
|
94
103
|
<View style={styles.cardActions}>
|
|
95
104
|
{customRowActions}
|
|
@@ -124,7 +124,16 @@ const DefaultTableFooter = ({ storeName }) => {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
return (
|
|
127
|
-
<View
|
|
127
|
+
<View
|
|
128
|
+
style={[
|
|
129
|
+
styles.footerBar,
|
|
130
|
+
{
|
|
131
|
+
backgroundColor: tableFooterBackgroundColor,
|
|
132
|
+
borderTopColor: tableFooterBorderColor,
|
|
133
|
+
borderTopWidth: tableFooterBorderColor ? 1 : 0,
|
|
134
|
+
},
|
|
135
|
+
]}
|
|
136
|
+
>
|
|
128
137
|
{summaryEntries.length > 0 ? (
|
|
129
138
|
<View style={styles.footerSummaryList}>
|
|
130
139
|
{summaryEntries.map(entry => (
|
|
@@ -23,7 +23,7 @@ import useDefaultTableTheme from './useDefaultTableTheme';
|
|
|
23
23
|
const DefaultTableRows = ({ storeName }) => {
|
|
24
24
|
const store = useStore(storeName);
|
|
25
25
|
const configs = store?.getters?.configs || {};
|
|
26
|
-
const { palette, resolvedAccentColor, themeTokens } = useDefaultTableTheme();
|
|
26
|
+
const { palette, resolvedAccentColor, tableBorderColors, themeTokens } = useDefaultTableTheme();
|
|
27
27
|
const columns = Array.isArray(store?.getters?.columns) ? store.getters.columns : [];
|
|
28
28
|
const visibleColumns = store?.getters?.visibleColumns || {};
|
|
29
29
|
const tableColumns = columns.filter(
|
|
@@ -38,7 +38,8 @@ const DefaultTableRows = ({ storeName }) => {
|
|
|
38
38
|
const emptyStateLabel = isLoading
|
|
39
39
|
? global.t?.t(storeName, 'label', 'loading')
|
|
40
40
|
: global.t?.t(storeName, 'label', 'empty');
|
|
41
|
-
const tableBorderColor =
|
|
41
|
+
const tableBorderColor = tableBorderColors.rowBorderColor;
|
|
42
|
+
const tableHeaderBorderColor = tableBorderColors.headerBorderColor || tableBorderColor;
|
|
42
43
|
const tableEvenColor = themeTokens.listItemEvenRow || themeTokens['bg-even-light'] || palette.background;
|
|
43
44
|
const tableHeaderColor = themeTokens['bg-headers-light'] || resolvedAccentColor;
|
|
44
45
|
const tableMutedColor = palette.textSecondary;
|
|
@@ -128,8 +129,12 @@ const DefaultTableRows = ({ storeName }) => {
|
|
|
128
129
|
<RowComponent
|
|
129
130
|
key={getRowKey(row)}
|
|
130
131
|
style={[
|
|
131
|
-
styles.row,
|
|
132
|
-
{
|
|
132
|
+
styles.row,
|
|
133
|
+
{
|
|
134
|
+
backgroundColor: rowBackgroundColor,
|
|
135
|
+
borderBottomColor: tableBorderColor,
|
|
136
|
+
borderBottomWidth: tableBorderColor ? 1 : 0,
|
|
137
|
+
},
|
|
133
138
|
rowStyleValue,
|
|
134
139
|
]}
|
|
135
140
|
{...rowPressProps}
|
|
@@ -209,7 +214,16 @@ const DefaultTableRows = ({ storeName }) => {
|
|
|
209
214
|
contentContainerStyle={styles.horizontalScrollContent}
|
|
210
215
|
>
|
|
211
216
|
<View style={styles.content}>
|
|
212
|
-
<View
|
|
217
|
+
<View
|
|
218
|
+
style={[
|
|
219
|
+
styles.headerRow,
|
|
220
|
+
{
|
|
221
|
+
backgroundColor: tableHeaderColor,
|
|
222
|
+
borderBottomColor: tableHeaderBorderColor,
|
|
223
|
+
borderBottomWidth: tableHeaderBorderColor ? 1 : 0,
|
|
224
|
+
},
|
|
225
|
+
]}
|
|
226
|
+
>
|
|
213
227
|
{tableColumns.map(column => {
|
|
214
228
|
const fieldName = getColumnKey(column);
|
|
215
229
|
const label = formatStoreColumnLabel({
|
|
@@ -267,7 +281,16 @@ const DefaultTableRows = ({ storeName }) => {
|
|
|
267
281
|
) : null}
|
|
268
282
|
</View>
|
|
269
283
|
{hasColumnFilters ? (
|
|
270
|
-
<View
|
|
284
|
+
<View
|
|
285
|
+
style={[
|
|
286
|
+
styles.filterRow,
|
|
287
|
+
{
|
|
288
|
+
backgroundColor: tableHeaderColor,
|
|
289
|
+
borderBottomColor: tableHeaderBorderColor,
|
|
290
|
+
borderBottomWidth: tableHeaderBorderColor ? 1 : 0,
|
|
291
|
+
},
|
|
292
|
+
]}
|
|
293
|
+
>
|
|
271
294
|
{tableColumns.map(column => {
|
|
272
295
|
const fieldName = getColumnKey(column);
|
|
273
296
|
|
|
@@ -20,13 +20,15 @@ const DefaultTableToolbar = ({ storeName }) => {
|
|
|
20
20
|
const showTotalItemsInCompactToolbar = configs.showTotalItemsInCompactToolbar === true;
|
|
21
21
|
const showTotalItemsInFooter = configs.showTotalItemsInFooter !== false;
|
|
22
22
|
const toolbarActions = Array.isArray(configs.toolbarActions) ? configs.toolbarActions : [];
|
|
23
|
-
const { toolbarColors } = useDefaultTableTheme();
|
|
23
|
+
const { tableBorderColors, toolbarColors } = useDefaultTableTheme();
|
|
24
24
|
const {
|
|
25
25
|
backgroundColor: toolbarBackgroundColor,
|
|
26
26
|
borderColor: toolbarBorderColor,
|
|
27
27
|
countBackgroundColor: toolbarCountBackgroundColor,
|
|
28
28
|
countTextColor: toolbarCountTextColor,
|
|
29
29
|
} = toolbarColors;
|
|
30
|
+
const resolvedToolbarBorderColor =
|
|
31
|
+
tableBorderColors.toolbarBorderColor || toolbarBorderColor;
|
|
30
32
|
const storeTotalItems = store?.getters?.totalItems;
|
|
31
33
|
const resolvedTotalItems = storeTotalItems;
|
|
32
34
|
const totalItemsNumber = Number(resolvedTotalItems);
|
|
@@ -63,7 +65,11 @@ const DefaultTableToolbar = ({ storeName }) => {
|
|
|
63
65
|
style={[
|
|
64
66
|
styles.toolbar,
|
|
65
67
|
shouldRenderCompactToolbarTotalItems ? styles.toolbarWithCompactTotal : null,
|
|
66
|
-
{
|
|
68
|
+
{
|
|
69
|
+
borderBottomColor: resolvedToolbarBorderColor,
|
|
70
|
+
borderBottomWidth: resolvedToolbarBorderColor ? 1 : 0,
|
|
71
|
+
backgroundColor: toolbarBackgroundColor,
|
|
72
|
+
},
|
|
67
73
|
]}
|
|
68
74
|
>
|
|
69
75
|
{shouldRenderCompactToolbarTotalItems ? (
|
|
@@ -1,20 +1,69 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { useStore } from '@store';
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useStore } from '@store';
|
|
3
|
+
|
|
4
|
+
const firstThemeToken = (themeColors, keys) =>
|
|
5
|
+
keys.map(key => themeColors?.[key]).find(Boolean);
|
|
6
|
+
|
|
7
|
+
const useDefaultTableTheme = (accentColor = null) => {
|
|
8
|
+
const themeStore = useStore('theme');
|
|
9
|
+
const rawThemeColors = themeStore?.getters?.colors || {};
|
|
10
|
+
const themeColors = useMemo(
|
|
11
|
+
() => ({ ...rawThemeColors }),
|
|
12
|
+
[rawThemeColors],
|
|
13
|
+
);
|
|
14
|
+
const themeTokens = useMemo(
|
|
15
|
+
() => ({ ...themeColors }),
|
|
16
|
+
[themeColors],
|
|
10
17
|
);
|
|
11
|
-
const palette = themeColors;
|
|
12
|
-
const resolvedAccentColor = accentColor ?? themeColors.primary;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const palette = themeColors;
|
|
19
|
+
const resolvedAccentColor = accentColor ?? themeColors.primary;
|
|
20
|
+
const tableBorderColors = {
|
|
21
|
+
containerBorderColor: firstThemeToken(themeColors, [
|
|
22
|
+
'tableContainerBorder',
|
|
23
|
+
'tableBorder',
|
|
24
|
+
'tableHeaderBorder',
|
|
25
|
+
'tableToolbarBorder',
|
|
26
|
+
'cardBorder',
|
|
27
|
+
'listItemBorder',
|
|
28
|
+
'dividerBorder',
|
|
29
|
+
'dividerBackground',
|
|
30
|
+
'inputBorder',
|
|
31
|
+
'panelBorder',
|
|
32
|
+
'border',
|
|
33
|
+
]),
|
|
34
|
+
headerBorderColor: firstThemeToken(themeColors, [
|
|
35
|
+
'tableHeaderBorder',
|
|
36
|
+
'tableToolbarBorder',
|
|
37
|
+
'tableBorder',
|
|
38
|
+
'dividerBorder',
|
|
39
|
+
'dividerBackground',
|
|
40
|
+
'listItemBorder',
|
|
41
|
+
'border',
|
|
42
|
+
]),
|
|
43
|
+
rowBorderColor: firstThemeToken(themeColors, [
|
|
44
|
+
'tableRowBorder',
|
|
45
|
+
'listItemBorder',
|
|
46
|
+
'dividerBorder',
|
|
47
|
+
'dividerBackground',
|
|
48
|
+
'tableBorder',
|
|
49
|
+
'border',
|
|
50
|
+
]),
|
|
51
|
+
toolbarBorderColor: firstThemeToken(themeColors, [
|
|
52
|
+
'tableToolbarBorder',
|
|
53
|
+
'tableHeaderBorder',
|
|
54
|
+
'toolbarBorder',
|
|
55
|
+
'tableBorder',
|
|
56
|
+
'dividerBorder',
|
|
57
|
+
'dividerBackground',
|
|
58
|
+
'border',
|
|
59
|
+
]),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
palette,
|
|
64
|
+
resolvedAccentColor,
|
|
65
|
+
tableBorderColors,
|
|
66
|
+
themeColors,
|
|
18
67
|
themeTokens,
|
|
19
68
|
checkboxBorderColor: themeColors.checkboxBorder,
|
|
20
69
|
checkboxSelectedMarkColor: themeColors.checkboxSelectedMark,
|
|
@@ -6,14 +6,18 @@ jest.mock('@store', () => ({
|
|
|
6
6
|
|
|
7
7
|
jest.mock('@controleonline/ui-common/src/utils/formatter.js', () => ({}));
|
|
8
8
|
|
|
9
|
-
jest.mock('@controleonline/ui-common/src/react/utils/storeColumns', () => ({
|
|
10
|
-
formatStoreColumnValue: ({value}) => value,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
const {
|
|
9
|
+
jest.mock('@controleonline/ui-common/src/react/utils/storeColumns', () => ({
|
|
10
|
+
formatStoreColumnValue: ({value}) => value?.status || value?.category || value,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
buildReadPresentationStyles,
|
|
15
|
+
mapOptions,
|
|
16
|
+
resolveCellPresentation,
|
|
17
|
+
} = require('../../../react/components/inputs/defaultInputUtils');
|
|
14
18
|
|
|
15
19
|
describe('defaultInputUtils', () => {
|
|
16
|
-
it('deduplicates list options by normalized key', () => {
|
|
20
|
+
it('deduplicates list options by normalized key', () => {
|
|
17
21
|
const column = {
|
|
18
22
|
formatList(item) {
|
|
19
23
|
return {
|
|
@@ -40,6 +44,73 @@ describe('defaultInputUtils', () => {
|
|
|
40
44
|
label: 'Cielo',
|
|
41
45
|
raw: {id: 4579, wallet: 'Cielo'},
|
|
42
46
|
},
|
|
43
|
-
]);
|
|
44
|
-
});
|
|
45
|
-
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('preserves option color and icon metadata from formatList', () => {
|
|
51
|
+
const column = {
|
|
52
|
+
formatList(item) {
|
|
53
|
+
return {
|
|
54
|
+
color: item.color,
|
|
55
|
+
icon: item.icon,
|
|
56
|
+
value: item.id,
|
|
57
|
+
label: item.status,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const options = mapOptions(column, [
|
|
63
|
+
{id: 1, status: 'Em rota', color: '#2563EB', icon: 'truck'},
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
expect(options).toEqual([
|
|
67
|
+
{
|
|
68
|
+
color: '#2563EB',
|
|
69
|
+
icon: 'truck',
|
|
70
|
+
key: '1',
|
|
71
|
+
label: 'Em rota',
|
|
72
|
+
raw: {id: 1, status: 'Em rota', color: '#2563EB', icon: 'truck'},
|
|
73
|
+
},
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('resolves table cell presentation from row value and column style', () => {
|
|
78
|
+
const presentation = resolveCellPresentation({
|
|
79
|
+
column: {
|
|
80
|
+
name: 'status',
|
|
81
|
+
style: row => ({color: row.status.color}),
|
|
82
|
+
},
|
|
83
|
+
row: {
|
|
84
|
+
status: {
|
|
85
|
+
status: 'Aprovado',
|
|
86
|
+
color: '#16A34A',
|
|
87
|
+
icon: 'check-circle',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
storeName: 'orders',
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(presentation).toEqual({
|
|
94
|
+
backgroundColor: undefined,
|
|
95
|
+
borderColor: undefined,
|
|
96
|
+
color: '#16A34A',
|
|
97
|
+
icon: 'check-circle',
|
|
98
|
+
image: undefined,
|
|
99
|
+
label: 'Aprovado',
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('builds subtle badge colors from resource colors', () => {
|
|
104
|
+
expect(buildReadPresentationStyles({
|
|
105
|
+
color: '#16A34A',
|
|
106
|
+
label: 'Aprovado',
|
|
107
|
+
})).toEqual({
|
|
108
|
+
badgeStyle: {
|
|
109
|
+
backgroundColor: 'rgba(22, 163, 74, 0.1)',
|
|
110
|
+
borderColor: 'rgba(22, 163, 74, 0.32)',
|
|
111
|
+
},
|
|
112
|
+
color: '#16A34A',
|
|
113
|
+
hasDecoration: true,
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|