@controleonline/ui-default 1.0.270 → 1.0.273

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 (100) hide show
  1. package/.github/workflows/integration-source-gate.yml +68 -0
  2. package/.github/workflows/manager-worker.yml +19 -0
  3. package/.github/workflows/publish-npm.yml +91 -0
  4. package/AGENTS.md +46 -50
  5. package/docs/technical/Contrato-de-colunas.md +67 -0
  6. package/docs/technical/Default-Components.md +76 -0
  7. package/docs/technical/DefaultForm.md +80 -0
  8. package/docs/technical/DefaultInput-e-DefaultSelect.md +73 -0
  9. package/docs/technical/DefaultTable.md +272 -0
  10. package/docs/wiki.md +1 -0
  11. package/package.json +4 -3
  12. package/scripts/validate-wiki-pointer.cjs +13 -0
  13. package/src/react/components/address/DefaultAddress.js +446 -0
  14. package/src/react/components/address/DefaultAddress.styles.js +133 -0
  15. package/src/react/components/address/DefaultAddressCoordFields.js +59 -0
  16. package/src/react/components/address/DefaultAddressMapPane.js +55 -0
  17. package/src/react/components/address/LatLonReadonlyFields.js +51 -0
  18. package/src/react/components/address/defaultAddressHelpers.js +163 -0
  19. package/src/react/components/address/defaultAddressStyles.js +148 -0
  20. package/src/react/components/address/defaultAddressUtils.js +129 -0
  21. package/src/react/components/extra-data/DefaultExtraData.js +152 -0
  22. package/src/react/components/extra-data/DefaultExtraData.styles.js +61 -0
  23. package/src/react/components/files/DefaultFile.js +231 -46
  24. package/src/react/components/files/DefaultFileColumn.js +123 -0
  25. package/src/react/components/files/DefaultFileColumn.styles.js +52 -0
  26. package/src/react/components/files/DefaultFileColumn.utils.js +104 -0
  27. package/src/react/components/filters/CompactFilterSelector.js +51 -35
  28. package/src/react/components/filters/DefaultColumnFilter.js +60 -48
  29. package/src/react/components/filters/DefaultExternalFilters.js +324 -265
  30. package/src/react/components/filters/filterValue.js +65 -0
  31. package/src/react/components/form/DefaultForm.js +99 -79
  32. package/src/react/components/help/DefaultTooltip.js +48 -12
  33. package/src/react/components/help/DefaultTooltip.styles.js +20 -0
  34. package/src/react/components/inputs/DefaultColorInput.js +153 -0
  35. package/src/react/components/inputs/DefaultFeatherIconPicker.js +146 -0
  36. package/src/react/components/inputs/DefaultFeatherIconPicker.styles.js +113 -0
  37. package/src/react/components/inputs/DefaultInput.js +296 -141
  38. package/src/react/components/inputs/DefaultInput.styles.js +26 -0
  39. package/src/react/components/inputs/DefaultSelect.js +134 -123
  40. package/src/react/components/inputs/defaultInputUtils.js +262 -213
  41. package/src/react/components/map/DefaultMap.native.js +73 -73
  42. package/src/react/components/map/DefaultMap.shared.js +911 -762
  43. package/src/react/components/map/DefaultMap.web.js +124 -68
  44. package/src/react/components/table/DefaultColumnMenu.js +22 -3
  45. package/src/react/components/table/DefaultDebug.js +44 -37
  46. package/src/react/components/table/DefaultSearchModal.js +9 -1
  47. package/src/react/components/table/DefaultTable.grouping.js +98 -0
  48. package/src/react/components/table/DefaultTable.js +217 -111
  49. package/src/react/components/table/DefaultTable.styles.js +369 -310
  50. package/src/react/components/table/DefaultTable.utils.js +38 -4
  51. package/src/react/components/table/DefaultTableBody.js +13 -8
  52. package/src/react/components/table/DefaultTableCards.js +20 -1
  53. package/src/react/components/table/DefaultTableControls.js +180 -205
  54. package/src/react/components/table/DefaultTableImportModal.js +108 -0
  55. package/src/react/components/table/DefaultTableInput.js +1 -0
  56. package/src/react/components/table/DefaultTableRowActions.js +1 -1
  57. package/src/react/components/table/DefaultTableRows.js +357 -325
  58. package/src/react/components/table/DefaultTableSearch.js +28 -5
  59. package/src/react/components/table/DefaultTableToolbar.js +92 -3
  60. package/src/react/components/table/useDefaultTablePagination.js +56 -7
  61. package/src/react/components/table/useDefaultTableStoreSync.js +164 -0
  62. package/src/react/components/upload/DefaultUpload.js +406 -0
  63. package/src/react/components/upload/DefaultUpload.styles.js +153 -0
  64. package/src/react/components/upload/DefaultUploadAttachmentsList.js +146 -0
  65. package/src/react/components/upload/DefaultUploadManagerModal.js +247 -0
  66. package/src/react/components/upload/defaultUploadHelpers.js +108 -0
  67. package/src/react/components/upload/defaultUploadLibrary.js +248 -0
  68. package/src/react/components/upload/fileUpload.js +93 -0
  69. package/src/react/hooks/usePostalCodeLookup.js +159 -0
  70. package/src/react/index.js +6 -0
  71. package/src/react/services/addressFormUtils.js +262 -0
  72. package/src/react/services/addressGeo.js +230 -0
  73. package/src/react/utils/tableVisibleColumnsPreferences.js +113 -15
  74. package/src/tests/react/components/address/defaultAddressHelpers.test.js +104 -0
  75. package/src/tests/react/components/files/DefaultFile.test.js +22 -6
  76. package/src/tests/react/components/files/DefaultFileColumn.company.test.js +24 -0
  77. package/src/tests/react/components/form/DefaultForm.test.js +123 -0
  78. package/src/tests/react/components/help/DefaultTooltip.test.js +93 -0
  79. package/src/tests/react/components/inputs/DefaultSelect.test.js +108 -79
  80. package/src/tests/react/components/table/DefaultTable.grouping.test.js +49 -0
  81. package/src/tests/react/components/table/DefaultTable.test.js +53 -2
  82. package/src/tests/react/components/table/DefaultTable.utils.test.js +10 -0
  83. package/src/tests/react/components/table/DefaultTableControls.filters.test.mjs +21 -0
  84. package/src/tests/react/components/table/DefaultTableRowActions.test.js +23 -0
  85. package/src/tests/react/components/table/DefaultTableRows.rowActions.test.js +152 -0
  86. package/src/tests/react/components/table/resolveRowBackgroundColor.test.mjs +45 -0
  87. package/src/tests/react/components/table/useDefaultTableStoreSync.test.js +161 -0
  88. package/src/tests/react/components/upload/DefaultUpload.test.js +353 -0
  89. package/src/tests/react/components/upload/defaultUploadLibrary.test.js +104 -0
  90. package/src/tests/react/components/upload/peopleMediaLibraryPreview.test.mjs +57 -0
  91. package/src/tests/react/filters/filterValue.test.js +46 -0
  92. package/src/tests/react/hooks/usePostalCodeLookup.test.js +107 -0
  93. package/src/tests/react/inputs/defaultInputUtils.test.js +9 -1
  94. package/src/tests/react/services/SMOKE-637-cep-hydrate.md +45 -0
  95. package/src/tests/react/services/addressFormUtils.test.js +179 -0
  96. package/src/tests/react/services/addressGeoLookup.async.test.js +104 -0
  97. package/src/tests/react/services/addressGeoLookup.test.js +105 -0
  98. package/src/tests/react/services/smoke-637/form-cep-12941040.png +0 -0
  99. package/src/tests/react/services/smoke-637/index.html +132 -0
  100. package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +96 -49
