@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,13 +1,13 @@
1
- import React, { useCallback, useMemo, useRef, useState } from 'react';
2
- import {
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import {
3
3
  Modal,
4
4
  Image,
5
5
  ScrollView,
6
- Text,
7
- TextInput,
8
- TouchableOpacity,
9
- View,
10
- } from 'react-native';
6
+ Text,
7
+ TextInput,
8
+ TouchableOpacity,
9
+ View,
10
+ } from 'react-native';
11
11
  import Icon from 'react-native-vector-icons/Feather';
12
12
  import { getAllStores, useStore } from '@store';
13
13
  import {
@@ -71,11 +71,13 @@ const resolveColumnListLoadParams = ({
71
71
  column,
72
72
  currentCompanyId,
73
73
  requestParams = {},
74
+ row = {},
74
75
  searchValue = '',
76
+ variant = 'cell',
75
77
  }) => {
76
78
  const listStoreName = resolveStoreNameFromList(column?.list);
77
79
  const resolvedCustomParams = typeof column?.listRequestParams === 'function'
78
- ? column.listRequestParams({ currentCompanyId, requestParams })
80
+ ? column.listRequestParams({ currentCompanyId, requestParams, row, variant })
79
81
  : column?.listRequestParams;
80
82
  const customParams =
81
83
  resolvedCustomParams &&
@@ -92,31 +94,31 @@ const resolveColumnListLoadParams = ({
92
94
  : {}),
93
95
  };
94
96
  };
95
-
96
- const DefaultSelect = ({
97
- accentColor = '#2563EB',
98
- autoSave = true,
99
- column,
100
- columns = [],
101
- containerStyle = null,
102
- displayValue,
103
- editing = false,
104
- getOptionsForColumn = null,
105
- label = '',
106
- numberOfLines = 1,
107
- onBeforeOpen = null,
97
+
98
+ const DefaultSelect = ({
99
+ accentColor = '#2563EB',
100
+ autoSave = true,
101
+ column,
102
+ columns = [],
103
+ containerStyle = null,
104
+ displayValue,
105
+ editing = false,
106
+ getOptionsForColumn = null,
107
+ label = '',
108
+ numberOfLines = 1,
109
+ onBeforeOpen = null,
108
110
  onCancelEditing = null,
109
111
  onChangeValue = null,
110
112
  onSave = null,
111
113
  onSearchChange = null,
112
114
  onStartEditing = null,
113
- readTextStyle = null,
114
- row = {},
115
- saving = false,
116
- showLabel = false,
117
- storeName = '',
118
- value,
119
- variant = 'cell',
115
+ readTextStyle = null,
116
+ row = {},
117
+ saving = false,
118
+ showLabel = false,
119
+ storeName = '',
120
+ value,
121
+ variant = 'cell',
120
122
  }) => {
121
123
  const peopleStore = useStore('people');
122
124
  const ownerStore = useStore(storeName);
@@ -126,9 +128,9 @@ const DefaultSelect = ({
126
128
  const [searchText, setSearchText] = useState('');
127
129
  const currentCompanyId = peopleStore?.getters?.currentCompany?.id;
128
130
  const requestParams = ownerStore?.getters?.configs?.requestParams || {};
129
-
130
- const fieldName = getColumnKey(column);
131
- const selectedKey = normalizeOptionKey(value ?? resolveEditValue(column, row));
131
+
132
+ const fieldName = getColumnKey(column);
133
+ const selectedKey = normalizeOptionKey(value ?? resolveEditValue(column, row));
132
134
  const options = useMemo(() => {
133
135
  const localOptions = buildOptionsFromColumn(column, getOptionsForColumn, storeName);
134
136
  const remoteOptions = mapOptions(column, loadedItems, storeName);
@@ -143,7 +145,8 @@ const DefaultSelect = ({
143
145
  ...localOptions.filter(option => !seenKeys.has(option.key)),
144
146
  ];
145
147
  }, [column, getOptionsForColumn, loadedItems, storeName]);
146
- const selected = options.find(option => option.key === selectedKey);
148
+ const selected = options.find(option => option.key === selectedKey);
149
+ const resolvedFieldLabel = label || column?.formLabel || column?.label || fieldName;
147
150
  const resolvedLabel =
148
151
  displayValue ??
149
152
  selected?.label ??
@@ -175,9 +178,9 @@ const DefaultSelect = ({
175
178
  const query = normalizeText(searchText).toLowerCase();
176
179
  if (!query || onSearchChange) return options;
177
180
  return options.filter(option =>
178
- normalizeText(option.label).toLowerCase().includes(query) ||
179
- normalizeText(option.key).toLowerCase().includes(query),
180
- );
181
+ normalizeText(option.label).toLowerCase().includes(query) ||
182
+ normalizeText(option.key).toLowerCase().includes(query),
183
+ );
181
184
  }, [options, searchText]);
182
185
 
183
186
  const applyLoadedItems = useCallback(value => {
@@ -187,6 +190,12 @@ const DefaultSelect = ({
187
190
  }
188
191
  }, []);
189
192
 
193
+ useEffect(() => {
194
+ loadedListKeysRef.current.clear();
195
+ setLoadedItems([]);
196
+ setSearchText('');
197
+ }, [currentCompanyId, fieldName, row]);
198
+
190
199
  const loadRemoteOptions = useCallback((searchValue = '') => {
191
200
  const listStoreName = resolveStoreNameFromList(column?.list);
192
201
  const actionName = resolveListActionName(column?.list);
@@ -202,7 +211,9 @@ const DefaultSelect = ({
202
211
  column,
203
212
  currentCompanyId,
204
213
  requestParams,
214
+ row,
205
215
  searchValue,
216
+ variant,
206
217
  });
207
218
  const loadKey = `${getColumnKey(column)}:${listStoreName}:${actionName}:${stableSerialize(listLoadParams)}`;
208
219
 
@@ -235,7 +246,7 @@ const DefaultSelect = ({
235
246
  loadedListKeysRef.current.delete(loadKey);
236
247
  throw error;
237
248
  });
238
- }, [applyLoadedItems, column, currentCompanyId, loadedItems, requestParams]);
249
+ }, [applyLoadedItems, column, currentCompanyId, loadedItems, requestParams, row, variant]);
239
250
 
240
251
  const handleSearchChange = useCallback(value => {
241
252
  setSearchText(value);
@@ -247,43 +258,43 @@ const DefaultSelect = ({
247
258
 
248
259
  applyLoadedItems(maybeLoad);
249
260
  }, [applyLoadedItems, loadRemoteOptions, onSearchChange]);
250
-
251
- const close = () => {
252
- setIsOpen(false);
253
- setSearchText('');
254
- if (autoSave) onCancelEditing?.();
255
- };
256
-
257
- const selectOption = option => {
258
- setIsOpen(false);
259
- setSearchText('');
260
-
261
- if (autoSave) {
262
- onSave?.({
263
- value: option.key,
264
- label: option.label,
265
- object: option.raw,
266
- });
267
- return;
268
- }
269
-
270
- onChangeValue?.(option.key, {
271
- value: option.key,
272
- label: option.label,
273
- object: option.raw,
274
- });
275
- };
276
-
277
- const open = async () => {
278
- if (!canEdit && !isForm) return;
279
- try {
280
- if (!editing && !isForm) {
281
- const maybePromise = onStartEditing?.();
282
- if (maybePromise && typeof maybePromise.then === 'function') {
283
- await maybePromise;
284
- }
285
- }
286
-
261
+
262
+ const close = () => {
263
+ setIsOpen(false);
264
+ setSearchText('');
265
+ if (autoSave) onCancelEditing?.();
266
+ };
267
+
268
+ const selectOption = option => {
269
+ setIsOpen(false);
270
+ setSearchText('');
271
+
272
+ if (autoSave) {
273
+ onSave?.({
274
+ value: option.key,
275
+ label: option.label,
276
+ object: option.raw,
277
+ });
278
+ return;
279
+ }
280
+
281
+ onChangeValue?.(option.key, {
282
+ value: option.key,
283
+ label: option.label,
284
+ object: option.raw,
285
+ });
286
+ };
287
+
288
+ const open = async () => {
289
+ if (!canEdit && !isForm) return;
290
+ try {
291
+ if (!editing && !isForm) {
292
+ const maybePromise = onStartEditing?.();
293
+ if (maybePromise && typeof maybePromise.then === 'function') {
294
+ await maybePromise;
295
+ }
296
+ }
297
+
287
298
  const maybeLoad = onBeforeOpen?.();
288
299
  if (maybeLoad && typeof maybeLoad.then === 'function') {
289
300
  applyLoadedItems(await maybeLoad);
@@ -296,11 +307,11 @@ const DefaultSelect = ({
296
307
  setIsOpen(true);
297
308
  loadRemoteOptions().catch(() => {});
298
309
  };
299
-
300
- return (
301
- <View style={[inputStyles.wrap, containerStyle]}>
302
- {showLabel ? <Text style={inputStyles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
303
-
310
+
311
+ return (
312
+ <View style={[inputStyles.wrap, containerStyle]}>
313
+ {showLabel ? <Text style={inputStyles.fieldLabel}>{label || column?.label || fieldName}</Text> : null}
314
+
304
315
  <TouchableOpacity
305
316
  style={[inputStyles.readButton, isForm ? inputStyles.readButtonForm : null]}
306
317
  activeOpacity={canEdit || isForm ? 0.78 : 1}
@@ -359,33 +370,33 @@ const DefaultSelect = ({
359
370
  {saving ? (
360
371
  <Text style={[inputStyles.savingText, { color: accentColor }]}>Salvando</Text>
361
372
  ) : canEdit || isForm ? (
362
- <Icon style={inputStyles.editIcon} name="chevron-down" size={14} color="#64748B" />
363
- ) : null}
364
- </TouchableOpacity>
365
-
366
- <Modal visible={isOpen} transparent animationType="fade" onRequestClose={close}>
367
- <View style={styles.overlay}>
368
- <View style={styles.modalCard}>
369
- <View style={styles.modalHeader}>
370
- <Text style={styles.modalTitle} numberOfLines={1}>
371
- {label || column?.label || fieldName}
372
- </Text>
373
- <TouchableOpacity style={inputStyles.cancelButton} onPress={close}>
374
- <Icon name="x" size={16} color="#64748B" />
375
- </TouchableOpacity>
376
- </View>
377
-
378
- <View style={styles.searchBox}>
379
- <TextInput
373
+ <Icon style={inputStyles.editIcon} name="chevron-down" size={14} color="#64748B" />
374
+ ) : null}
375
+ </TouchableOpacity>
376
+
377
+ <Modal visible={isOpen} transparent animationType="fade" onRequestClose={close}>
378
+ <View style={styles.overlay}>
379
+ <View style={styles.modalCard}>
380
+ <View style={styles.modalHeader}>
381
+ <Text style={styles.modalTitle} numberOfLines={1}>
382
+ {resolvedFieldLabel}
383
+ </Text>
384
+ <TouchableOpacity style={inputStyles.cancelButton} onPress={close}>
385
+ <Icon name="x" size={16} color="#64748B" />
386
+ </TouchableOpacity>
387
+ </View>
388
+
389
+ <View style={styles.searchBox}>
390
+ <TextInput
380
391
  style={[inputStyles.input, inputStyles.formInput]}
381
392
  value={searchText}
382
- placeholder={global.t?.t(storeName, 'input', column?.searchParam || 'search')}
393
+ placeholder={resolvedFieldLabel || global.t?.t(storeName, 'input', column?.searchParam || 'search')}
383
394
  onChangeText={handleSearchChange}
384
395
  />
385
- </View>
386
-
387
- <ScrollView keyboardShouldPersistTaps="handled">
388
- {filteredOptions.length > 0 ? (
396
+ </View>
397
+
398
+ <ScrollView keyboardShouldPersistTaps="handled">
399
+ {filteredOptions.length > 0 ? (
389
400
  filteredOptions.map(option => {
390
401
  const isSelected = option.key === selectedKey;
391
402
  const optionColor = normalizeText(option.color);
@@ -401,10 +412,10 @@ const DefaultSelect = ({
401
412
  return (
402
413
  <TouchableOpacity
403
414
  key={`${option.key}_${option.label}`}
404
- style={styles.optionRow}
405
- activeOpacity={0.78}
406
- onPress={() => selectOption(option)}
407
- >
415
+ style={styles.optionRow}
416
+ activeOpacity={0.78}
417
+ onPress={() => selectOption(option)}
418
+ >
408
419
  {option.image ? (
409
420
  <Image
410
421
  source={option.image}
@@ -429,21 +440,21 @@ const DefaultSelect = ({
429
440
  {option.label}
430
441
  </Text>
431
442
  </TouchableOpacity>
432
- );
433
- })
434
- ) : (
435
- <View style={styles.emptyBox}>
436
- <Text style={styles.emptyText}>
437
- Nenhum resultado encontrado
438
- </Text>
439
- </View>
440
- )}
441
- </ScrollView>
442
- </View>
443
- </View>
444
- </Modal>
445
- </View>
446
- );
447
- };
448
-
449
- export default DefaultSelect;
443
+ );
444
+ })
445
+ ) : (
446
+ <View style={styles.emptyBox}>
447
+ <Text style={styles.emptyText}>
448
+ Nenhum resultado encontrado
449
+ </Text>
450
+ </View>
451
+ )}
452
+ </ScrollView>
453
+ </View>
454
+ </View>
455
+ </Modal>
456
+ </View>
457
+ );
458
+ };
459
+
460
+ export default DefaultSelect;