@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.
Files changed (61) hide show
  1. package/AGENTS.md +47 -45
  2. package/package.json +20 -20
  3. package/src/react/components/errors/DefaultErrors.js +307 -325
  4. package/src/react/components/files/DefaultFile.js +46 -46
  5. package/src/react/components/filters/CompactFilterSelector.js +78 -24
  6. package/src/react/components/filters/CompactFilterSelector.styles.js +17 -5
  7. package/src/react/components/filters/DefaultColumnFilter.js +191 -57
  8. package/src/react/components/filters/DefaultExternalFilters.js +245 -182
  9. package/src/react/components/filters/DefaultSearch.js +131 -92
  10. package/src/react/components/filters/DefaultSearch.styles.js +65 -70
  11. package/src/react/components/form/DefaultForm.js +172 -151
  12. package/src/react/components/form/DefaultForm.styles.js +71 -66
  13. package/src/react/components/help/DefaultTooltip.js +87 -87
  14. package/src/react/components/help/DefaultTooltip.styles.js +61 -61
  15. package/src/react/components/inputs/DefaultDateInput.js +150 -0
  16. package/src/react/components/inputs/DefaultInput.js +162 -127
  17. package/src/react/components/inputs/DefaultInput.styles.js +6 -0
  18. package/src/react/components/inputs/DefaultSelect.js +320 -152
  19. package/src/react/components/inputs/defaultInputUtils.js +40 -19
  20. package/src/react/components/map/DefaultGoogleMap.styles.js +115 -9
  21. package/src/react/components/map/DefaultGoogleMap.web.js +560 -446
  22. package/src/react/components/map/DefaultMap.native.js +73 -71
  23. package/src/react/components/map/DefaultMap.styles.js +16 -16
  24. package/src/react/components/map/DefaultMap.web.js +68 -66
  25. package/src/react/components/map/DefaultNativeMap.native.js +307 -183
  26. package/src/react/components/map/DefaultNativeMap.shared.js +439 -340
  27. package/src/react/components/map/DefaultNativeMap.styles.js +156 -122
  28. package/src/react/components/table/DefaultColumnMenu.js +108 -0
  29. package/src/react/components/table/DefaultDebug.js +233 -0
  30. package/src/react/components/table/DefaultFiltersModal.js +142 -0
  31. package/src/react/components/table/DefaultModalButton.js +18 -0
  32. package/src/react/components/table/DefaultSearchModal.js +49 -0
  33. package/src/react/components/table/DefaultTable.js +345 -1846
  34. package/src/react/components/table/DefaultTable.styles.js +247 -136
  35. package/src/react/components/table/DefaultTable.utils.js +502 -0
  36. package/src/react/components/table/DefaultTableBody.js +26 -0
  37. package/src/react/components/table/DefaultTableCards.js +171 -0
  38. package/src/react/components/table/DefaultTableControls.js +208 -0
  39. package/src/react/components/table/DefaultTableEmptyState.js +22 -0
  40. package/src/react/components/table/DefaultTableFooter.js +172 -0
  41. package/src/react/components/table/DefaultTableInput.js +145 -0
  42. package/src/react/components/table/DefaultTableRows.js +340 -0
  43. package/src/react/components/table/DefaultTableSearch.js +100 -0
  44. package/src/react/components/table/DefaultTableToolbar.js +98 -0
  45. package/src/react/components/table/DefaultToolbarAction.js +56 -0
  46. package/src/react/components/table/useDefaultTablePagination.js +370 -0
  47. package/src/react/components/table/useDefaultTableSorting.js +126 -0
  48. package/src/react/components/table/useDefaultTableTheme.js +58 -0
  49. package/src/react/index.js +10 -10
  50. package/src/react/utils/tableVisibleColumnsPreferences.js +239 -211
  51. package/src/store/default/actions.js +51 -13
  52. package/src/store/default/getters.js +10 -8
  53. package/src/store/default/mutation_types.js +4 -2
  54. package/src/store/default/mutations.js +10 -1
  55. package/src/tests/react/components/errors/DefaultErrors.test.js +162 -162
  56. package/src/tests/react/components/files/DefaultFile.test.js +80 -80
  57. package/src/tests/react/components/form/DefaultForm.test.js +81 -0
  58. package/src/tests/react/components/inputs/DefaultSelect.test.js +185 -0
  59. package/src/tests/react/components/table/DefaultTable.test.js +1183 -0
  60. package/src/tests/react/store/defaultActions.test.js +59 -0
  61. package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +247 -168
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import { Modal, ScrollView, Text, TouchableOpacity, View } from 'react-native';
3
+ import Icon from 'react-native-vector-icons/Feather';
4
+ import { useStore } from '@store';
5
+ import { formatStoreColumnLabel } from '@controleonline/ui-common/src/react/utils/storeColumns';
6
+ import DefaultColumnFilter from '../filters/DefaultColumnFilter';
7
+ import { getColumnKey, normalizeText } from '../inputs/defaultInputUtils';
8
+ import styles from './DefaultTable.styles';
9
+ import { shouldIncludeColumn } from './DefaultTable.utils';
10
+ import {
11
+ persistTableFiltersPreference,
12
+ resolveDefaultTablePreferenceScope,
13
+ sanitizeTableFiltersPreference,
14
+ } from '../../utils/tableVisibleColumnsPreferences';
15
+ import useDefaultTableTheme from './useDefaultTableTheme';
16
+
17
+ const DefaultFiltersModal = ({ storeName, visible = false, onClose }) => {
18
+ const store = useStore(storeName);
19
+ const columns = (Array.isArray(store?.getters?.columns) ? store.getters.columns : []).filter(
20
+ column =>
21
+ shouldIncludeColumn(column) &&
22
+ column?.filter !== false &&
23
+ column?.filters !== false,
24
+ );
25
+ const filters = store?.getters?.filters || {};
26
+ const configs = store?.getters?.configs || {};
27
+ const tablePreferenceScope =
28
+ configs.tablePreferenceScope ||
29
+ resolveDefaultTablePreferenceScope({ storeName });
30
+ const applyFilters = nextFilters => {
31
+ const persistedFilters = sanitizeTableFiltersPreference({
32
+ columns,
33
+ filters: nextFilters,
34
+ });
35
+
36
+ persistTableFiltersPreference(tablePreferenceScope, persistedFilters);
37
+
38
+ if (typeof store?.actions?.setFilters === 'function') {
39
+ store.actions.setFilters(nextFilters);
40
+ } else if (store?.getters) {
41
+ store.getters.filters = nextFilters;
42
+ }
43
+
44
+ configs.onFilterChange?.(nextFilters);
45
+ };
46
+ const updateFilter = (fieldName, value) => {
47
+ const nextFilters = { ...(filters || {}) };
48
+ const isEmpty =
49
+ value === null ||
50
+ value === undefined ||
51
+ normalizeText(value) === '' ||
52
+ (Array.isArray(value) && value.length === 0);
53
+
54
+ if (isEmpty) delete nextFilters[fieldName];
55
+ else nextFilters[fieldName] = value;
56
+
57
+ applyFilters(nextFilters);
58
+ };
59
+ const applyLabel = global.t?.t(storeName, 'button', 'apply');
60
+ const clearLabel = global.t?.t(storeName, 'button', 'clear');
61
+ const title = global.t?.t(storeName, 'label', 'filters');
62
+ const { modalColors, resolvedAccentColor } = useDefaultTableTheme();
63
+ if (!visible) return null;
64
+
65
+ const {
66
+ backgroundColor,
67
+ borderColor,
68
+ closeIconColor,
69
+ headerTextColor,
70
+ overlayColor,
71
+ textColor,
72
+ } = modalColors;
73
+
74
+ return (
75
+ <Modal visible transparent animationType="fade" onRequestClose={onClose}>
76
+ <View style={[styles.modalOverlay, { backgroundColor: overlayColor }]}>
77
+ <View style={[styles.modalCard, styles.filtersModalCard, { borderColor, backgroundColor }]}>
78
+ <View style={[styles.modalHeader, { borderBottomColor: borderColor }]}>
79
+ <Text style={[styles.modalTitle, { color: headerTextColor }]} numberOfLines={1}>
80
+ {title}
81
+ </Text>
82
+ <TouchableOpacity
83
+ style={[styles.modalCloseButton, { borderColor, backgroundColor }]}
84
+ activeOpacity={0.82}
85
+ onPress={onClose}
86
+ >
87
+ <Icon name="x" size={16} color={closeIconColor} />
88
+ </TouchableOpacity>
89
+ </View>
90
+ <ScrollView style={styles.filtersModalBody} contentContainerStyle={styles.filtersModalList}>
91
+ {columns.map(column => {
92
+ const fieldName = getColumnKey(column);
93
+ const label = formatStoreColumnLabel({
94
+ columns,
95
+ fieldName,
96
+ fallbackLabel: column?.label || fieldName,
97
+ storeName,
98
+ });
99
+
100
+ return (
101
+ <View key={fieldName} style={styles.filtersModalField}>
102
+ <Text style={[styles.formLabel, { color: textColor }]} numberOfLines={1}>
103
+ {label}
104
+ </Text>
105
+ <DefaultColumnFilter
106
+ column={column}
107
+ filters={filters}
108
+ onChange={updateFilter}
109
+ storeName={storeName}
110
+ style={styles.filtersModalInput}
111
+ />
112
+ </View>
113
+ );
114
+ })}
115
+ </ScrollView>
116
+ <View style={[styles.modalActions, { borderTopColor: borderColor }]}>
117
+ <TouchableOpacity
118
+ style={[styles.secondaryButton, { borderColor }]}
119
+ activeOpacity={0.82}
120
+ onPress={() => applyFilters({})}
121
+ >
122
+ <Text style={[styles.secondaryButtonText, { color: textColor }]}>
123
+ {clearLabel}
124
+ </Text>
125
+ </TouchableOpacity>
126
+ <TouchableOpacity
127
+ style={[styles.primaryButton, { backgroundColor: resolvedAccentColor }]}
128
+ activeOpacity={0.82}
129
+ onPress={onClose}
130
+ >
131
+ <Text style={styles.primaryButtonText}>
132
+ {applyLabel}
133
+ </Text>
134
+ </TouchableOpacity>
135
+ </View>
136
+ </View>
137
+ </View>
138
+ </Modal>
139
+ );
140
+ };
141
+
142
+ export default DefaultFiltersModal;
@@ -0,0 +1,18 @@
1
+ import React, { useCallback, useState } from 'react';
2
+
3
+ const DefaultModalButton = ({ children, renderButton }) => {
4
+ const [isOpen, setIsOpen] = useState(false);
5
+
6
+ const close = useCallback(() => setIsOpen(false), []);
7
+ const open = useCallback(() => setIsOpen(true), []);
8
+ const toggle = useCallback(() => setIsOpen(prev => !prev), []);
9
+
10
+ return (
11
+ <>
12
+ {renderButton?.({ close, isOpen, open, toggle })}
13
+ {children?.({ close, isOpen, open, toggle })}
14
+ </>
15
+ );
16
+ };
17
+
18
+ export default DefaultModalButton;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import { Modal, Text, TouchableOpacity, View } from 'react-native';
3
+ import Icon from 'react-native-vector-icons/Feather';
4
+ import DefaultSearch from '../filters/DefaultSearch';
5
+ import styles from './DefaultTable.styles';
6
+ import useDefaultTableTheme from './useDefaultTableTheme';
7
+
8
+ const DefaultSearchModal = ({ storeName, visible = false, onClose }) => {
9
+ const { modalColors } = useDefaultTableTheme();
10
+ if (!visible) return null;
11
+
12
+ const {
13
+ backgroundColor,
14
+ borderColor,
15
+ closeIconColor,
16
+ headerTextColor,
17
+ overlayColor,
18
+ } = modalColors;
19
+
20
+ return (
21
+ <Modal visible transparent animationType="fade" onRequestClose={onClose}>
22
+ <View style={[styles.modalOverlay, { backgroundColor: overlayColor }]}>
23
+ <View style={[styles.modalCard, styles.searchModalCard, { borderColor, backgroundColor }]}>
24
+ <View style={[styles.modalHeader, { borderBottomColor: borderColor }]}>
25
+ <Text style={[styles.modalTitle, { color: headerTextColor }]} numberOfLines={1}>
26
+ {global.t?.t(storeName, 'label', 'search')}
27
+ </Text>
28
+ <TouchableOpacity
29
+ style={[styles.modalCloseButton, { borderColor, backgroundColor }]}
30
+ activeOpacity={0.82}
31
+ onPress={onClose}
32
+ >
33
+ <Icon name="x" size={16} color={closeIconColor} />
34
+ </TouchableOpacity>
35
+ </View>
36
+ <View style={styles.searchModalBody}>
37
+ <DefaultSearch
38
+ autoFocus
39
+ storeName={storeName}
40
+ onSearch={onClose}
41
+ />
42
+ </View>
43
+ </View>
44
+ </View>
45
+ </Modal>
46
+ );
47
+ };
48
+
49
+ export default DefaultSearchModal;