ikualo-ui-kit-mobile 0.0.4 → 0.0.7

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.
@@ -11,7 +11,6 @@ const styleAlerts = StyleSheet.create({
11
11
  width: '92%',
12
12
  borderRadius: 4,
13
13
  borderLeftWidth: 8,
14
- minHeight: 102,
15
14
  padding: 16,
16
15
  },
17
16
  'alert--info': {
@@ -31,8 +30,8 @@ const styleAlerts = StyleSheet.create({
31
30
  borderLeftColor: theme.colors.darkRed,
32
31
  },
33
32
  'alert-container-text': { flexDirection: 'row', gap: 8 },
34
- 'alert-container-title': { fontSize: 14, fontFamily: 'MontserratBold', color: theme.colors.text },
33
+ 'alert-container-title': { fontSize: 14, fontFamily: 'MontserratBold', color: theme.colors.text , alignSelf: 'center' },
35
34
  'alert-body': { marginTop: 8 },
36
35
  });
37
36
 
38
- export { styleAlerts };
37
+ export { styleAlerts };
@@ -156,6 +156,7 @@ const stylesBtnLightSmall = StyleSheet.create({
156
156
  minHeight: 48,
157
157
  width: 48,
158
158
  height: 48,
159
+ position: 'relative',
159
160
  },
160
161
  'btn-light-small-content': {
161
162
  alignSelf: 'center',
@@ -166,7 +167,6 @@ const stylesBtnLightSmall = StyleSheet.create({
166
167
  minHeight: 48,
167
168
  width: 48,
168
169
  height: 48,
169
- marginLeft: 12,
170
170
  },
171
171
  'btn-light-small-label': {
172
172
  fontSize: 24,
@@ -183,8 +183,23 @@ const stylesBtnLightSmall = StyleSheet.create({
183
183
  width: 48,
184
184
  height: 48,
185
185
  },
186
+ 'btn-light-small--active': {
187
+ backgroundColor: theme.colors.secondaryLight,
188
+ borderColor: theme.colors.secondary,
189
+ borderRadius: 8,
190
+ borderWidth: 1,
191
+ maxWidth: 48,
192
+ minWidth: 48,
193
+ maxHeight: 48,
194
+ minHeight: 48,
195
+ width: 48,
196
+ height: 48,
197
+ },
186
198
  'btn-light-small-label--disabled': {
187
199
  color: theme.colors.disabledButtonBorder,
188
200
  },
201
+ 'btn-light-small-label--active': {
202
+ color: theme.colors.secondary,
203
+ },
189
204
  });
190
205
  export { stylesButtonContained, stylesButtonOutlined, stylesButtonText, stylesBtnLightSmall };
@@ -40,8 +40,7 @@ export const stylesCards = StyleSheet.create({
40
40
  marginVertical: 4,
41
41
  },
42
42
  'card-interactive-icon': {
43
- width: 24,
44
- marginRight: 8,
43
+ marginRight: 16,
45
44
  },
46
45
  'card-interactive-info': {
47
46
  flexDirection: 'row',
@@ -4,15 +4,14 @@ import { theme } from '../../../src/config/paper.config';
4
4
  const styleDropdown = StyleSheet.create({
5
5
  'dropdown-container': {
6
6
  width: 'auto',
7
- marginRight: -42,
8
7
  flexDirection: 'row',
9
8
  justifyContent: 'flex-end',
9
+ marginTop:28
10
10
  },
11
11
  'dropdown-menu': { flexDirection: 'row', alignItems: 'center' },
12
+ 'dropdown-content': { backgroundColor: 'white', borderRadius: 16, padding: 16 },
12
13
  'dropdown-label': { fontSize: 16, marginTop: 15 },
13
14
  'dropdown-label-content': { width: 70 },
14
- 'dropdown-label-arrow': { fontSize: 24 },
15
- 'dropdown-label-width': { width: 10 },
16
15
  'dropdown-overlay': {
17
16
  position: 'absolute',
18
17
  top: 0,
@@ -27,6 +26,12 @@ const styleDropdown = StyleSheet.create({
27
26
  fontSize: 14,
28
27
  color: theme.colors.boldBlack,
29
28
  },
29
+ 'dropdown-color--primary': {
30
+ color: theme.colors.primary,
31
+ },
32
+ 'dropdown-highlight-color': {
33
+ color: theme.colors.lightPrimary,
34
+ }
30
35
  });
31
36
 
32
37
  export { styleDropdown };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ikualo-ui-kit-mobile",
3
- "version": "0.0.4",
3
+ "version": "0.0.7",
4
4
  "main": "src/index.ts",
5
5
  "scripts": {
6
6
  "start": "expo start",
@@ -10,11 +10,10 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@expo/metro-runtime": "~3.2.1",
13
+ "@expo/vector-icons": "^14.0.3",
13
14
  "@react-navigation/bottom-tabs": "^6.5.20",
14
15
  "@react-navigation/native": "^6.1.17",
15
16
  "@react-navigation/stack": "^6.3.29",
16
- "axios": "^1.7.2",
17
- "crypto-js": "^4.2.0",
18
17
  "expo": "~51.0.8",
19
18
  "expo-application": "~5.9.1",
20
19
  "expo-constants": "^16.0.1",
@@ -27,21 +26,16 @@
27
26
  "expo-secure-store": "~13.0.2",
28
27
  "expo-status-bar": "~1.12.1",
29
28
  "expo-updates": "^0.25.14",
30
- "i18next": "^23.11.5",
31
- "p-retry": "^6.2.0",
32
29
  "react": "18.2.0",
33
30
  "react-dom": "18.2.0",
34
- "react-i18next": "^14.1.2",
35
31
  "react-native": "0.74.1",
36
32
  "react-native-asset": "^2.1.1",
37
33
  "react-native-country-flag": "^2.0.2",
38
- "react-native-crypto-js": "^1.0.0",
39
34
  "react-native-gesture-handler": "^2.16.2",
40
35
  "react-native-paper": "^5.12.3",
41
36
  "react-native-safe-area-context": "^4.10.1",
42
37
  "react-native-screens": "^3.31.1",
43
- "react-native-web": "~0.19.10",
44
- "zustand": "^4.5.2"
38
+ "react-native-web": "~0.19.10"
45
39
  },
46
40
  "devDependencies": {
47
41
  "@babel/cli": "^7.24.8",
@@ -53,4 +47,4 @@
53
47
  "metro-react-native-babel-preset": "^0.77.0",
54
48
  "typescript": "^5.1.3"
55
49
  }
56
- }
50
+ }
@@ -5,7 +5,8 @@ export const theme = {
5
5
  colors: {
6
6
  ...DefaultTheme.colors,
7
7
  primary: '#512BDA',
8
- secondary: '#00F993',
8
+ secondary: '#05CFD6',
9
+ secondaryLight: '#DDF7F7',
9
10
  dark: '#29292C',
10
11
  light: '#FFFFFF',
11
12
  error: '#F13A59',
@@ -5,7 +5,7 @@ import { styleAlerts } from '../../../assets/styles/elements/alert';
5
5
  import { icons } from '../../../assets/icons/_icons';
6
6
  interface IFAlertInfo {
7
7
  title: string;
8
- text: JSX.Element;
8
+ text?: JSX.Element;
9
9
  type: 'info' | 'warning' | 'error' | 'success';
10
10
  onClose: () => void;
11
11
  }
@@ -24,8 +24,9 @@ export const Alert = (props: IFAlertInfo) => {
24
24
  <Image source={icons[type]} />
25
25
  <Text style={styleAlerts['alert-container-title']}>{title}</Text>
26
26
  </View>
27
- <View style={styleAlerts['alert-body']}>{text}</View>
27
+ {text && <View style={styleAlerts['alert-body']}>{text}</View>}
28
+
28
29
  </Animated.View>
29
30
  </Portal>
30
31
  );
31
- };
32
+ }
@@ -1,31 +1,38 @@
1
+
1
2
  import { Button, Text } from 'react-native-paper';
2
3
  import { stylesBtnLightSmall } from '../../../assets/styles/elements/buttons';
4
+ import { View } from 'react-native';
5
+ import { cloneElement } from 'react';
3
6
 
4
7
  interface IfBtnLightSmall {
5
8
  onPress: () => void;
6
- icon: any;
9
+ icon: JSX.Element;
7
10
  disabled?: boolean;
11
+ active?: boolean;
8
12
  }
9
13
  export const BtnLightSmall = (props: IfBtnLightSmall) => {
10
- const { onPress, icon, disabled = false } = props;
14
+ const { onPress, icon, disabled = false,active } = props;
11
15
  const anything = '';
12
-
13
16
  return (
14
17
  <Button
15
18
  style={[
16
19
  stylesBtnLightSmall['btn-light-small'],
20
+ active && stylesBtnLightSmall['btn-light-small--active'],
17
21
  disabled && stylesBtnLightSmall['btn-light-small--disabled'],
18
22
  ]}
19
23
  contentStyle={stylesBtnLightSmall['btn-light-small-content']}
20
24
  labelStyle={[
21
25
  (stylesBtnLightSmall['btn-light-small-label'],
26
+ active && stylesBtnLightSmall['btn-light-small-label--active'],
22
27
  disabled && stylesBtnLightSmall['btn-light-small-label--disabled']),
23
28
  ]}
24
29
  onPress={onPress}
25
- icon={icon}
26
30
  disabled={disabled}
27
31
  >
28
- <Text>{anything}</Text>
32
+ <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
33
+ {cloneElement(icon, { size:21,color: active?stylesBtnLightSmall['btn-light-small--active'].borderColor: stylesBtnLightSmall['btn-light-small'].borderColor })}
34
+ <Text>{anything}</Text>
35
+ </View>
29
36
  </Button>
30
37
  );
31
38
  };
@@ -1,10 +1,12 @@
1
- import { View, Image, Touchable, TouchableHighlight } from 'react-native';
1
+ import { View } from 'react-native';
2
2
  import { Card, Text, TouchableRipple } from 'react-native-paper';
3
3
  import { stylesCards } from '../../../assets/styles/elements/cards';
4
- import { icons } from '../../../assets/icons/_icons';
5
-
4
+ import FontAwesome6 from '@expo/vector-icons/FontAwesome6';
5
+ import { cloneElement } from 'react';
6
+ import { theme } from '../../config/paper.config';
6
7
  interface IFCardInteractive {
7
- iconSource?: any;
8
+ iconLeft?: JSX.Element;
9
+ iconRight?: JSX.Element;
8
10
  title: string;
9
11
  description?: string;
10
12
  onPress: () => void;
@@ -12,13 +14,13 @@ interface IFCardInteractive {
12
14
  }
13
15
 
14
16
  export const CardInteractive = (props: IFCardInteractive) => {
15
- const { iconSource, title, description, onPress } = props;
17
+ const { iconLeft, title, description,iconRight, onPress } = props;
16
18
  return (
17
19
  <TouchableRipple onPress={onPress}>
18
20
  <Card style={stylesCards['card-interactive']}>
19
21
  <View style={stylesCards['card-interactive-info']}>
20
22
  <View style={stylesCards['card-interactive-container']}>
21
- {iconSource && <Image source={iconSource} style={stylesCards['card-interactive-icon']} />}
23
+ {iconLeft ? cloneElement(iconLeft, { style: stylesCards['card-interactive-icon'],color:theme.colors.primary }) : ""}
22
24
  <View>
23
25
  <Text style={stylesCards['card-interactive-text']}>{title}</Text>
24
26
  <View style={stylesCards['card-interactive-description']}>
@@ -26,7 +28,7 @@ export const CardInteractive = (props: IFCardInteractive) => {
26
28
  </View>
27
29
  </View>
28
30
  </View>
29
- <Image source={icons.arrowRight} style={stylesCards['card-interactive-arrow']} />
31
+ {iconRight??<FontAwesome6 name="chevron-right" size={15} color={theme.colors.blackText} />}
30
32
  </View>
31
33
  </Card>
32
34
  </TouchableRipple>
@@ -1,14 +1,16 @@
1
1
  import { useState } from 'react';
2
- import { View } from 'react-native';
2
+ import { TouchableNativeFeedback, View } from 'react-native';
3
3
  import { Button, Divider, Menu, Portal } from 'react-native-paper';
4
4
  import { BtnIcon } from '../buttons/BtnIcon';
5
- import { icons } from '../../../assets/icons/_icons';
6
5
  import { styleDropdown } from '../../../assets/styles/elements/dropdown';
7
6
  import { theme } from '../../config/paper.config';
7
+ import FontAwesome6 from '@expo/vector-icons/FontAwesome6';
8
+ import { TouchableHighlight } from 'react-native-gesture-handler';
8
9
  interface IFDropdown {
9
10
  items: IFMenuItem[];
10
- icon?: string;
11
- label: string;
11
+ iconText?: string;
12
+ iconToShow?: JSX.Element;
13
+ label?: string;
12
14
  title?: string;
13
15
  onPress: (value: string) => void;
14
16
  }
@@ -19,34 +21,37 @@ interface IFMenuItem {
19
21
  divider?: boolean;
20
22
  }
21
23
  export const Dropdown = (props: IFDropdown) => {
22
- const { items, icon, label, title, onPress } = props;
24
+ const { items, iconText, label, title, iconToShow, onPress } = props;
23
25
  const [visible, setVisible] = useState(false);
24
26
  const openMenu = () => setVisible(true);
25
27
  const closeMenu = () => setVisible(false);
26
-
27
28
  return (
28
29
  <View style={styleDropdown['dropdown-container']}>
29
30
  <Menu
30
31
  anchorPosition="bottom"
31
- contentStyle={{ backgroundColor: 'white', borderRadius: 16, padding: 16 }}
32
+ contentStyle={styleDropdown['dropdown-content']}
32
33
  visible={visible}
33
34
  onDismiss={closeMenu}
34
35
  anchor={
35
- <View style={styleDropdown['dropdown-menu']}>
36
- <BtnIcon
37
- labelStyle={styleDropdown['dropdown-label']}
38
- contentStyle={styleDropdown['dropdown-label-content']}
39
- icon={icon}
40
- text={label}
41
- direction={'left'}
42
- onPress={openMenu}
43
- />
44
- <BtnIcon
45
- labelStyle={styleDropdown['dropdown-label-arrow']}
46
- contentStyle={styleDropdown['dropdown-label-width']}
47
- icon={icons.arrowDropdown}
48
- onPress={openMenu}
49
- />
36
+ <View
37
+ style={styleDropdown['dropdown-menu']}
38
+ >
39
+ {label &&
40
+ <BtnIcon
41
+ labelStyle={styleDropdown['dropdown-label']}
42
+ contentStyle={styleDropdown['dropdown-label-content']}
43
+ icon={iconText}
44
+ text={label}
45
+ direction={'left'}
46
+ onPress={openMenu}
47
+ />
48
+ }
49
+ <TouchableHighlight
50
+ onPress={openMenu}
51
+ underlayColor={styleDropdown['dropdown-highlight-color'].color}
52
+ >
53
+ {iconToShow ?? <FontAwesome6 name="chevron-down" size={15} color={styleDropdown['dropdown-color--primary'].color} />}
54
+ </TouchableHighlight>
50
55
  </View>
51
56
  }
52
57
  >
@@ -81,4 +86,4 @@ export const Dropdown = (props: IFDropdown) => {
81
86
  <Portal>{visible && <View style={styleDropdown['dropdown-overlay']} />}</Portal>
82
87
  </View>
83
88
  );
84
- };
89
+ };
@@ -28,10 +28,13 @@ interface IfInputText {
28
28
  isValid?: boolean;
29
29
  msgHelper?: string;
30
30
  msgError?: string;
31
+ required?: boolean;
32
+ msgErrorRequired?: string;
31
33
  }
32
34
 
33
35
  export const Input = (props: IfInputText) => {
34
36
  const [isFocus, setIsFocus] = useState<boolean>(false);
37
+ const [errorRequired, setErrorRequired] = useState<boolean>(false);
35
38
  const {
36
39
  label,
37
40
  isDisabled,
@@ -53,15 +56,22 @@ export const Input = (props: IfInputText) => {
53
56
  type,
54
57
  placeholder,
55
58
  pattern,
59
+ required,
60
+ msgErrorRequired
56
61
  } = props;
57
62
  const patternNumber = /^[0-9]*$/;
58
63
  const patternAlphanumeric = /^[a-zA-Z0-9]*$/;
64
+ const patternLettersWithAccentsAndSpaces = /^[a-zA-ZáéíóúÁÉÍÓÚñÑ\s]*$/;
59
65
  const onChangeText = (text: string) => {
60
66
  onChange(text);
67
+ setErrorRequired(false);
61
68
  if (type === 'number' && !patternNumber.test(text)) {
62
69
  onInvalid && onInvalid();
63
70
  } else if (type === 'alphanumeric' && !patternAlphanumeric.test(text)) {
64
71
  onInvalid && onInvalid();
72
+ }
73
+ else if (type === 'text' && !patternLettersWithAccentsAndSpaces.test(text)) {
74
+ onInvalid && onInvalid();
65
75
  } else if (pattern && !pattern.test(text)) {
66
76
  onInvalid && onInvalid();
67
77
  }
@@ -69,15 +79,17 @@ export const Input = (props: IfInputText) => {
69
79
  return (
70
80
  <View>
71
81
  <TextInput
72
- label={!isFocus && placeholder && value.trim() !== '' ? placeholder : label}
82
+ label={!isFocus && placeholder && value?.trim() !== '' ? placeholder : label}
73
83
  mode={mode ?? 'flat'}
74
84
  disabled={isDisabled}
75
85
  value={value}
76
86
  onChangeText={onChangeText}
77
87
  maxLength={maxLength}
88
+ selectionColor={!errorRequired ?styleInput['input'].borderBottomColor:styleInput['input-txt-error'].borderBottomColor}
78
89
  theme={{
79
90
  colors: {
80
- onSurfaceVariant: styleInput['input-txt'].color,
91
+ onSurfaceVariant: !errorRequired ?styleInput['input'].borderBottomColor:styleInput['input-txt-error'].borderBottomColor,
92
+ error: styleInput['input-txt-error'].borderBottomColor,
81
93
  },
82
94
  }}
83
95
  onFocus={() => {
@@ -87,44 +99,56 @@ export const Input = (props: IfInputText) => {
87
99
  onBlur={() => {
88
100
  setIsFocus(false);
89
101
  onBlur && onBlur();
102
+ if (value?.trim() === '' && required) {
103
+ setErrorRequired(true);
104
+ onInvalid && onInvalid();
105
+ }
90
106
  }}
91
- error={error}
107
+ error={error || errorRequired}
92
108
  textColor={textColor}
93
109
  style={[styleInput['input-label'], style ?? []]}
94
110
  contentStyle={[
95
111
  styleInput['input-label'],
96
112
  isFocus && isValid && styleInput['input-text--focused'],
97
- !isValid && value.trim() !== '' && styleInput['input-error-focused'],
98
- !isValid && !isFocus && value.trim() !== '' && styleInput['input-txt-error'],
113
+ !isValid && value?.trim() !== '' && styleInput['input-error-focused'],
114
+ !isValid && !isFocus && value?.trim() !== '' && styleInput['input-txt-error'],
115
+ errorRequired && styleInput['input-txt-error'],
116
+ errorRequired && isFocus && styleInput['input-error-focused'],
99
117
  style ?? [],
100
118
  ]}
101
119
  underlineColor={
102
120
  underlineColor
103
121
  ? underlineColor
104
- : isValid
105
- ? styleInput['input-text-underline'].color
106
- : styleInput['input-txt-error'].borderBottomColor
122
+ : isValid && !errorRequired
123
+ ? styleInput['input-text-underline'].color
124
+ : styleInput['input-txt-error'].borderBottomColor
107
125
  }
108
126
  activeUnderlineColor={
109
127
  activeUnderlineColor
110
128
  ? activeUnderlineColor
111
- : !isValid && value.trim() !== ''
112
- ? styleInput['input-text--activeUnderline'].color
113
- : ''
129
+ : !isValid && value?.trim() !== ''
130
+ ? styleInput['input-text--activeUnderline'].color
131
+ : errorRequired ? styleInput['input-txt-error'].color:''
114
132
  }
115
133
  keyboardType={type === 'number' ? 'numeric' : 'default'}
116
134
  />
117
- {isValid && (
135
+ {isValid && !errorRequired && (
118
136
  <HelperText type="info" style={styleInput['input-password-helper']} visible={true}>
119
137
  {msgHelper}
120
138
  </HelperText>
121
139
  )}
122
- {!isValid && msgError !== undefined && value.trim() !== '' && (
140
+ {!isValid && msgError !== undefined && value?.trim() !== '' && !errorRequired && (
123
141
  <View style={styleInput['input-helper--error-text']}>
124
142
  <Image style={styleInput['input-helper--error-image']} source={icons.error} />
125
143
  <Text style={styleInput['input-password-helper--error-text']}>{msgError}</Text>
126
144
  </View>
127
145
  )}
146
+ {errorRequired && (
147
+ <View style={styleInput['input-helper--error-text']}>
148
+ <Image style={styleInput['input-helper--error-image']} source={icons.error} />
149
+ <Text style={styleInput['input-password-helper--error-text']}>{msgErrorRequired}</Text>
150
+ </View>
151
+ )}
128
152
  </View>
129
153
  );
130
154
  };
@@ -25,6 +25,7 @@ interface IfInputPassword {
25
25
  msgHelper?: string;
26
26
  msgError?: string;
27
27
  pattern?: RegExp;
28
+ readonly?: boolean;
28
29
  }
29
30
 
30
31
  export const InputPassword = (props: IfInputPassword) => {
@@ -49,6 +50,7 @@ export const InputPassword = (props: IfInputPassword) => {
49
50
  msgError,
50
51
  pattern,
51
52
  onInvalid,
53
+ readonly
52
54
  } = props;
53
55
  const patternPasswordDefault = pattern ?? /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d#?!@$%^&*-]{8,}$/;
54
56
 
@@ -67,6 +69,7 @@ export const InputPassword = (props: IfInputPassword) => {
67
69
  disabled={isDisabled}
68
70
  value={value}
69
71
  onChangeText={validateText}
72
+ readOnly={readonly}
70
73
  onFocus={() => {
71
74
  setIsFocus(true);
72
75
  onFocus && onFocus();
@@ -6,14 +6,15 @@ interface IfProgressBarComponent {
6
6
  title: string;
7
7
  progressValue: number;
8
8
  style?: object;
9
+ width: number;
9
10
  isActive: boolean;
10
11
  }
11
12
 
12
13
  export const ProgressBarComponent = (props: IfProgressBarComponent) => {
13
- const { title, progressValue, style, isActive } = props;
14
+ const { title, progressValue, style, isActive,width } = props;
14
15
 
15
16
  return (
16
- <View style={styleProgressBar['progress-bar-container']}>
17
+ <View style={{width: `${width}%`}}>
17
18
  {title && (
18
19
  <Text
19
20
  style={[
@@ -15,7 +15,7 @@ interface IFProgressBar {
15
15
  export const ProgressBarSteps = (props: IFProgressBarStepsProps) => {
16
16
  const { items, currentKey, children } = props;
17
17
  const currentItem: IFProgressBar | undefined = items.find((item) => item.key === currentKey);
18
-
18
+ const width = Math.round(100 / items.length);
19
19
  return (
20
20
  <>
21
21
  <View style={styleRegisterContent['progress-bar-container']}>
@@ -23,6 +23,7 @@ export const ProgressBarSteps = (props: IFProgressBarStepsProps) => {
23
23
  return (
24
24
  <ProgressBarComponent
25
25
  key={item.key}
26
+ width={width}
26
27
  title={item.title}
27
28
  progressValue={item.progress}
28
29
  isActive={item.progress > 0 || item.key === currentKey}
@@ -34,4 +35,4 @@ export const ProgressBarSteps = (props: IFProgressBarStepsProps) => {
34
35
  {currentItem?.child}
35
36
  </>
36
37
  );
37
- };
38
+ };