@widergy/mobile-ui 1.11.4 → 1.11.6

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 (50) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/lib/components/UTButton/index.js +12 -3
  3. package/lib/components/UTIcon/README.md +22 -8
  4. package/lib/components/UTIcon/constants.js +24 -0
  5. package/lib/components/UTIcon/index.js +15 -5
  6. package/lib/components/UTIcon/theme.js +18 -0
  7. package/lib/components/UTLabel/README.md +74 -0
  8. package/lib/components/UTLabel/theme.js +11 -2
  9. package/lib/components/UTTextArea/constants.js +1 -0
  10. package/lib/components/UTTextArea/index.js +14 -0
  11. package/lib/components/UTTextInput/index.js +9 -60
  12. package/lib/components/UTTextInput/{components → versions/V0/components}/BaseInput/index.js +3 -3
  13. package/lib/components/UTTextInput/{components → versions/V0/components}/InputAnimatedBorder/index.js +1 -1
  14. package/lib/components/UTTextInput/{components → versions/V0/components}/InputLabel/index.js +1 -1
  15. package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/FilledInput/index.js +6 -6
  16. package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/OutlinedInput/index.js +6 -6
  17. package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/StandardInput/index.js +6 -6
  18. package/lib/components/UTTextInput/versions/V0/index.js +67 -0
  19. package/lib/components/UTTextInput/versions/V1/components/TextInputField/constants.js +12 -0
  20. package/lib/components/UTTextInput/versions/V1/components/TextInputField/index.js +202 -0
  21. package/lib/components/UTTextInput/versions/V1/components/TextInputField/theme.js +124 -0
  22. package/lib/components/UTTextInput/versions/V1/components/TextInputField/utils.js +11 -0
  23. package/lib/components/UTTextInput/versions/V1/constants.js +8 -0
  24. package/lib/components/UTTextInput/versions/V1/index.js +94 -0
  25. package/lib/components/UTTextInput/versions/V1/proptypes.js +36 -0
  26. package/lib/components/UTTextInput/versions/V1/styles.js +10 -0
  27. package/lib/components/UTTextInput/versions/V1/utils.js +1 -0
  28. package/lib/components/UTValidation/README.md +56 -0
  29. package/lib/components/UTValidation/constants.js +39 -0
  30. package/lib/components/UTValidation/index.js +69 -0
  31. package/lib/components/UTValidation/styles.js +25 -0
  32. package/lib/components/UTValidation/theme.js +17 -0
  33. package/lib/components/UTValidation/utils.js +8 -0
  34. package/lib/index.js +5 -2
  35. package/lib/theming/README.md +10 -18
  36. package/package.json +1 -1
  37. package/lib/components/UTTextInput/flavors/FilledInput/constants.js +0 -1
  38. package/lib/components/UTTextInput/flavors/FilledInput/utils.js +0 -35
  39. package/lib/components/UTTextInput/flavors/OutlinedInput/constants.js +0 -1
  40. package/lib/components/UTTextInput/flavors/OutlinedInput/utils.js +0 -37
  41. package/lib/components/UTTextInput/flavors/StandardInput/constants.js +0 -1
  42. /package/lib/components/UTTextInput/{components → versions/V0/components}/BaseInput/constants.js +0 -0
  43. /package/lib/components/UTTextInput/{components → versions/V0/components}/BaseInput/styles.js +0 -0
  44. /package/lib/components/UTTextInput/{components → versions/V0/components}/InputAnimatedBorder/styles.js +0 -0
  45. /package/lib/components/UTTextInput/{components → versions/V0/components}/InputAnimatedBorder/utils.js +0 -0
  46. /package/lib/components/UTTextInput/{components → versions/V0/components}/InputLabel/styles.js +0 -0
  47. /package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/FilledInput/styles.js +0 -0
  48. /package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/OutlinedInput/styles.js +0 -0
  49. /package/lib/components/UTTextInput/{flavors → versions/V0/flavors}/StandardInput/styles.js +0 -0
  50. /package/lib/components/UTTextInput/{proptypes.js → versions/V0/proptypes.js} +0 -0