@@ -1,22 +1,32 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
- import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native';
2
+ import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native';
3
+ import DefaultExtraData from '../extra-data/DefaultExtraData';
4
+ import DefaultFileColumn from '../files/DefaultFileColumn';
3
5
  import Icon from 'react-native-vector-icons/Feather';
4
- import {
5
- buildReadPresentationStyles,
6
- getColumnKey,
7
- isDateLikeColumn,
8
- isEditableColumn,
9
- isValidFeatherIcon,
10
- normalizeText,
11
- resolveCellPresentation,
12
- resolveCellText,
13
- resolveEditValue,
14
- } from './defaultInputUtils';
15
- import DefaultDateInput from './DefaultDateInput';
16
- import DefaultSelect from './DefaultSelect';
17
- import styles from './DefaultInput.styles';
18
-
19
- const DefaultInput = ({
6
+ import {
7
+ buildReadPresentationStyles,
8
+ getColumnKey,
9
+ isColorColumn,
10
+ isDateLikeColumn,
11
+ isEditableColumn,
12
+ isExtraDataColumn,
13
+ isFileColumn,
14
+ isIconColumn,
15
+ isValidFeatherIcon,
16
+ normalizeText,
17
+ resolveCellPresentation,
18
+ resolveCellText,
19
+ resolveEditValue,
20
+ } from './defaultInputUtils';
21
+ import DefaultColorInput from './DefaultColorInput';
22
+ import DefaultDateInput from './DefaultDateInput';
23
+ import DefaultFeatherIconPicker, {
24
+ normalizeFeatherIconName,
25
+ } from './DefaultFeatherIconPicker';
26
+ import DefaultSelect from './DefaultSelect';
27
+ import styles from './DefaultInput.styles';
28
+
29
+ const DefaultInput = ({
20
30
  accentColor = '#2563EB',
21
31
  autoFocus = true,
22
32
  autoSave = true,
@@ -24,17 +34,18 @@ const DefaultInput = ({
24
34
  columns = [],
25
35
  containerStyle = null,
26
36
  displayValue,
37
+ defaultColor = '',
27
38
  editing = false,
28
39
  getOptionsForColumn = null,
29
40
  inputStyle = null,
30
41
  label = '',
31
42
  numberOfLines = 1,
32
- onBeforeOpen = null,
33
- onCancelEditing = null,
34
- onChangeValue = null,
35
- onSave = null,
36
- onSearchChange = null,
37
- onStartEditing = null,
43
+ onBeforeOpen = null,
44
+ onCancelEditing = null,
45
+ onChangeValue = null,
46
+ onSave = null,
47
+ onSearchChange = null,
48
+ onStartEditing = null,
38
49
  readTextStyle = null,
39
50
  row = {},
40
51
  saving = false,
@@ -44,6 +55,9 @@ const DefaultInput = ({
44
55
  variant = 'cell',
45
56
  }) => {
46
57
  const fieldName = getColumnKey(column);
58
+ const isExtraDataField = isExtraDataColumn(column) || ['extradata', 'extra_data'].includes(
59
+ normalizeText(fieldName).replace(/[^a-zA-Z0-9_]/g, '').toLowerCase(),
60
+ );
47
61
  const isForm = variant === 'form';
48
62
  const canEdit = isEditableColumn(column) && typeof onStartEditing === 'function';
49
63
  const editValue = useMemo(
@@ -51,25 +65,25 @@ const DefaultInput = ({
51
65
  [column, row, value],
52
66
  );
53
67
  const [draftValue, setDraftValue] = useState(editValue);
54
- const resolvedLabel =
55
- displayValue ?? resolveCellText({ column, columns, row, storeName, value });
56
- const readPresentation = useMemo(
57
- () => resolveCellPresentation({ column, columns, row, storeName, value }),
58
- [column, columns, row, storeName, value],
59
- );
60
- const readPresentationStyles = useMemo(
61
- () => buildReadPresentationStyles({
62
- ...readPresentation,
63
- label: resolvedLabel,
64
- }),
65
- [readPresentation, resolvedLabel],
66
- );
68
+ const resolvedLabel =
69
+ displayValue ?? resolveCellText({ column, columns, row, storeName, value });
70
+ const readPresentation = useMemo(
71
+ () => resolveCellPresentation({ column, columns, row, storeName, value }),
72
+ [column, columns, row, storeName, value],
73
+ );
74
+ const readPresentationStyles = useMemo(
75
+ () => buildReadPresentationStyles({
76
+ ...readPresentation,
77
+ label: resolvedLabel,
78
+ }),
79
+ [readPresentation, resolvedLabel],
80
+ );
67
81
 
68
82
  useEffect(() => {
69
83
  setDraftValue(editValue);
70
84
  }, [editValue, editing]);
71
85
 
72
- if (column?.list) {
86
+ if (column?.list) {
73
87
  return (
74
88
  <DefaultSelect
75
89
  accentColor={accentColor}
@@ -96,37 +110,150 @@ const DefaultInput = ({
96
110
  variant={variant}
97
111
  />
98
112
  );
99
- }
100
-
101
- if (isDateLikeColumn(column)) {
102
- return (
103
- <DefaultDateInput
104
- accentColor={accentColor}
105
- autoFocus={autoFocus}
106
- autoSave={autoSave}
107
- column={column}
108
- columns={columns}
109
- containerStyle={containerStyle}
110
- displayValue={displayValue}
111
- editing={editing}
112
- inputStyle={inputStyle}
113
- label={label}
114
- numberOfLines={numberOfLines}
115
- onCancelEditing={onCancelEditing}
116
- onChangeValue={onChangeValue}
117
- onSave={onSave}
118
- onSearchChange={onSearchChange}
119
- onStartEditing={onStartEditing}
120
- readTextStyle={readTextStyle}
121
- row={row}
122
- saving={saving}
123
- showLabel={showLabel}
124
- storeName={storeName}
125
- value={value}
126
- variant={variant}
127
- />
128
- );
129
- }
113
+ }
114
+
115
+ if (isColorColumn(column)) {
116
+ return (
117
+ <DefaultColorInput
118
+ accentColor={accentColor}
119
+ autoFocus={autoFocus}
120
+ autoSave={autoSave}
121
+ column={column}
122
+ containerStyle={containerStyle}
123
+ defaultColor={defaultColor}
124
+ editing={editing}
125
+ inputStyle={inputStyle}
126
+ label={label}
127
+ onCancelEditing={onCancelEditing}
128
+ onChangeValue={onChangeValue}
129
+ onSave={onSave}
130
+ onStartEditing={onStartEditing}
131
+ row={row}
132
+ saving={saving}
133
+ showLabel={showLabel}
134
+ storeName={storeName}
135
+ value={value}
136
+ variant={variant}
137
+ />
138
+ );
139
+ }
140
+
141
+ if (isIconColumn(column)) {
142
+ const fieldNameIcon = getColumnKey(column);
143
+ const rawIconValue = value ?? row?.[fieldNameIcon];
144
+ const selectedIcon = normalizeFeatherIconName(rawIconValue);
145
+ const isFormIcon = variant === 'form';
146
+ const canEditIcon = isEditableColumn(column) && typeof onStartEditing === 'function';
147
+
148
+ const commitIcon = nextIcon => {
149
+ const normalized = normalizeFeatherIconName(nextIcon);
150
+ if (autoSave) {
151
+ onSave?.(normalized);
152
+ return;
153
+ }
154
+ onChangeValue?.(normalized);
155
+ };
156
+
157
+ if (!editing && !isFormIcon) {
158
+ return (
159
+ <View style={[styles.wrap, containerStyle]}>
160
+ {showLabel ? (
161
+ <Text style={styles.fieldLabel}>{label || column?.label || fieldNameIcon}</Text>
162
+ ) : null}
163
+ <TouchableOpacity
164
+ style={styles.readButton}
165
+ activeOpacity={canEditIcon ? 0.78 : 1}
166
+ disabled={!canEditIcon}
167
+ onPress={() => onStartEditing?.()}
168
+ >
169
+ <View style={styles.readValueWrap}>
170
+ <Icon
171
+ name={selectedIcon || 'search'}
172
+ size={14}
173
+ color={selectedIcon ? '#0F172A' : '#94A3B8'}
174
+ />
175
+ <Text
176
+ style={[
177
+ styles.readText,
178
+ !selectedIcon ? styles.mutedText : null,
179
+ readTextStyle,
180
+ ]}
181
+ numberOfLines={numberOfLines}
182
+ >
183
+ {selectedIcon || '-'}
184
+ </Text>
185
+ </View>
186
+ {saving ? (
187
+ <Text style={[styles.savingText, { color: accentColor }]}>Salvando</Text>
188
+ ) : canEditIcon ? (
189
+ <Icon style={styles.editIcon} name="edit-2" size={13} color="#64748B" />
190
+ ) : null}
191
+ </TouchableOpacity>
192
+ </View>
193
+ );
194
+ }
195
+
196
+ return (
197
+ <View style={[styles.wrap, containerStyle]}>
198
+ {showLabel ? (
199
+ <Text style={styles.fieldLabel}>{label || column?.label || fieldNameIcon}</Text>
200
+ ) : null}
201
+ <View style={styles.editingWrap}>
202
+ <View style={styles.editingRow}>
203
+ <DefaultFeatherIconPicker
204
+ value={selectedIcon}
205
+ onChange={commitIcon}
206
+ placeholder={
207
+ global.t?.t(storeName, 'input', column?.label || fieldNameIcon) ||
208
+ 'Buscar icone'
209
+ }
210
+ style={[isFormIcon ? styles.formInput : null, inputStyle, { flex: 1 }]}
211
+ />
212
+ {!isFormIcon ? (
213
+ <TouchableOpacity
214
+ style={styles.cancelButton}
215
+ activeOpacity={0.8}
216
+ onPress={onCancelEditing}
217
+ >
218
+ <Icon name="x" size={14} color="#64748B" />
219
+ </TouchableOpacity>
220
+ ) : null}
221
+ </View>
222
+ {saving ? <Text style={styles.savingText}>Salvando</Text> : null}
223
+ </View>
224
+ </View>
225
+ );
226
+ }
227
+
228
+ if (isDateLikeColumn(column)) {
229
+ return (
230
+ <DefaultDateInput
231
+ accentColor={accentColor}
232
+ autoFocus={autoFocus}
233
+ autoSave={autoSave}
234
+ column={column}
235
+ columns={columns}
236
+ containerStyle={containerStyle}
237
+ displayValue={displayValue}
238
+ editing={editing}
239
+ inputStyle={inputStyle}
240
+ label={label}
241
+ numberOfLines={numberOfLines}
242
+ onCancelEditing={onCancelEditing}
243
+ onChangeValue={onChangeValue}
244
+ onSave={onSave}
245
+ onSearchChange={onSearchChange}
246
+ onStartEditing={onStartEditing}
247
+ readTextStyle={readTextStyle}
248
+ row={row}
249
+ saving={saving}
250
+ showLabel={showLabel}
251
+ storeName={storeName}
252
+ value={value}
253
+ variant={variant}
254
+ />
255
+ );
256
+ }
130
257
 
131
258
  const saveDraft = () => {
132
259
  if (autoSave) {
@@ -142,81 +269,109 @@ const DefaultInput = ({
142
269
  if (!autoSave) onChangeValue?.(nextValue);
143
270
  };
144
271
 
145
- if (!editing && !isForm) {
146
- const readIconName = isValidFeatherIcon(readPresentation.icon)
147
- ? readPresentation.icon
148
- : '';
149
- const shouldRenderIconFallbackText = Boolean(
150
- readPresentationStyles.hasDecoration &&
151
- !readIconName &&
152
- readPresentationStyles.color &&
153
- normalizeText(resolvedLabel) &&
154
- resolvedLabel !== '-',
155
- );
156
-
157
- return (
158
- <View style={[styles.wrap, containerStyle]}>
159
- {showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
160
- <TouchableOpacity
272
+ if (!editing && !isForm) {
273
+ if (isExtraDataField) {
274
+ return (
275
+ <View style={[styles.wrap, containerStyle]}>
276
+ {showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
277
+ <DefaultExtraData
278
+ column={column}
279
+ row={row}
280
+ value={value ?? row?.[fieldName]}
281
+ variant={variant}
282
+ />
283
+ </View>
284
+ );
285
+ }
286
+
287
+ if (isFileColumn(column)) {
288
+ return (
289
+ <View style={[styles.wrap, containerStyle]}>
290
+ {showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
291
+ <DefaultFileColumn
292
+ column={column}
293
+ row={row}
294
+ value={value}
295
+ variant={variant}
296
+ />
297
+ </View>
298
+ );
299
+ }
300
+
301
+ const readIconName = isValidFeatherIcon(readPresentation.icon)
302
+ ? readPresentation.icon
303
+ : '';
304
+ const shouldRenderIconFallbackText = Boolean(
305
+ readPresentationStyles.hasDecoration &&
306
+ !readIconName &&
307
+ readPresentationStyles.color &&
308
+ normalizeText(resolvedLabel) &&
309
+ resolvedLabel !== '-',
310
+ );
311
+
312
+ return (
313
+ <View style={[styles.wrap, containerStyle]}>
314
+ {showLabel ? <Text style={styles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
315
+ <TouchableOpacity
161
316
  style={styles.readButton}
162
317
  activeOpacity={canEdit ? 0.78 : 1}
163
- disabled={!canEdit}
164
- onPress={() => onStartEditing?.()}
165
- >
166
- {shouldRenderIconFallbackText ? (
167
- <Text
168
- style={[
169
- styles.readText,
170
- styles.readTextBadge,
171
- readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
172
- readTextStyle,
173
- ]}
174
- numberOfLines={numberOfLines}
175
- >
176
- {resolvedLabel}
177
- </Text>
178
- ) : (
179
- <View
180
- style={[
181
- styles.readValueWrap,
182
- readPresentationStyles.hasDecoration ? styles.readBadge : null,
183
- readPresentationStyles.badgeStyle,
184
- ]}
185
- >
186
- {readPresentation.image ? (
187
- <Image
188
- source={readPresentation.image}
189
- style={styles.readImage}
190
- resizeMode="contain"
191
- />
192
- ) : null}
193
- {readPresentationStyles.hasDecoration && readIconName && readPresentationStyles.color ? (
194
- <Icon
195
- style={styles.readBadgeIcon}
196
- name={readIconName}
197
- size={12}
198
- color={readPresentationStyles.color}
199
- />
200
- ) : null}
201
- <Text
202
- style={[
203
- styles.readText,
204
- readPresentationStyles.hasDecoration ? styles.readBadgeText : null,
205
- resolvedLabel === '-' ? styles.mutedText : null,
206
- readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
207
- readTextStyle,
208
- ]}
209
- numberOfLines={numberOfLines}
210
- >
211
- {column?.prefix || ''}
212
- {resolvedLabel || '-'}
213
- {column?.sufix || column?.suffix || ''}
214
- </Text>
215
- </View>
216
- )}
217
- {saving ? (
218
- <Text style={[styles.savingText, { color: accentColor }]}>Salvando</Text>
219
- ) : canEdit ? (
318
+ disabled={!canEdit}
319
+ onPress={() => onStartEditing?.()}
320
+ >
321
+ {shouldRenderIconFallbackText ? (
322
+ <Text
323
+ style={[
324
+ styles.readText,
325
+ styles.readTextBadge,
326
+ readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
327
+ readTextStyle,
328
+ ]}
329
+ numberOfLines={numberOfLines}
330
+ >
331
+ {resolvedLabel}
332
+ </Text>
333
+ ) : (
334
+ <View
335
+ style={[
336
+ styles.readValueWrap,
337
+ readPresentationStyles.hasDecoration ? styles.readBadge : null,
338
+ readPresentationStyles.badgeStyle,
339
+ ]}
340
+ >
341
+ {readPresentation.image ? (
342
+ <Image
343
+ source={readPresentation.image}
344
+ style={styles.readImage}
345
+ resizeMode="contain"
346
+ />
347
+ ) : null}
348
+ {readPresentationStyles.hasDecoration && readIconName && readPresentationStyles.color ? (
349
+ <Icon
350
+ style={styles.readBadgeIcon}
351
+ name={readIconName}
352
+ size={12}
353
+ color={readPresentationStyles.color}
354
+ />
355
+ ) : null}
356
+ <Text
357
+ style={[
358
+ styles.readText,
359
+ readPresentationStyles.hasDecoration ? styles.readBadgeText : null,
360
+ resolvedLabel === '-' ? styles.mutedText : null,
361
+ readPresentationStyles.color ? { color: readPresentationStyles.color } : null,
362
+ readTextStyle,
363
+ ]}
364
+ numberOfLines={numberOfLines}
365
+ >
366
+ {column?.prefix || ''}
367
+ {resolvedLabel || '-'}
368
+ {column?.sufix || column?.suffix || ''}
369
+ </Text>
370
+ </View>
371
+ )}
372
+ {saving ? (
373
+ <Text style={[styles.savingText, { color: accentColor }]}>Salvando</Text>
374
+ ) : canEdit ? (
220
375
  <Icon style={styles.editIcon} name="edit-2" size={13} color="#64748B" />
221
376
  ) : null}
222
377
  </TouchableOpacity>
@@ -104,6 +104,32 @@ const styles = StyleSheet.create({
104
104
  fontWeight: '600',
105
105
  backgroundColor: '#FFFFFF',
106
106
  },
107
+ colorInput: {
108
+ fontFamily: 'monospace',
109
+ textTransform: 'uppercase',
110
+ },
111
+ invalidColorInput: {
112
+ borderColor: '#DC2626',
113
+ },
114
+ colorPreview: {
115
+ width: 18,
116
+ height: 18,
117
+ flexShrink: 0,
118
+ borderWidth: 1,
119
+ borderColor: '#CBD5E1',
120
+ borderRadius: 5,
121
+ },
122
+ colorDefaultButton: {
123
+ width: 28,
124
+ height: 28,
125
+ flexShrink: 0,
126
+ alignItems: 'center',
127
+ justifyContent: 'center',
128
+ borderWidth: 1,
129
+ borderColor: '#CBD5E1',
130
+ borderRadius: 14,
131
+ backgroundColor: '#FFFFFF',
132
+ },
107
133
  formInput: {
108
134
  height: 34,
109
135
  borderColor: '#CBD5E1',