@controleonline/ui-default 1.0.263 → 1.0.264
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +48 -47
- package/package.json +3 -6
- package/src/react/components/errors/DefaultErrors.js +360 -360
- package/src/react/components/files/DefaultFile.js +46 -46
- package/src/react/components/filters/CompactFilterSelector.js +22 -3
- package/src/react/components/filters/DefaultColumnFilter.js +15 -13
- package/src/react/components/filters/DefaultExternalFilters.js +44 -39
- package/src/react/components/filters/DefaultSearch.js +140 -103
- package/src/react/components/filters/DefaultSearch.styles.js +65 -70
- package/src/react/components/form/DefaultForm.js +200 -198
- package/src/react/components/help/DefaultTooltip.js +87 -87
- package/src/react/components/help/DefaultTooltip.styles.js +61 -61
- package/src/react/components/inputs/DefaultInput.js +162 -160
- package/src/react/components/inputs/DefaultSelect.js +203 -192
- package/src/react/components/map/DefaultGoogleMap.styles.js +115 -9
- package/src/react/components/map/DefaultGoogleMap.web.js +560 -446
- package/src/react/components/map/DefaultMap.native.js +73 -71
- package/src/react/components/map/DefaultMap.styles.js +16 -16
- package/src/react/components/map/DefaultMap.web.js +68 -66
- package/src/react/components/map/DefaultNativeMap.native.js +307 -183
- package/src/react/components/map/DefaultNativeMap.shared.js +439 -340
- package/src/react/components/map/DefaultNativeMap.styles.js +156 -122
- package/src/react/components/table/DefaultTable.js +529 -355
- package/src/react/components/table/DefaultTable.styles.js +30 -39
- package/src/react/index.js +10 -10
- package/src/tests/react/components/errors/DefaultErrors.test.js +162 -162
- package/src/tests/react/components/files/DefaultFile.test.js +80 -80
- package/src/tests/react/components/inputs/DefaultSelect.test.js +93 -0
- package/src/tests/react/components/table/DefaultTable.test.js +334 -0
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import React, {memo, useMemo} from 'react';
|
|
2
|
-
import {Image} from 'react-native';
|
|
3
|
-
import {useStore} from '@store';
|
|
4
|
-
import {resolveDefaultFileSource} from '@controleonline/ui-common/src/react/utils/fileUrl';
|
|
5
|
-
|
|
6
|
-
const resolveCompanyFromStore = peopleGetters => {
|
|
7
|
-
if (peopleGetters?.defaultCompany?.id) {
|
|
8
|
-
return peopleGetters.defaultCompany;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (peopleGetters?.currentCompany?.id) {
|
|
12
|
-
return peopleGetters.currentCompany;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return null;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const DefaultFile = ({
|
|
19
|
-
file,
|
|
20
|
-
source,
|
|
21
|
-
company,
|
|
22
|
-
appDomain = '',
|
|
23
|
-
headers = {},
|
|
24
|
-
...imageProps
|
|
25
|
-
}) => {
|
|
26
|
-
const peopleStore = useStore('people');
|
|
27
|
-
const peopleGetters = peopleStore?.getters || {};
|
|
28
|
-
const resolvedCompany = company || resolveCompanyFromStore(peopleGetters);
|
|
29
|
-
const resolvedSource = useMemo(
|
|
30
|
-
() =>
|
|
31
|
-
resolveDefaultFileSource(source ?? file, {
|
|
32
|
-
company: resolvedCompany,
|
|
33
|
-
appDomain,
|
|
34
|
-
headers,
|
|
35
|
-
}),
|
|
36
|
-
[appDomain, company, file, headers, resolvedCompany, source],
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
if (!resolvedSource) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return <Image {...imageProps} source={resolvedSource} />;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export default memo(DefaultFile);
|
|
1
|
+
import React, {memo, useMemo} from 'react';
|
|
2
|
+
import {Image} from 'react-native';
|
|
3
|
+
import {useStore} from '@store';
|
|
4
|
+
import {resolveDefaultFileSource} from '@controleonline/ui-common/src/react/utils/fileUrl';
|
|
5
|
+
|
|
6
|
+
const resolveCompanyFromStore = peopleGetters => {
|
|
7
|
+
if (peopleGetters?.defaultCompany?.id) {
|
|
8
|
+
return peopleGetters.defaultCompany;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (peopleGetters?.currentCompany?.id) {
|
|
12
|
+
return peopleGetters.currentCompany;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return null;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const DefaultFile = ({
|
|
19
|
+
file,
|
|
20
|
+
source,
|
|
21
|
+
company,
|
|
22
|
+
appDomain = '',
|
|
23
|
+
headers = {},
|
|
24
|
+
...imageProps
|
|
25
|
+
}) => {
|
|
26
|
+
const peopleStore = useStore('people');
|
|
27
|
+
const peopleGetters = peopleStore?.getters || {};
|
|
28
|
+
const resolvedCompany = company || resolveCompanyFromStore(peopleGetters);
|
|
29
|
+
const resolvedSource = useMemo(
|
|
30
|
+
() =>
|
|
31
|
+
resolveDefaultFileSource(source ?? file, {
|
|
32
|
+
company: resolvedCompany,
|
|
33
|
+
appDomain,
|
|
34
|
+
headers,
|
|
35
|
+
}),
|
|
36
|
+
[appDomain, company, file, headers, resolvedCompany, source],
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (!resolvedSource) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return <Image {...imageProps} source={resolvedSource} />;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default memo(DefaultFile);
|
|
@@ -89,6 +89,7 @@ const CompactFilterSelector = ({
|
|
|
89
89
|
label = '',
|
|
90
90
|
labelCaption = '',
|
|
91
91
|
onClose = null,
|
|
92
|
+
onBeforeOpen = null,
|
|
92
93
|
onSelect = null,
|
|
93
94
|
options = [],
|
|
94
95
|
selectedKey = '',
|
|
@@ -121,10 +122,28 @@ const CompactFilterSelector = ({
|
|
|
121
122
|
}, [onClose]);
|
|
122
123
|
|
|
123
124
|
const openModal = useCallback(() => {
|
|
124
|
-
if (
|
|
125
|
-
|
|
125
|
+
if (disabled) {
|
|
126
|
+
return;
|
|
126
127
|
}
|
|
127
|
-
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const maybePromise = onBeforeOpen?.();
|
|
131
|
+
if (maybePromise && typeof maybePromise.then === 'function') {
|
|
132
|
+
maybePromise
|
|
133
|
+
.then(() => {
|
|
134
|
+
setVisible(true);
|
|
135
|
+
})
|
|
136
|
+
.catch(() => {
|
|
137
|
+
// Keep the modal closed if the lazy load fails.
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
setVisible(true);
|
|
146
|
+
}, [disabled, onBeforeOpen]);
|
|
128
147
|
|
|
129
148
|
const handleSelect = useCallback(optionKey => {
|
|
130
149
|
const shouldClose = onSelect?.(optionKey, {
|
|
@@ -13,11 +13,12 @@ import styles from './DefaultColumnFilter.styles';
|
|
|
13
13
|
|
|
14
14
|
const DefaultColumnFilter = ({
|
|
15
15
|
accentColor = '#2563EB',
|
|
16
|
-
column,
|
|
17
|
-
filters = {},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
column,
|
|
17
|
+
filters = {},
|
|
18
|
+
onBeforeOpen = null,
|
|
19
|
+
getOptionsForColumn = null,
|
|
20
|
+
onChange = null,
|
|
21
|
+
storeName = '',
|
|
21
22
|
style = null,
|
|
22
23
|
}) => {
|
|
23
24
|
const fieldName = getColumnKey(column);
|
|
@@ -63,14 +64,15 @@ const DefaultColumnFilter = ({
|
|
|
63
64
|
|
|
64
65
|
return (
|
|
65
66
|
<View style={[style, styles.filterCell]}>
|
|
66
|
-
<CompactFilterSelector
|
|
67
|
-
dense
|
|
68
|
-
store={storeName}
|
|
69
|
-
field={fieldName}
|
|
70
|
-
icon="filter"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
<CompactFilterSelector
|
|
68
|
+
dense
|
|
69
|
+
store={storeName}
|
|
70
|
+
field={fieldName}
|
|
71
|
+
icon="filter"
|
|
72
|
+
onBeforeOpen={onBeforeOpen}
|
|
73
|
+
accentColor={accentColor}
|
|
74
|
+
active={Boolean(selectedKey)}
|
|
75
|
+
label={selected?.label || options[0]?.label || ''}
|
|
74
76
|
options={options}
|
|
75
77
|
selectedKey={selectedKey}
|
|
76
78
|
onSelect={optionKey => {
|
|
@@ -183,11 +183,11 @@ const DefaultExternalFilters = ({
|
|
|
183
183
|
storeName = '',
|
|
184
184
|
}) => {
|
|
185
185
|
const { width } = useWindowDimensions();
|
|
186
|
-
const peopleStore = useStore('people');
|
|
187
|
-
const themeStore = useStore('theme');
|
|
188
|
-
const [isFiltersModalOpen, setIsFiltersModalOpen] = useState(false);
|
|
189
|
-
const { currentCompany } = peopleStore.getters || {};
|
|
190
|
-
const { colors: themeColors } = themeStore.getters
|
|
186
|
+
const peopleStore = useStore('people');
|
|
187
|
+
const themeStore = useStore('theme');
|
|
188
|
+
const [isFiltersModalOpen, setIsFiltersModalOpen] = useState(false);
|
|
189
|
+
const { currentCompany } = peopleStore.getters || {};
|
|
190
|
+
const { colors: themeColors } = themeStore.getters;
|
|
191
191
|
const themeTokens = useMemo(
|
|
192
192
|
() => ({...themeColors, ...(currentCompany?.theme?.colors || {})}),
|
|
193
193
|
[currentCompany?.theme?.colors, themeColors],
|
|
@@ -199,10 +199,15 @@ const DefaultExternalFilters = ({
|
|
|
199
199
|
const resolvedAccentColor = accentColor || palette.primary;
|
|
200
200
|
const surfaceColor = themeTokens['bg-odd-light'] || palette.background;
|
|
201
201
|
const panelColor = themeTokens['bg-headers-light'] || palette.background;
|
|
202
|
-
const borderColor = palette.border;
|
|
203
|
-
const textColor = palette.text;
|
|
204
|
-
const textSecondaryColor = palette.textSecondary;
|
|
205
|
-
const
|
|
202
|
+
const borderColor = palette.border;
|
|
203
|
+
const textColor = palette.text;
|
|
204
|
+
const textSecondaryColor = palette.textSecondary;
|
|
205
|
+
const buttonBackgroundColor = themeColors.buttonBackground;
|
|
206
|
+
const buttonTextColor = themeColors.buttonText;
|
|
207
|
+
const tableFilterBackgroundColor = themeColors.tableFilterBackground;
|
|
208
|
+
const tableFilterBorderColor = themeColors.tableFilterBorder;
|
|
209
|
+
const tableFilterTextColor = themeColors.tableFilterText;
|
|
210
|
+
const onAccentColor = palette.secondary || palette.text;
|
|
206
211
|
const isCompactView = width > 0 && width <= compactBreakpoint;
|
|
207
212
|
const filterColumns = useMemo(
|
|
208
213
|
() => columns.filter(shouldIncludeColumn),
|
|
@@ -335,30 +340,30 @@ const DefaultExternalFilters = ({
|
|
|
335
340
|
if (isCompactView) {
|
|
336
341
|
return (
|
|
337
342
|
<View style={styles.mobileWrap}>
|
|
338
|
-
<TouchableOpacity
|
|
339
|
-
style={[
|
|
340
|
-
styles.mobileButton,
|
|
341
|
-
{ borderColor: borderColor, backgroundColor: surfaceColor },
|
|
342
|
-
activeCount > 0 ? { borderColor:
|
|
343
|
-
]}
|
|
344
|
-
activeOpacity={0.84}
|
|
345
|
-
onPress={() => setIsFiltersModalOpen(true)}
|
|
346
|
-
>
|
|
347
|
-
<Icon name="filter" size={15} color={activeCount > 0 ?
|
|
348
|
-
<Text
|
|
349
|
-
style={[
|
|
350
|
-
styles.mobileButtonText,
|
|
351
|
-
{ color: textColor },
|
|
352
|
-
activeCount > 0 ? { color:
|
|
353
|
-
]}
|
|
354
|
-
>
|
|
355
|
-
{filterTitle}
|
|
356
|
-
</Text>
|
|
357
|
-
{activeCount > 0 ? (
|
|
358
|
-
<View style={[styles.mobileCountBadge, { backgroundColor:
|
|
359
|
-
<Text style={styles.mobileCountBadgeText}>{activeCount}</Text>
|
|
360
|
-
</View>
|
|
361
|
-
) : null}
|
|
343
|
+
<TouchableOpacity
|
|
344
|
+
style={[
|
|
345
|
+
styles.mobileButton,
|
|
346
|
+
{ borderColor: borderColor, backgroundColor: surfaceColor },
|
|
347
|
+
activeCount > 0 ? { borderColor: tableFilterBorderColor, backgroundColor: tableFilterBackgroundColor } : null,
|
|
348
|
+
]}
|
|
349
|
+
activeOpacity={0.84}
|
|
350
|
+
onPress={() => setIsFiltersModalOpen(true)}
|
|
351
|
+
>
|
|
352
|
+
<Icon name="filter" size={15} color={activeCount > 0 ? tableFilterTextColor : textSecondaryColor} />
|
|
353
|
+
<Text
|
|
354
|
+
style={[
|
|
355
|
+
styles.mobileButtonText,
|
|
356
|
+
{ color: textColor },
|
|
357
|
+
activeCount > 0 ? { color: tableFilterTextColor } : null,
|
|
358
|
+
]}
|
|
359
|
+
>
|
|
360
|
+
{filterTitle}
|
|
361
|
+
</Text>
|
|
362
|
+
{activeCount > 0 ? (
|
|
363
|
+
<View style={[styles.mobileCountBadge, { backgroundColor: tableFilterBorderColor }]}>
|
|
364
|
+
<Text style={styles.mobileCountBadgeText}>{activeCount}</Text>
|
|
365
|
+
</View>
|
|
366
|
+
) : null}
|
|
362
367
|
</TouchableOpacity>
|
|
363
368
|
|
|
364
369
|
<Modal
|
|
@@ -402,12 +407,12 @@ const DefaultExternalFilters = ({
|
|
|
402
407
|
</Text>
|
|
403
408
|
</TouchableOpacity>
|
|
404
409
|
) : null}
|
|
405
|
-
<TouchableOpacity
|
|
406
|
-
style={[styles.modalPrimaryButton, { backgroundColor:
|
|
407
|
-
activeOpacity={0.84}
|
|
408
|
-
onPress={() => setIsFiltersModalOpen(false)}
|
|
409
|
-
>
|
|
410
|
-
<Text style={[styles.modalPrimaryButtonText, { color:
|
|
410
|
+
<TouchableOpacity
|
|
411
|
+
style={[styles.modalPrimaryButton, { backgroundColor: buttonBackgroundColor }]}
|
|
412
|
+
activeOpacity={0.84}
|
|
413
|
+
onPress={() => setIsFiltersModalOpen(false)}
|
|
414
|
+
>
|
|
415
|
+
<Text style={[styles.modalPrimaryButtonText, { color: buttonTextColor }]}>
|
|
411
416
|
{global.t?.t(storeName, 'button', 'apply')}
|
|
412
417
|
</Text>
|
|
413
418
|
</TouchableOpacity>
|
|
@@ -1,103 +1,140 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import { TextInput, TouchableOpacity, View } from 'react-native';
|
|
3
|
-
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
autoFocus = false,
|
|
11
|
-
compact = false,
|
|
12
|
-
filters = null,
|
|
13
|
-
onChangeFilters = null,
|
|
14
|
-
onClear = null,
|
|
15
|
-
onSearch = null,
|
|
16
|
-
placeholder = '',
|
|
17
|
-
searchKey = 'search',
|
|
18
|
-
storeName = '',
|
|
19
|
-
style = null,
|
|
20
|
-
value,
|
|
21
|
-
}) => {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
style
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { TextInput, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import Icon from 'react-native-vector-icons/Feather';
|
|
4
|
+
import { useStore } from '@store';
|
|
5
|
+
import styles from './DefaultSearch.styles';
|
|
6
|
+
|
|
7
|
+
const normalizeText = value => String(value || '').trim();
|
|
8
|
+
|
|
9
|
+
const DefaultSearch = ({
|
|
10
|
+
autoFocus = false,
|
|
11
|
+
compact = false,
|
|
12
|
+
filters = null,
|
|
13
|
+
onChangeFilters = null,
|
|
14
|
+
onClear = null,
|
|
15
|
+
onSearch = null,
|
|
16
|
+
placeholder = '',
|
|
17
|
+
searchKey = 'search',
|
|
18
|
+
storeName = '',
|
|
19
|
+
style = null,
|
|
20
|
+
value,
|
|
21
|
+
}) => {
|
|
22
|
+
const themeStore = useStore('theme');
|
|
23
|
+
const themeColors = themeStore.getters.colors;
|
|
24
|
+
const palette = useMemo(
|
|
25
|
+
() => ({
|
|
26
|
+
buttonBackgroundSecondary: themeColors.buttonBackgroundSecondary,
|
|
27
|
+
buttonBorder: themeColors.buttonBorder,
|
|
28
|
+
buttonIcon: themeColors.buttonIcon,
|
|
29
|
+
buttonIconSecondary: themeColors.buttonIconSecondary,
|
|
30
|
+
inputBackground: themeColors.inputBackground,
|
|
31
|
+
inputBorder: themeColors.inputBorder,
|
|
32
|
+
inputIcon: themeColors.inputIcon,
|
|
33
|
+
inputPlaceholderText: themeColors.inputPlaceholderText,
|
|
34
|
+
inputText: themeColors.inputText,
|
|
35
|
+
}),
|
|
36
|
+
[themeColors],
|
|
37
|
+
);
|
|
38
|
+
const resolvedValue = useMemo(
|
|
39
|
+
() => normalizeText(value ?? filters?.[searchKey]),
|
|
40
|
+
[filters, searchKey, value],
|
|
41
|
+
);
|
|
42
|
+
const [draftValue, setDraftValue] = useState(resolvedValue);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setDraftValue(resolvedValue);
|
|
46
|
+
}, [resolvedValue]);
|
|
47
|
+
|
|
48
|
+
const commitSearch = nextValue => {
|
|
49
|
+
const searchValue = normalizeText(nextValue ?? draftValue);
|
|
50
|
+
|
|
51
|
+
if (typeof onChangeFilters === 'function') {
|
|
52
|
+
const nextFilters = { ...(filters || {}) };
|
|
53
|
+
if (searchValue) nextFilters[searchKey] = searchValue;
|
|
54
|
+
else delete nextFilters[searchKey];
|
|
55
|
+
onChangeFilters(nextFilters);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onSearch?.(searchValue);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const clearSearch = () => {
|
|
62
|
+
setDraftValue('');
|
|
63
|
+
|
|
64
|
+
if (typeof onChangeFilters === 'function') {
|
|
65
|
+
const nextFilters = { ...(filters || {}) };
|
|
66
|
+
delete nextFilters[searchKey];
|
|
67
|
+
onChangeFilters(nextFilters);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onClear?.();
|
|
71
|
+
onSearch?.('');
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const resolvedPlaceholder =
|
|
75
|
+
placeholder ||
|
|
76
|
+
global.t?.t(storeName, 'input', searchKey) ||
|
|
77
|
+
global.t?.t(storeName, 'placeholder', searchKey) ||
|
|
78
|
+
'Buscar...';
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<View
|
|
82
|
+
style={[
|
|
83
|
+
styles.wrap,
|
|
84
|
+
compact ? styles.wrapCompact : null,
|
|
85
|
+
{
|
|
86
|
+
backgroundColor: palette.inputBackground,
|
|
87
|
+
borderColor: palette.inputBorder,
|
|
88
|
+
},
|
|
89
|
+
style,
|
|
90
|
+
]}
|
|
91
|
+
>
|
|
92
|
+
<Icon name="search" size={compact ? 14 : 16} color={palette.inputIcon} />
|
|
93
|
+
<TextInput
|
|
94
|
+
autoCapitalize="none"
|
|
95
|
+
autoCorrect={false}
|
|
96
|
+
autoFocus={autoFocus}
|
|
97
|
+
placeholder={resolvedPlaceholder}
|
|
98
|
+
placeholderTextColor={palette.inputPlaceholderText}
|
|
99
|
+
returnKeyType="search"
|
|
100
|
+
style={[
|
|
101
|
+
styles.input,
|
|
102
|
+
compact ? styles.inputCompact : null,
|
|
103
|
+
{ color: palette.inputText },
|
|
104
|
+
]}
|
|
105
|
+
value={draftValue}
|
|
106
|
+
onChangeText={setDraftValue}
|
|
107
|
+
onSubmitEditing={() => commitSearch()}
|
|
108
|
+
/>
|
|
109
|
+
{draftValue ? (
|
|
110
|
+
<TouchableOpacity
|
|
111
|
+
style={[
|
|
112
|
+
styles.iconButton,
|
|
113
|
+
compact ? styles.iconButtonCompact : null,
|
|
114
|
+
{ backgroundColor: palette.buttonBackgroundSecondary },
|
|
115
|
+
]}
|
|
116
|
+
activeOpacity={0.82}
|
|
117
|
+
onPress={clearSearch}
|
|
118
|
+
>
|
|
119
|
+
<Icon name="x" size={14} color={palette.buttonIconSecondary} />
|
|
120
|
+
</TouchableOpacity>
|
|
121
|
+
) : null}
|
|
122
|
+
<TouchableOpacity
|
|
123
|
+
style={[
|
|
124
|
+
styles.searchButton,
|
|
125
|
+
compact ? styles.searchButtonCompact : null,
|
|
126
|
+
{
|
|
127
|
+
backgroundColor: palette.buttonBackgroundSecondary,
|
|
128
|
+
borderColor: palette.buttonBorder,
|
|
129
|
+
},
|
|
130
|
+
]}
|
|
131
|
+
activeOpacity={0.82}
|
|
132
|
+
onPress={() => commitSearch()}
|
|
133
|
+
>
|
|
134
|
+
<Icon name="arrow-right" size={compact ? 13 : 15} color={palette.buttonIcon} />
|
|
135
|
+
</TouchableOpacity>
|
|
136
|
+
</View>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export default DefaultSearch;
|
|
@@ -1,70 +1,65 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native';
|
|
2
|
-
|
|
3
|
-
const styles = StyleSheet.create({
|
|
4
|
-
wrap: {
|
|
5
|
-
minHeight: 40,
|
|
6
|
-
minWidth: 180,
|
|
7
|
-
borderWidth: 1,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
borderRadius: 12,
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
export default styles;
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
const styles = StyleSheet.create({
|
|
4
|
+
wrap: {
|
|
5
|
+
minHeight: 40,
|
|
6
|
+
minWidth: 180,
|
|
7
|
+
borderWidth: 1,
|
|
8
|
+
borderRadius: 12,
|
|
9
|
+
paddingLeft: 10,
|
|
10
|
+
paddingRight: 5,
|
|
11
|
+
paddingVertical: 5,
|
|
12
|
+
flexDirection: 'row',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
gap: 8,
|
|
15
|
+
},
|
|
16
|
+
wrapCompact: {
|
|
17
|
+
minHeight: 30,
|
|
18
|
+
minWidth: 150,
|
|
19
|
+
maxWidth: 240,
|
|
20
|
+
borderRadius: 15,
|
|
21
|
+
paddingLeft: 9,
|
|
22
|
+
paddingRight: 3,
|
|
23
|
+
paddingVertical: 3,
|
|
24
|
+
gap: 6,
|
|
25
|
+
},
|
|
26
|
+
input: {
|
|
27
|
+
flex: 1,
|
|
28
|
+
minWidth: 0,
|
|
29
|
+
padding: 0,
|
|
30
|
+
fontSize: 13,
|
|
31
|
+
lineHeight: 16,
|
|
32
|
+
fontWeight: '700',
|
|
33
|
+
},
|
|
34
|
+
inputCompact: {
|
|
35
|
+
fontSize: 12,
|
|
36
|
+
lineHeight: 14,
|
|
37
|
+
},
|
|
38
|
+
iconButton: {
|
|
39
|
+
width: 28,
|
|
40
|
+
height: 28,
|
|
41
|
+
borderRadius: 14,
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
},
|
|
45
|
+
iconButtonCompact: {
|
|
46
|
+
width: 22,
|
|
47
|
+
height: 22,
|
|
48
|
+
borderRadius: 11,
|
|
49
|
+
},
|
|
50
|
+
searchButton: {
|
|
51
|
+
width: 30,
|
|
52
|
+
height: 30,
|
|
53
|
+
borderRadius: 15,
|
|
54
|
+
borderWidth: 1,
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'center',
|
|
57
|
+
},
|
|
58
|
+
searchButtonCompact: {
|
|
59
|
+
width: 24,
|
|
60
|
+
height: 24,
|
|
61
|
+
borderRadius: 12,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export default styles;
|