@@ -0,0 +1,202 @@
1
+ import React, { useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
2
+ import { bool, elementType, func, number, string, shape } from 'prop-types';
3
+ import { View, TextInput } from 'react-native';
4
+ import { ViewPropTypes } from 'deprecated-react-native-prop-types';
5
+
6
+ import { themeType, withTheme } from '../../../../../../theming';
7
+ import UTButton from '../../../../../UTButton';
8
+ import UTIcon from '../../../../../UTIcon';
9
+ import UTLabel from '../../../../../UTLabel';
10
+ import UTTooltip from '../../../../../UTTooltip';
11
+
12
+ import { ERROR_ICON, KEYBOARD_BY_TYPE, TYPES } from './constants';
13
+ import { iconRenderer } from './utils';
14
+ import { retrieveStyle } from './theme';
15
+
16
+ const TextInputField = ({
17
+ action,
18
+ alwaysShowPlaceholder,
19
+ disabled,
20
+ error,
21
+ inputSize,
22
+ LeftIcon,
23
+ maxCount,
24
+ maxRows,
25
+ onBlur,
26
+ onChange,
27
+ onFocus,
28
+ placeholder,
29
+ prefix,
30
+ readOnly,
31
+ RightIcon,
32
+ style,
33
+ suffix,
34
+ theme,
35
+ tooltip,
36
+ type,
37
+ value
38
+ }) => {
39
+ const [displayValue, setDisplayValue] = useState(value);
40
+ const [focused, setFocused] = useState(false);
41
+ const [inputWidth, setInputWidth] = useState(null);
42
+ const [internalValue, setInternalValue] = useState(value);
43
+ const textInputRef = useRef(null);
44
+
45
+ const multiline = maxRows > 1;
46
+
47
+ const handleTextChange = useCallback(
48
+ text => {
49
+ setInternalValue(text);
50
+ onChange?.(text);
51
+ },
52
+ [onChange]
53
+ );
54
+
55
+ const handleFocus = useCallback(
56
+ event => {
57
+ setFocused(true);
58
+ if (!multiline) setDisplayValue(internalValue);
59
+ onFocus?.(event);
60
+ },
61
+ [onFocus, internalValue, multiline]
62
+ );
63
+
64
+ const handleBlur = useCallback(
65
+ event => {
66
+ const truncateText = text => {
67
+ if (!inputWidth || !text) return text;
68
+
69
+ const charWidth = 8;
70
+ const maxCharsPerLine = Math.floor(inputWidth / charWidth);
71
+ const maxLength = maxCharsPerLine;
72
+
73
+ return text.length > maxLength ? `${text.substring(0, maxLength - 3)}...` : text;
74
+ };
75
+
76
+ setFocused(false);
77
+ if (!multiline) setDisplayValue(truncateText(internalValue));
78
+ onBlur?.(event);
79
+ },
80
+ [inputWidth, internalValue, multiline, onBlur]
81
+ );
82
+
83
+ const { actionStyle, containerStyle, inputRowStyle, inputStyle, textLengthRowStyle, placeholderColor } =
84
+ retrieveStyle({
85
+ disabled,
86
+ error,
87
+ focused,
88
+ inputSize,
89
+ maxRows,
90
+ multiline,
91
+ readOnly,
92
+ style,
93
+ theme
94
+ });
95
+
96
+ useEffect(() => {
97
+ setInternalValue(value);
98
+ setDisplayValue(value);
99
+ }, [value]);
100
+
101
+ useLayoutEffect(() => {
102
+ if (textInputRef.current) {
103
+ textInputRef.current.measure((_x, _y, width) => {
104
+ setInputWidth(width);
105
+ });
106
+ }
107
+ }, [focused]);
108
+
109
+ const secureTextEntry = type === TYPES.PASSWORD;
110
+ const autoCapitalize = type === TYPES.EMAIL ? 'none' : 'sentences';
111
+ const keyboardType = KEYBOARD_BY_TYPE[type] || 'default';
112
+
113
+ const renderIcon = iconRenderer(error, inputStyle.color);
114
+
115
+ return (
116
+ <View style={containerStyle}>
117
+ <View style={inputRowStyle}>
118
+ {LeftIcon && renderIcon(LeftIcon)}
119
+ {prefix && <UTLabel colorTheme="gray">{prefix}</UTLabel>}
120
+ <TextInput
121
+ autoCapitalize={autoCapitalize}
122
+ autoCorrect={false}
123
+ editable={!disabled && !readOnly}
124
+ keyboardType={keyboardType}
125
+ maxLength={maxCount}
126
+ multiline={multiline}
127
+ numberOfLines={maxRows}
128
+ onChangeText={handleTextChange}
129
+ onEndEditing={handleBlur}
130
+ onFocus={handleFocus}
131
+ placeholder={!focused && !alwaysShowPlaceholder ? '' : placeholder}
132
+ placeholderTextColor={placeholderColor}
133
+ ref={textInputRef}
134
+ secureTextEntry={secureTextEntry}
135
+ style={inputStyle}
136
+ type={type}
137
+ value={focused || multiline ? internalValue : displayValue}
138
+ />
139
+ {suffix && (
140
+ <UTLabel colorTheme="gray" variant="small">
141
+ {suffix}
142
+ </UTLabel>
143
+ )}
144
+ {action && (
145
+ <UTButton
146
+ disabled={disabled}
147
+ style={actionStyle}
148
+ variant="text"
149
+ colorTheme={action.colorTheme}
150
+ Icon={action.icon}
151
+ onPress={action.onPress}
152
+ >
153
+ {action.text}
154
+ </UTButton>
155
+ )}
156
+ {error ? renderIcon(ERROR_ICON) : RightIcon && renderIcon(RightIcon)}
157
+ {!!tooltip && (
158
+ <UTTooltip content={<UTLabel>{tooltip}</UTLabel>}>
159
+ <UTIcon name="IconInfoCircle" color="gray" />
160
+ </UTTooltip>
161
+ )}
162
+ </View>
163
+ {maxCount && (
164
+ <View style={textLengthRowStyle}>
165
+ <UTLabel colorTheme="gray" variant="small">
166
+ {internalValue?.length || 0}/{maxCount}
167
+ </UTLabel>
168
+ </View>
169
+ )}
170
+ </View>
171
+ );
172
+ };
173
+
174
+ TextInputField.propTypes = {
175
+ action: shape({ icon: elementType, action: func, colorTheme: string, text: string }),
176
+ alwaysShowPlaceholder: bool,
177
+ disabled: bool,
178
+ error: string,
179
+ inputSize: string,
180
+ LeftIcon: elementType,
181
+ maxCount: number,
182
+ maxRows: number,
183
+ onBlur: func,
184
+ onChange: func,
185
+ onFocus: func,
186
+ placeholder: string,
187
+ prefix: string,
188
+ readOnly: bool,
189
+ RightIcon: elementType,
190
+ style: shape({
191
+ container: ViewPropTypes.style,
192
+ input: ViewPropTypes.style,
193
+ root: ViewPropTypes.style
194
+ }),
195
+ suffix: string,
196
+ theme: themeType,
197
+ tooltip: string,
198
+ type: string,
199
+ value: string
200
+ };
201
+
202
+ export default withTheme(TextInputField);
@@ -0,0 +1,124 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ import { SMALL } from '../../constants';
4
+
5
+ const LINE_HEIGHT = 22;
6
+
7
+ const baseTextInputTheme = theme => ({
8
+ action: {
9
+ root: {
10
+ paddingHorizontal: 0,
11
+ paddingVertical: 0
12
+ }
13
+ },
14
+ container: {
15
+ alignItems: 'center',
16
+ backgroundColor: 'transparent',
17
+ borderColor: theme.Palette.light['05'],
18
+ borderRadius: 4,
19
+ borderWidth: 1,
20
+ flex: 1,
21
+ flexDirection: 'column',
22
+ paddingHorizontal: 16,
23
+ paddingVertical: 12,
24
+ rowGap: 16,
25
+ width: '100%'
26
+ },
27
+ input: {
28
+ color: theme.Palette.dark['05'],
29
+ flex: 1,
30
+ fontFamily: theme.fonts.fontFamily, // TODO! Change when integration of font sizes
31
+ fontSize: 16,
32
+ lineHeight: LINE_HEIGHT,
33
+ padding: 0,
34
+ zIndex: 4,
35
+ ...Platform.select({
36
+ ios: {
37
+ height: '100%',
38
+ lineHeight: LINE_HEIGHT + 4
39
+ }
40
+ })
41
+ },
42
+ inputRow: {
43
+ alignItems: 'center',
44
+ columnGap: 16,
45
+ flex: 1,
46
+ flexDirection: 'row',
47
+ justifyContent: 'space-between',
48
+ width: '100%'
49
+ },
50
+ textLengthRow: {
51
+ flexDirection: 'row',
52
+ justifyContent: 'flex-start',
53
+ width: '100%'
54
+ },
55
+ placeholder: {
56
+ color: theme.Palette.gray['02']
57
+ }
58
+ });
59
+
60
+ const conditionalContainerStyle = (focused, error, theme, readOnly, disabled, inputSize) => ({
61
+ ...(focused && {
62
+ borderColor: theme.Palette.accent['04'],
63
+ borderWidth: 2,
64
+ padding: -1
65
+ }),
66
+ ...(error && {
67
+ borderColor: theme.Palette.error['04']
68
+ }),
69
+ ...(readOnly && {
70
+ backgroundColor: 'transparent',
71
+ borderColor: 'transparent',
72
+ paddingHorizontal: 0
73
+ }),
74
+ ...(disabled && {
75
+ backgroundColor: theme.Palette.light['03'],
76
+ borderColor: 'transparent'
77
+ }),
78
+ ...(inputSize === SMALL && {
79
+ paddingHorizontal: 12,
80
+ paddingVertical: 8
81
+ })
82
+ });
83
+
84
+ const conditionalInputStyle = (maxRows, multiline) => ({
85
+ ...(multiline && {
86
+ height: maxRows * LINE_HEIGHT,
87
+ textAlignVertical: 'top'
88
+ })
89
+ });
90
+
91
+ export const retrieveStyle = ({
92
+ disabled,
93
+ error,
94
+ focused,
95
+ inputSize,
96
+ maxRows,
97
+ multiline,
98
+ readOnly,
99
+ style = {},
100
+ theme
101
+ }) => {
102
+ const baseTheme = baseTextInputTheme(theme);
103
+
104
+ const containerStyle = {
105
+ ...baseTheme.container,
106
+ ...conditionalContainerStyle(focused, error, theme, readOnly, disabled, inputSize),
107
+ ...style.container
108
+ };
109
+
110
+ const inputStyle = {
111
+ ...baseTheme.input,
112
+ ...conditionalInputStyle(maxRows, multiline),
113
+ ...style.input
114
+ };
115
+
116
+ return {
117
+ actionStyle: { ...baseTheme.action, ...style.action },
118
+ inputStyle,
119
+ containerStyle,
120
+ inputRowStyle: baseTheme.inputRow,
121
+ textLengthRowStyle: baseTheme.textLengthRow,
122
+ placeholderColor: baseTheme.placeholder.color
123
+ };
124
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+
3
+ import UTIcon from '../../../../../UTIcon';
4
+
5
+ const isUTIcon = icon => typeof icon === 'string';
6
+
7
+ export const iconRenderer = (error, themeColor) => Icon => {
8
+ const color = error ? 'error' : 'gray';
9
+ const shade = error && '04';
10
+ return isUTIcon(Icon) ? <UTIcon name={Icon} color={color} shade={shade} /> : <Icon fill={themeColor} />;
11
+ };
@@ -0,0 +1,8 @@
1
+ export const DEFAULT_PROPS = {
2
+ maxRows: 1,
3
+ style: {}
4
+ };
5
+
6
+ export const REQUIRED_LABEL = ' *';
7
+
8
+ export const SMALL = 's';
@@ -0,0 +1,94 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import UTLabel from '../../../UTLabel';
5
+ import UTValidation from '../../../UTValidation';
6
+
7
+ import { DEFAULT_PROPS, REQUIRED_LABEL, SMALL } from './constants';
8
+ import { formatErrorToValidation } from './utils';
9
+ import propTypes from './proptypes';
10
+ import styles from './styles';
11
+ import TextInputField from './components/TextInputField';
12
+
13
+ const UTTextInput = ({
14
+ action,
15
+ alwaysShowPlaceholder,
16
+ disabled,
17
+ error,
18
+ helpText,
19
+ inputSize,
20
+ label,
21
+ labelVariant,
22
+ LeftIcon,
23
+ maxCount,
24
+ maxRows,
25
+ onBlur,
26
+ onChange,
27
+ onFocus,
28
+ placeholder,
29
+ prefix,
30
+ readOnly,
31
+ required,
32
+ RightIcon,
33
+ style,
34
+ suffix,
35
+ tooltip,
36
+ type,
37
+ validations,
38
+ value
39
+ }) => {
40
+ const labelColorTheme = error ? 'error' : readOnly ? 'gray' : 'dark';
41
+ const labelComponentVariant = labelVariant === SMALL ? 'small' : 'body';
42
+ const validationData = validations || formatErrorToValidation(error);
43
+
44
+ return (
45
+ <View style={[styles.container, style.root]}>
46
+ {label && (
47
+ <View style={styles.label}>
48
+ <UTLabel colorTheme={labelColorTheme} shade={error && '04'} variant={labelComponentVariant}>
49
+ {label}
50
+ </UTLabel>
51
+ {required && (
52
+ <UTLabel colorTheme="error" shade="04" variant={labelComponentVariant}>
53
+ {REQUIRED_LABEL}
54
+ </UTLabel>
55
+ )}
56
+ </View>
57
+ )}
58
+ <TextInputField
59
+ action={action}
60
+ alwaysShowPlaceholder={alwaysShowPlaceholder}
61
+ disabled={disabled}
62
+ error={error}
63
+ inputSize={inputSize}
64
+ LeftIcon={LeftIcon}
65
+ maxCount={maxCount}
66
+ maxRows={maxRows}
67
+ onBlur={onBlur}
68
+ onChange={onChange}
69
+ onFocus={onFocus}
70
+ placeholder={placeholder}
71
+ prefix={prefix}
72
+ readOnly={readOnly}
73
+ RightIcon={RightIcon}
74
+ style={style}
75
+ suffix={suffix}
76
+ tooltip={tooltip}
77
+ type={type}
78
+ value={value}
79
+ />
80
+ {helpText && (
81
+ <UTLabel colorTheme="gray" variant="small">
82
+ {helpText}
83
+ </UTLabel>
84
+ )}
85
+ {error && <UTValidation validationData={validationData} />}
86
+ </View>
87
+ );
88
+ };
89
+
90
+ UTTextInput.defaultProps = DEFAULT_PROPS;
91
+
92
+ UTTextInput.propTypes = propTypes;
93
+
94
+ export default UTTextInput;
@@ -0,0 +1,36 @@
1
+ import { bool, elementType, func, number, shape, string } from 'prop-types';
2
+ import { ViewPropTypes } from 'deprecated-react-native-prop-types';
3
+
4
+ import { validationDataProptypes } from '../../../UTValidation/constants';
5
+
6
+ export default {
7
+ action: shape({ icon: elementType, action: func, colorTheme: string, text: string }),
8
+ alwaysShowPlaceholder: bool,
9
+ disabled: bool,
10
+ error: string,
11
+ helpText: string,
12
+ inputSize: string,
13
+ label: string,
14
+ labelVariant: string,
15
+ LeftIcon: elementType,
16
+ maxCount: number,
17
+ maxRows: number,
18
+ onBlur: func,
19
+ onChange: func,
20
+ onFocus: func,
21
+ placeholder: string,
22
+ prefix: string,
23
+ readOnly: bool,
24
+ required: bool,
25
+ RightIcon: elementType,
26
+ style: shape({
27
+ container: ViewPropTypes.style,
28
+ input: ViewPropTypes.style,
29
+ root: ViewPropTypes.style
30
+ }),
31
+ suffix: string,
32
+ tooltip: string,
33
+ type: string,
34
+ validations: validationDataProptypes,
35
+ value: string
36
+ };
@@ -0,0 +1,10 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ container: {
5
+ rowGap: 8
6
+ },
7
+ label: {
8
+ flexDirection: 'row'
9
+ }
10
+ });
@@ -0,0 +1 @@
1
+ export const formatErrorToValidation = error => [{ items: [{ text: error, status: 'error' }] }];
@@ -0,0 +1,56 @@
1
+ # UTValidation
2
+
3
+ ### Description
4
+
5
+ `UTValidation` is a component designed to display input validation messages. The statuses of the messages can be information, error, or success, helping users understand the current state of their input.
6
+
7
+ ### Validation Data
8
+
9
+ The `validationData` prop is an array of objects, each representing a validation message or group of messages. Each object can optionally have a `title` and must have a `status` and an `items` array. The `items` array contains objects, each with `text` and `status` properties.
10
+
11
+ #### Structure of validationData
12
+
13
+ - title (optional): A string that represents the title of the validation group.
14
+ - status (required): A string indicating the status of the validation group. Possible values are success, error, and default.
15
+ - items (required): An array of objects, each representing an individual validation item.
16
+ - text (required): A string containing the validation message.
17
+ - status (required): A string indicating the status of the validation item. Possible values are success, error, and default.
18
+
19
+ Here's an example of `validationData`:
20
+
21
+ ```javascript
22
+ const validationData = [
23
+ {
24
+ items: [
25
+ {
26
+ status: 'success',
27
+ text: 'Debe tener como mínimo 8 caracteres.'
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ title: 'Debe cumplir con al menos 1 de las siguientes condiciones:',
33
+ status: 'error',
34
+ items: [
35
+ {
36
+ status: 'default',
37
+ text: 'Al menos 1 letra minúscula.'
38
+ },
39
+ {
40
+ status: 'default',
41
+ text: 'Al menos 1 letra mayúscula.'
42
+ },
43
+ {
44
+ status: 'success',
45
+ text: 'Al menos 1 número.'
46
+ }
47
+ ]
48
+ }
49
+ ];
50
+ ```
51
+
52
+ ### Props
53
+
54
+ | Name | Description | Default |
55
+ | -------------- | ------------------- | ------- |
56
+ | validationData | The data to display | {} |
@@ -0,0 +1,39 @@
1
+ import { arrayOf, shape, string } from 'prop-types';
2
+
3
+ export const STATUSES = {
4
+ success: 'success',
5
+ error: 'error',
6
+ default: 'default'
7
+ };
8
+
9
+ export const STATUS_COLOR_MAPPER = {
10
+ [STATUSES.success]: 'success',
11
+ [STATUSES.error]: 'error',
12
+ [STATUSES.default]: 'gray'
13
+ };
14
+
15
+ export const ICON_MAPPER = {
16
+ [STATUSES.success]: 'IconCheck',
17
+ [STATUSES.error]: 'IconX'
18
+ };
19
+
20
+ export const STATUSES_WITH_ICON = [STATUSES.success, STATUSES.error];
21
+
22
+ export const ICON_SIZE = 15;
23
+
24
+ export const DEFAULT_PROPS = {
25
+ validationData: {}
26
+ };
27
+
28
+ export const validationDataProptypes = arrayOf(
29
+ shape({
30
+ items: arrayOf(
31
+ shape({
32
+ text: string,
33
+ status: string
34
+ })
35
+ ),
36
+ status: string,
37
+ title: string
38
+ })
39
+ );
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import { isEmpty } from 'lodash';
3
+ import { View } from 'react-native';
4
+ import { ViewPropTypes } from 'deprecated-react-native-prop-types';
5
+
6
+ import { themeType, withTheme } from '../../theming';
7
+ import UTIcon from '../UTIcon';
8
+ import UTLabel from '../UTLabel';
9
+
10
+ import {
11
+ DEFAULT_PROPS,
12
+ ICON_MAPPER,
13
+ ICON_SIZE,
14
+ STATUS_COLOR_MAPPER,
15
+ STATUSES_WITH_ICON,
16
+ validationDataProptypes
17
+ } from './constants';
18
+ import { retrieveStyle } from './theme';
19
+ import styles from './styles';
20
+ import { generateItemKey, generateKey } from './utils';
21
+
22
+ const UTValidation = ({ theme, validationData, style }) => {
23
+ if (isEmpty(validationData)) return null;
24
+
25
+ const themeStyles = retrieveStyle({ theme });
26
+
27
+ const showIcon = status => STATUSES_WITH_ICON.includes(status);
28
+
29
+ return (
30
+ <View style={[style, styles.container]}>
31
+ {validationData.map(({ items, status, title }, index) => (
32
+ <View key={generateKey({ items, status, title }, index)} style={styles.validationContainer}>
33
+ {title && (
34
+ <UTLabel colorTheme={STATUS_COLOR_MAPPER[status]} variant="small">
35
+ {title}
36
+ </UTLabel>
37
+ )}
38
+ <View style={styles.itemsContainer}>
39
+ {items.map(({ text, status: itemStatus }, itemIndex) => (
40
+ <View
41
+ key={generateItemKey({ text, status: itemStatus }, itemIndex)}
42
+ style={styles.itemContainer}
43
+ >
44
+ <View style={[styles.iconContainer, themeStyles.icon[itemStatus]]}>
45
+ {showIcon(itemStatus) && (
46
+ <UTIcon color={itemStatus} name={ICON_MAPPER[itemStatus]} size={ICON_SIZE} />
47
+ )}
48
+ </View>
49
+ <UTLabel colorTheme={STATUS_COLOR_MAPPER[itemStatus]} variant="small">
50
+ {text}
51
+ </UTLabel>
52
+ </View>
53
+ ))}
54
+ </View>
55
+ </View>
56
+ ))}
57
+ </View>
58
+ );
59
+ };
60
+
61
+ UTValidation.defaultProps = DEFAULT_PROPS;
62
+
63
+ UTValidation.propTypes = {
64
+ style: ViewPropTypes.style,
65
+ theme: themeType,
66
+ validationData: validationDataProptypes
67
+ };
68
+
69
+ export default withTheme(UTValidation);
@@ -0,0 +1,25 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ container: {
5
+ rowGap: 16
6
+ },
7
+ iconContainer: {
8
+ alignItems: 'center',
9
+ borderRadius: 100,
10
+ height: 20,
11
+ justifyContent: 'center',
12
+ marginRight: 8,
13
+ width: 20
14
+ },
15
+ itemContainer: {
16
+ alignItems: 'center',
17
+ flexDirection: 'row'
18
+ },
19
+ itemsContainer: {
20
+ rowGap: 8
21
+ },
22
+ validationContainer: {
23
+ rowGap: 12
24
+ }
25
+ });
@@ -0,0 +1,17 @@
1
+ import { STATUSES, STATUS_COLOR_MAPPER } from './constants';
2
+
3
+ const variantsColorTheme = (colorTheme, theme) => theme.Palette[colorTheme];
4
+
5
+ export const retrieveStyle = ({ theme }) => ({
6
+ icon: {
7
+ [STATUSES.success]: {
8
+ backgroundColor: variantsColorTheme(STATUS_COLOR_MAPPER[STATUSES.success], theme)['01']
9
+ },
10
+ [STATUSES.error]: {
11
+ backgroundColor: variantsColorTheme(STATUS_COLOR_MAPPER[STATUSES.error], theme)['01']
12
+ },
13
+ [STATUSES.default]: {
14
+ backgroundColor: variantsColorTheme(STATUS_COLOR_MAPPER[STATUSES.default], theme)['01']
15
+ }
16
+ }
17
+ });