ikualo-ui-kit-mobile 0.0.3 → 0.0.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.
@@ -0,0 +1,8 @@
1
+ > Why do I have a folder named ".expo" in my project?
2
+ The ".expo" folder is created when an Expo project is started using "expo start" command.
3
+ > What do the files contain?
4
+ - "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
5
+ - "settings.json": contains the server configuration that is used to serve the application manifest.
6
+ > Should I commit the ".expo" folder?
7
+ No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
8
+ Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
@@ -45,4 +45,9 @@ export const images = {
45
45
  },
46
46
  validateIdentity: require('./validateIdentity.png'),
47
47
  validationFailed: require('./validationFailed.png'),
48
+ header:{
49
+ back: require('./headerBack.png'),
50
+ close: require('./headerClose.png'),
51
+ help: require('./headerInfo.png'),
52
+ }
48
53
  };
Binary file
Binary file
Binary file
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ikualo-ui-kit-mobile",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "main": "src/index.ts",
5
5
  "scripts": {
6
6
  "start": "expo start",
@@ -27,11 +27,9 @@
27
27
  "expo-secure-store": "~13.0.2",
28
28
  "expo-status-bar": "~1.12.1",
29
29
  "expo-updates": "^0.25.14",
30
- "i18next": "^23.11.5",
31
30
  "p-retry": "^6.2.0",
32
31
  "react": "18.2.0",
33
32
  "react-dom": "18.2.0",
34
- "react-i18next": "^14.1.2",
35
33
  "react-native": "0.74.1",
36
34
  "react-native-asset": "^2.1.1",
37
35
  "react-native-country-flag": "^2.0.2",
@@ -40,8 +38,7 @@
40
38
  "react-native-paper": "^5.12.3",
41
39
  "react-native-safe-area-context": "^4.10.1",
42
40
  "react-native-screens": "^3.31.1",
43
- "react-native-web": "~0.19.10",
44
- "zustand": "^4.5.2"
41
+ "react-native-web": "~0.19.10"
45
42
  },
46
43
  "devDependencies": {
47
44
  "@babel/cli": "^7.24.8",
@@ -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',
@@ -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:24,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
  };
@@ -2,9 +2,10 @@ import { Card } from 'react-native-paper';
2
2
  import { stylesCards } from '../../../assets/styles/elements/cards';
3
3
  import { View, Text, TouchableHighlight } from 'react-native';
4
4
  import { useState } from 'react';
5
+ import { ScrollView } from 'react-native-gesture-handler';
5
6
 
6
7
  interface IfCardList {
7
- options: { value: string }[];
8
+ options: { value: string | JSX.Element, id: string }[];
8
9
  children?: React.ReactNode;
9
10
  onSelectOption: (value: string) => void;
10
11
  }
@@ -14,13 +15,13 @@ export const CardList = (props: IfCardList) => {
14
15
  const [selectedOption, setSelectOption] = useState(0);
15
16
 
16
17
  return (
17
- <View>
18
+ <ScrollView>
18
19
  {options.map((option, index) => (
19
20
  <TouchableHighlight
20
21
  key={index}
21
22
  onPress={() => {
22
23
  setSelectOption(index);
23
- onSelectOption(option.value);
24
+ onSelectOption(option.id);
24
25
  }}
25
26
  style={stylesCards['card-list-item']}
26
27
  >
@@ -34,6 +35,6 @@ export const CardList = (props: IfCardList) => {
34
35
  </Card>
35
36
  </TouchableHighlight>
36
37
  ))}
37
- </View>
38
+ </ScrollView>
38
39
  );
39
40
  };
@@ -2,32 +2,52 @@ import { Text } from 'react-native-paper';
2
2
  import { Image, TouchableOpacity, View } from 'react-native';
3
3
  import { useNavigation } from '@react-navigation/native';
4
4
  import { stylesHeader } from '../../../assets/styles/elements/header';
5
- import { icons } from '../../../assets/icons/_icons';
6
5
  import { images } from '../../../assets/images/_images';
7
6
 
8
7
  interface IFHeaderPage {
9
8
  title: string;
10
- navigateTo: string;
11
- onPress?: () => void;
9
+ navigateTo: 'Back' | string;
10
+ onPressBack?: () => void;
11
+ onPressRight?: () => void;
12
+ right: 'icon' | 'close' | 'help' | ''
12
13
  }
13
14
  export const HeaderPage = (props: IFHeaderPage) => {
14
- const { navigateTo, title, onPress } = props;
15
- const navigation = useNavigation();
15
+ const { navigateTo, title, onPressBack, onPressRight, right } = props;
16
+ const { navigate, goBack } = useNavigation();
16
17
  const navigateToScreen = () => {
17
- onPress && onPress();
18
- navigateTo === 'Back' ? navigation.goBack() : navigation.navigate(navigateTo as never);
18
+ onPressBack && onPressBack();
19
+ navigateTo === 'Back' ? goBack() : navigate(navigateTo as never);
19
20
  };
21
+ const actionsRight = [
22
+ {
23
+ name: 'icon',
24
+ component: <Image source={images.logoSmallBlack} style={stylesHeader['header-logo']} />
25
+ },
26
+ {
27
+ name: 'close',
28
+ component: <TouchableOpacity onPress={()=>onPressRight && onPressRight()}>
29
+ <Image source={images.header.close} style={stylesHeader['header-logo']} />
30
+ </TouchableOpacity>
31
+
32
+ },
33
+ {
34
+ name: 'help',
35
+ component: <TouchableOpacity onPress={()=>onPressRight && onPressRight()}>
36
+ <Image source={images.header.help} style={stylesHeader['header-logo']} />
37
+ </TouchableOpacity>
38
+ },
39
+ ]
20
40
  return (
21
41
  <View style={stylesHeader['header']}>
22
- <TouchableOpacity onPress={navigateToScreen} style={stylesHeader['header-back']}>
23
- <Image source={icons.arrowBack} style={stylesHeader['header-back-icon']} />
42
+ <TouchableOpacity onPress={navigateToScreen}>
43
+ <Image source={images.header.back} style={stylesHeader['header-logo']} />
24
44
  </TouchableOpacity>
25
-
26
- <Text variant="bodyMedium" style={stylesHeader['header-title']}>
27
- {title}
28
- </Text>
29
-
30
- <Image source={images.logoSmallBlack} style={stylesHeader['header-logo']} />
45
+ <View style={{ flex: 1, alignItems: 'center' }}>
46
+ <Text variant="bodyMedium" style={stylesHeader['header-title']}>
47
+ {title}
48
+ </Text>
49
+ </View>
50
+ {actionsRight.find(x => x.name === right)?.component ?? ""}
31
51
  </View>
32
52
  );
33
53
  };
@@ -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();