@sanctum-key/react-native-sdk 1.0.49 → 1.0.50

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 (58) hide show
  1. package/build/package.json +1 -1
  2. package/build/src/components/KYCElements/CountrySelection.d.ts.map +1 -1
  3. package/build/src/components/KYCElements/CountrySelection.js +33 -108
  4. package/build/src/components/KYCElements/CountrySelection.js.map +1 -1
  5. package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  6. package/build/src/components/KYCElements/CountrySelectionTemplate.js +50 -164
  7. package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  8. package/build/src/components/KYCElements/DocumentTypeSelection.d.ts.map +1 -1
  9. package/build/src/components/KYCElements/DocumentTypeSelection.js +32 -109
  10. package/build/src/components/KYCElements/DocumentTypeSelection.js.map +1 -1
  11. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  12. package/build/src/components/KYCElements/IDCardCapture.js +58 -25
  13. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  14. package/build/src/components/KYCElements/InitializationStep.d.ts.map +1 -1
  15. package/build/src/components/KYCElements/InitializationStep.js +13 -1
  16. package/build/src/components/KYCElements/InitializationStep.js.map +1 -1
  17. package/build/src/components/KYCElements/LocationCaptureTemplate.d.ts.map +1 -1
  18. package/build/src/components/KYCElements/LocationCaptureTemplate.js +46 -157
  19. package/build/src/components/KYCElements/LocationCaptureTemplate.js.map +1 -1
  20. package/build/src/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  21. package/build/src/components/KYCElements/SelfieCapture.js +28 -24
  22. package/build/src/components/KYCElements/SelfieCapture.js.map +1 -1
  23. package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
  24. package/build/src/components/KYCElements/VerificationProgressTemplate.js +0 -4
  25. package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
  26. package/build/src/components/SelfieCapture.d.ts.map +1 -1
  27. package/build/src/components/SelfieCapture.js +33 -90
  28. package/build/src/components/SelfieCapture.js.map +1 -1
  29. package/build/src/components/TemplateKYCExample.d.ts.map +1 -1
  30. package/build/src/components/TemplateKYCExample.js +69 -120
  31. package/build/src/components/TemplateKYCExample.js.map +1 -1
  32. package/build/src/components/TemplateKYCFlowRefactored.d.ts +0 -2
  33. package/build/src/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
  34. package/build/src/components/TemplateKYCFlowRefactored.js +95 -210
  35. package/build/src/components/TemplateKYCFlowRefactored.js.map +1 -1
  36. package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  37. package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
  38. package/build/src/types/KYC.types.d.ts.map +1 -1
  39. package/build/src/types/KYC.types.js.map +1 -1
  40. package/build/src/utils/logger.d.ts +12 -4
  41. package/build/src/utils/logger.d.ts.map +1 -1
  42. package/build/src/utils/logger.js +156 -28
  43. package/build/src/utils/logger.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/components/KYCElements/CountrySelection.tsx +36 -109
  46. package/src/components/KYCElements/CountrySelectionTemplate.tsx +67 -266
  47. package/src/components/KYCElements/DocumentTypeSelection.tsx +34 -110
  48. package/src/components/KYCElements/IDCardCapture.tsx +93 -39
  49. package/src/components/KYCElements/InitializationStep.tsx +17 -2
  50. package/src/components/KYCElements/LocationCaptureTemplate.tsx +53 -170
  51. package/src/components/KYCElements/SelfieCapture.tsx +50 -58
  52. package/src/components/KYCElements/VerificationProgressTemplate.tsx +1 -4
  53. package/src/components/SelfieCapture.tsx +44 -100
  54. package/src/components/TemplateKYCExample.tsx +94 -145
  55. package/src/components/TemplateKYCFlowRefactored.tsx +105 -239
  56. package/src/hooks/useTemplateKYCFlow.tsx +1 -0
  57. package/src/types/KYC.types.ts +0 -1
  58. package/src/utils/logger.ts +182 -29
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanctum-key/react-native-sdk",
3
- "version": "1.0.49",
3
+ "version": "1.0.50",
4
4
  "description": "Sanctum Key React Native SDK",
5
5
  "main": "build/src/index.js",
6
6
  "types": "build/src/index.d.ts",
@@ -1 +1 @@
1
- {"version":3,"file":"CountrySelection.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAoB,MAAM,uBAAuB,CAAC;AAErE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA2G5D,CAAC"}
1
+ {"version":3,"file":"CountrySelection.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAoB,MAAM,uBAAuB,CAAC;AAIrE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAoH5D,CAAC"}
@@ -1,9 +1,18 @@
1
- import React, { useState, useMemo } from 'react';
1
+ import React, { useState, useMemo, useEffect } from 'react';
2
2
  import { View, Text, TouchableOpacity, StyleSheet, FlatList, TextInput } from 'react-native';
3
+ import { sdkLogger } from '../../utils/logger';
4
+ import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
3
5
  export const CountrySelection = ({ element, value, onValueChange, error, }) => {
4
6
  const countries = element.options || [];
5
- console.log(`Countries options: ${countries}`);
6
7
  const [searchQuery, setSearchQuery] = useState('');
8
+ const { state } = useTemplateKYCFlowContext();
9
+ useEffect(() => {
10
+ if (state.session?.session_id) {
11
+ sdkLogger.info("User started country selection step", {
12
+ availableCountriesCount: countries.length
13
+ });
14
+ }
15
+ }, [state.session?.session_id, countries.length]);
7
16
  // Filter countries based on user input
8
17
  const filteredCountries = useMemo(() => {
9
18
  if (!searchQuery.trim())
@@ -16,11 +25,13 @@ export const CountrySelection = ({ element, value, onValueChange, error, }) => {
16
25
  return (<TouchableOpacity style={[
17
26
  styles.option,
18
27
  isSelected && styles.selectedOption
19
- ]} onPress={() => onValueChange(country.value)} activeOpacity={0.7}
28
+ ]} onPress={() => {
29
+ sdkLogger.info("User selected country", { countryCode: country.value }); // 🚨 LOG
30
+ onValueChange(country.value);
31
+ }} activeOpacity={0.7}
20
32
  // Accessibility Enhancements
21
33
  accessible={true} accessibilityRole="button" accessibilityState={{ selected: isSelected }} accessibilityLabel={`${country.label}. ${isSelected ? 'Selected' : 'Unselected'}.`} accessibilityHint={`Tap to select ${country.label} as your country`}>
22
34
  <Text style={styles.optionIcon}>{country.icon}</Text>
23
-
24
35
  <View style={styles.optionContent}>
25
36
  <Text style={[
26
37
  styles.optionLabel,
@@ -30,7 +41,6 @@ export const CountrySelection = ({ element, value, onValueChange, error, }) => {
30
41
  </Text>
31
42
  {country.description && (<Text style={styles.optionDescription}>{country.description}</Text>)}
32
43
  </View>
33
-
34
44
  {isSelected && (<View style={styles.checkmark}>
35
45
  <Text style={styles.checkmarkText}>✓</Text>
36
46
  </View>)}
@@ -40,7 +50,7 @@ export const CountrySelection = ({ element, value, onValueChange, error, }) => {
40
50
  <View style={styles.headerContainer}>
41
51
  <Text style={styles.title} accessibilityRole="header">{element.title}</Text>
42
52
  <Text style={styles.description}>{element.description}</Text>
43
-
53
+
44
54
  {/* Search Bar */}
45
55
  <TextInput style={styles.searchInput} placeholder="Rechercher un pays..." placeholderTextColor="#999" value={searchQuery} onChangeText={setSearchQuery} clearButtonMode="while-editing" // Adds a clear 'x' on iOS
46
56
 
@@ -53,111 +63,26 @@ export const CountrySelection = ({ element, value, onValueChange, error, }) => {
53
63
  initialNumToRender={15} maxToRenderPerBatch={20} windowSize={5} removeClippedSubviews={true} accessibilityRole="list" ListEmptyComponent={<Text style={styles.emptyText} accessibilityRole="text">
54
64
  Aucun pays configuré ou trouvé.
55
65
  </Text>}/>
56
-
57
66
  {error && (<Text style={styles.errorText} accessibilityRole="alert">{error}</Text>)}
58
67
  </View>);
59
68
  };
60
69
  const styles = StyleSheet.create({
61
- container: {
62
- flex: 1,
63
- backgroundColor: '#fff',
64
- },
65
- headerContainer: {
66
- paddingHorizontal: 16,
67
- paddingTop: 16,
68
- paddingBottom: 8,
69
- },
70
- title: {
71
- fontSize: 24,
72
- fontWeight: 'bold',
73
- color: '#333',
74
- marginBottom: 8,
75
- textAlign: 'center',
76
- },
77
- description: {
78
- fontSize: 16,
79
- color: '#666',
80
- textAlign: 'center',
81
- marginBottom: 16,
82
- lineHeight: 22,
83
- },
84
- searchInput: {
85
- backgroundColor: '#f5f5f5',
86
- borderRadius: 10,
87
- padding: 12,
88
- fontSize: 16,
89
- color: '#333',
90
- borderWidth: 1,
91
- borderColor: '#e5e5e5',
92
- marginBottom: 8,
93
- },
94
- listContent: {
95
- paddingHorizontal: 16,
96
- paddingBottom: 24,
97
- },
98
- emptyText: {
99
- textAlign: 'center',
100
- color: '#999',
101
- marginTop: 20,
102
- fontSize: 16,
103
- },
104
- option: {
105
- flexDirection: 'row',
106
- alignItems: 'center',
107
- padding: 16,
108
- backgroundColor: 'white',
109
- borderRadius: 12,
110
- marginBottom: 12,
111
- borderWidth: 2,
112
- borderColor: '#e5e5e5',
113
- shadowColor: '#000',
114
- shadowOffset: { width: 0, height: 2 },
115
- shadowOpacity: 0.05,
116
- shadowRadius: 3.84,
117
- elevation: 3,
118
- },
119
- selectedOption: {
120
- borderColor: '#4CAF50',
121
- backgroundColor: '#f0f9f0',
122
- },
123
- optionIcon: {
124
- fontSize: 32,
125
- marginRight: 16,
126
- },
127
- optionContent: {
128
- flex: 1,
129
- },
130
- optionLabel: {
131
- fontSize: 18,
132
- fontWeight: '600',
133
- color: '#333',
134
- },
135
- selectedOptionLabel: {
136
- color: '#4CAF50',
137
- },
138
- optionDescription: {
139
- fontSize: 14,
140
- color: '#666',
141
- marginTop: 4,
142
- },
143
- checkmark: {
144
- width: 24,
145
- height: 24,
146
- borderRadius: 12,
147
- backgroundColor: '#4CAF50',
148
- justifyContent: 'center',
149
- alignItems: 'center',
150
- },
151
- checkmarkText: {
152
- color: 'white',
153
- fontSize: 16,
154
- fontWeight: 'bold',
155
- },
156
- errorText: {
157
- color: '#dc2626',
158
- fontSize: 14,
159
- margin: 16,
160
- textAlign: 'center',
161
- },
70
+ container: { flex: 1, backgroundColor: '#fff', },
71
+ headerContainer: { paddingHorizontal: 16, paddingTop: 16, paddingBottom: 8, },
72
+ title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center', },
73
+ description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 16, lineHeight: 22, },
74
+ searchInput: { backgroundColor: '#f5f5f5', borderRadius: 10, padding: 12, fontSize: 16, color: '#333', borderWidth: 1, borderColor: '#e5e5e5', marginBottom: 8, },
75
+ listContent: { paddingHorizontal: 16, paddingBottom: 24, },
76
+ emptyText: { textAlign: 'center', color: '#999', marginTop: 20, fontSize: 16, },
77
+ option: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: 'white', borderRadius: 12, marginBottom: 12, borderWidth: 2, borderColor: '#e5e5e5', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 3.84, elevation: 3, },
78
+ selectedOption: { borderColor: '#4CAF50', backgroundColor: '#f0f9f0', },
79
+ optionIcon: { fontSize: 32, marginRight: 16, },
80
+ optionContent: { flex: 1, },
81
+ optionLabel: { fontSize: 18, fontWeight: '600', color: '#333', },
82
+ selectedOptionLabel: { color: '#4CAF50', },
83
+ optionDescription: { fontSize: 14, color: '#666', marginTop: 4, },
84
+ checkmark: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#4CAF50', justifyContent: 'center', alignItems: 'center', },
85
+ checkmarkText: { color: 'white', fontSize: 16, fontWeight: 'bold', },
86
+ errorText: { color: '#dc2626', fontSize: 14, margin: 16, textAlign: 'center', },
162
87
  });
163
88
  //# sourceMappingURL=CountrySelection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CountrySelection.js","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelection.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { View, Text, TouchableOpacity, StyleSheet, FlatList, TextInput } from 'react-native';\nimport { KYCElement, KYCElementOption } from '../../types/KYC.types';\n\ninterface CountrySelectionProps {\n element: KYCElement;\n value?: string;\n onValueChange: (value: string) => void;\n error?: string;\n}\n\nexport const CountrySelection: React.FC<CountrySelectionProps> = ({\n element,\n value,\n onValueChange,\n error,\n}) => {\n const countries = element.options || [];\n console.log(`Countries options: ${countries}`)\n\n const [searchQuery, setSearchQuery] = useState('');\n\n // Filter countries based on user input\n const filteredCountries = useMemo(() => {\n if (!searchQuery.trim()) return countries;\n return countries.filter(country =>\n country.label.toLowerCase().includes(searchQuery.toLowerCase())\n );\n }, [countries, searchQuery]);\n\n // Extract the render logic into a separate function for FlatList performance\n const renderCountry = ({ item: country }: { item: KYCElementOption }) => {\n const isSelected = value === country.value;\n\n return (\n <TouchableOpacity\n style={[\n styles.option,\n isSelected && styles.selectedOption\n ]}\n onPress={() => onValueChange(country.value)}\n activeOpacity={0.7}\n // Accessibility Enhancements\n accessible={true}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: isSelected }}\n accessibilityLabel={`${country.label}. ${isSelected ? 'Selected' : 'Unselected'}.`}\n accessibilityHint={`Tap to select ${country.label} as your country`}\n >\n <Text style={styles.optionIcon}>{country.icon}</Text>\n \n <View style={styles.optionContent}>\n <Text style={[\n styles.optionLabel,\n isSelected && styles.selectedOptionLabel\n ]}>\n {country.label}\n </Text>\n {country.description && (\n <Text style={styles.optionDescription}>{country.description}</Text>\n )}\n </View>\n\n {isSelected && (\n <View style={styles.checkmark}>\n <Text style={styles.checkmarkText}>✓</Text>\n </View>\n )}\n </TouchableOpacity>\n );\n };\n\n return (\n <View style={styles.container}>\n <View style={styles.headerContainer}>\n <Text style={styles.title} accessibilityRole=\"header\">{element.title}</Text>\n <Text style={styles.description}>{element.description}</Text>\n \n {/* Search Bar */}\n <TextInput\n style={styles.searchInput}\n placeholder=\"Rechercher un pays...\"\n placeholderTextColor=\"#999\"\n value={searchQuery}\n onChangeText={setSearchQuery}\n clearButtonMode=\"while-editing\" // Adds a clear 'x' on iOS\n // Accessibility for Search\n accessibilityRole=\"search\"\n accessibilityLabel=\"Search countries\"\n accessibilityHint=\"Type to filter the list of configured countries below\"\n />\n </View>\n\n <FlatList\n data={filteredCountries}\n keyExtractor={(item) => item.value}\n renderItem={renderCountry}\n showsVerticalScrollIndicator={true} // Enable scroll indicator for better UX visibility\n contentContainerStyle={styles.listContent}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\" // 🚨 UX FIX: Hides keyboard naturally when user starts scrolling\n initialNumToRender={15}\n maxToRenderPerBatch={20}\n windowSize={5}\n removeClippedSubviews={true}\n accessibilityRole=\"list\"\n ListEmptyComponent={\n <Text style={styles.emptyText} accessibilityRole=\"text\">\n Aucun pays configuré ou trouvé.\n </Text>\n }\n />\n\n {error && (\n <Text style={styles.errorText} accessibilityRole=\"alert\">{error}</Text>\n )}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: '#fff',\n },\n headerContainer: {\n paddingHorizontal: 16,\n paddingTop: 16,\n paddingBottom: 8,\n },\n title: {\n fontSize: 24,\n fontWeight: 'bold',\n color: '#333',\n marginBottom: 8,\n textAlign: 'center',\n },\n description: {\n fontSize: 16,\n color: '#666',\n textAlign: 'center',\n marginBottom: 16,\n lineHeight: 22,\n },\n searchInput: {\n backgroundColor: '#f5f5f5',\n borderRadius: 10,\n padding: 12,\n fontSize: 16,\n color: '#333',\n borderWidth: 1,\n borderColor: '#e5e5e5',\n marginBottom: 8,\n },\n listContent: {\n paddingHorizontal: 16,\n paddingBottom: 24,\n },\n emptyText: {\n textAlign: 'center',\n color: '#999',\n marginTop: 20,\n fontSize: 16,\n },\n option: {\n flexDirection: 'row',\n alignItems: 'center',\n padding: 16,\n backgroundColor: 'white',\n borderRadius: 12,\n marginBottom: 12,\n borderWidth: 2,\n borderColor: '#e5e5e5',\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.05,\n shadowRadius: 3.84,\n elevation: 3,\n },\n selectedOption: {\n borderColor: '#4CAF50',\n backgroundColor: '#f0f9f0',\n },\n optionIcon: {\n fontSize: 32,\n marginRight: 16,\n },\n optionContent: {\n flex: 1,\n },\n optionLabel: {\n fontSize: 18,\n fontWeight: '600',\n color: '#333',\n },\n selectedOptionLabel: {\n color: '#4CAF50',\n },\n optionDescription: {\n fontSize: 14,\n color: '#666',\n marginTop: 4,\n },\n checkmark: {\n width: 24,\n height: 24,\n borderRadius: 12,\n backgroundColor: '#4CAF50',\n justifyContent: 'center',\n alignItems: 'center',\n },\n checkmarkText: {\n color: 'white',\n fontSize: 16,\n fontWeight: 'bold',\n },\n errorText: {\n color: '#dc2626',\n fontSize: 14,\n margin: 16,\n textAlign: 'center',\n },\n});"]}
1
+ {"version":3,"file":"CountrySelection.js","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelection.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useMemo, useEffect } from 'react';\nimport { View, Text, TouchableOpacity, StyleSheet, FlatList, TextInput } from 'react-native';\nimport { KYCElement, KYCElementOption } from '../../types/KYC.types';\nimport { sdkLogger } from '../../utils/logger'; \nimport { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow'; \n\ninterface CountrySelectionProps {\n element: KYCElement;\n value?: string;\n onValueChange: (value: string) => void;\n error?: string;\n}\n\nexport const CountrySelection: React.FC<CountrySelectionProps> = ({\n element,\n value,\n onValueChange,\n error,\n}) => {\n const countries = element.options || [];\n const [searchQuery, setSearchQuery] = useState('');\n \n const { state } = useTemplateKYCFlowContext();\n\n useEffect(() => {\n if (state.session?.session_id) {\n sdkLogger.info(\"User started country selection step\", { \n availableCountriesCount: countries.length \n });\n }\n }, [state.session?.session_id, countries.length]);\n\n // Filter countries based on user input\n const filteredCountries = useMemo(() => {\n if (!searchQuery.trim()) return countries;\n return countries.filter(country =>\n country.label.toLowerCase().includes(searchQuery.toLowerCase())\n );\n }, [countries, searchQuery]);\n\n // Extract the render logic into a separate function for FlatList performance\n const renderCountry = ({ item: country }: { item: KYCElementOption }) => {\n const isSelected = value === country.value;\n\n return (\n <TouchableOpacity\n style={[\n styles.option,\n isSelected && styles.selectedOption\n ]}\n onPress={() => {\n sdkLogger.info(\"User selected country\", { countryCode: country.value }); // 🚨 LOG\n onValueChange(country.value);\n }}\n activeOpacity={0.7}\n // Accessibility Enhancements\n accessible={true}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: isSelected }}\n accessibilityLabel={`${country.label}. ${isSelected ? 'Selected' : 'Unselected'}.`}\n accessibilityHint={`Tap to select ${country.label} as your country`}\n >\n <Text style={styles.optionIcon}>{country.icon}</Text>\n <View style={styles.optionContent}>\n <Text style={[\n styles.optionLabel,\n isSelected && styles.selectedOptionLabel\n ]}>\n {country.label}\n </Text>\n {country.description && (\n <Text style={styles.optionDescription}>{country.description}</Text>\n )}\n </View>\n {isSelected && (\n <View style={styles.checkmark}>\n <Text style={styles.checkmarkText}>✓</Text>\n </View>\n )}\n </TouchableOpacity>\n );\n };\n\n return (\n <View style={styles.container}>\n <View style={styles.headerContainer}>\n <Text style={styles.title} accessibilityRole=\"header\">{element.title}</Text>\n <Text style={styles.description}>{element.description}</Text>\n\n {/* Search Bar */}\n <TextInput\n style={styles.searchInput}\n placeholder=\"Rechercher un pays...\"\n placeholderTextColor=\"#999\"\n value={searchQuery}\n onChangeText={setSearchQuery}\n clearButtonMode=\"while-editing\" // Adds a clear 'x' on iOS\n \n // Accessibility for Search\n accessibilityRole=\"search\"\n accessibilityLabel=\"Search countries\"\n accessibilityHint=\"Type to filter the list of configured countries below\"\n />\n </View>\n\n <FlatList\n data={filteredCountries}\n keyExtractor={(item) => item.value}\n renderItem={renderCountry}\n showsVerticalScrollIndicator={true} // Enable scroll indicator for better UX visibility\n contentContainerStyle={styles.listContent}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\" // 🚨 UX FIX: Hides keyboard naturally when user starts scrolling\n initialNumToRender={15}\n maxToRenderPerBatch={20}\n windowSize={5}\n removeClippedSubviews={true}\n accessibilityRole=\"list\"\n ListEmptyComponent={\n <Text style={styles.emptyText} accessibilityRole=\"text\">\n Aucun pays configuré ou trouvé.\n </Text>\n }\n />\n {error && (\n <Text style={styles.errorText} accessibilityRole=\"alert\">{error}</Text>\n )}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, backgroundColor: '#fff', },\n headerContainer: { paddingHorizontal: 16, paddingTop: 16, paddingBottom: 8, },\n title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center', },\n description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 16, lineHeight: 22, },\n searchInput: { backgroundColor: '#f5f5f5', borderRadius: 10, padding: 12, fontSize: 16, color: '#333', borderWidth: 1, borderColor: '#e5e5e5', marginBottom: 8, },\n listContent: { paddingHorizontal: 16, paddingBottom: 24, },\n emptyText: { textAlign: 'center', color: '#999', marginTop: 20, fontSize: 16, },\n option: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: 'white', borderRadius: 12, marginBottom: 12, borderWidth: 2, borderColor: '#e5e5e5', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.05, shadowRadius: 3.84, elevation: 3, },\n selectedOption: { borderColor: '#4CAF50', backgroundColor: '#f0f9f0', },\n optionIcon: { fontSize: 32, marginRight: 16, },\n optionContent: { flex: 1, },\n optionLabel: { fontSize: 18, fontWeight: '600', color: '#333', },\n selectedOptionLabel: { color: '#4CAF50', },\n optionDescription: { fontSize: 14, color: '#666', marginTop: 4, },\n checkmark: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#4CAF50', justifyContent: 'center', alignItems: 'center', },\n checkmarkText: { color: 'white', fontSize: 16, fontWeight: 'bold', },\n errorText: { color: '#dc2626', fontSize: 14, margin: 16, textAlign: 'center', },\n});"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CountrySelectionTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelectionTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAyC,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAOxH,UAAU,6BAA6B;IACrC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAuCD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,CAqe5E,CAAC"}
1
+ {"version":3,"file":"CountrySelectionTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelectionTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAyC,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAQxH,UAAU,6BAA6B;IACrC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAeD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,CAqT5E,CAAC"}
@@ -5,40 +5,21 @@ import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
5
5
  import { Button } from '../ui/Button';
6
6
  import { countryData } from '../../config/countriesData';
7
7
  import REGION_MAPPING from '../../config/region_mapping.json';
8
+ import { sdkLogger } from '../../utils/logger'; // 🚨 IMPORT SDK LOGGER
8
9
  const ISO_TO_COUNTRY_NAME = { 'KE': 'Kenya', 'CM': 'Cameroon', 'NG': 'Nigeria', 'CA': 'Canada', 'FR': 'France', 'GH': 'Ghana', 'ZA': 'South Africa', 'GB': 'Britain', 'CI': 'Ivory Coast', 'SN': 'Senegal', 'TG': 'Togo', 'ML': 'Mali' };
9
- const jsonDocMap = {
10
- 'nationalId': 'identity_card',
11
- 'national_id': 'identity_card',
12
- 'passport': 'passport',
13
- 'driversLicense': 'drivers_licence',
14
- 'drivers_licence': 'drivers_licence',
15
- 'residencePermit': 'permanent_residence',
16
- 'healthInsuranceCard': 'health_insurance_card'
17
- };
18
- const SUB_REGION_CODES = {
19
- "Alberta": "AB",
20
- "British Columbia": "BC",
21
- "Manitoba": "MB",
22
- "New Brunswick": "NB",
23
- "Newfoundland and Labrador": "NL",
24
- "Northwest Territories": "NT",
25
- "Nova Scotia": "NS",
26
- "Nunavut": "NU",
27
- "Ontario": "ON",
28
- "Prince Edward Island": "PE",
29
- "Quebec": "QC",
30
- "Saskatchewan": "SK",
31
- "Yukon": "YT"
32
- };
10
+ const jsonDocMap = { 'nationalId': 'identity_card', 'national_id': 'identity_card', 'passport': 'passport', 'driversLicense': 'drivers_licence', 'drivers_licence': 'drivers_licence', 'residencePermit': 'permanent_residence', 'healthInsuranceCard': 'health_insurance_card' };
11
+ const SUB_REGION_CODES = { "Alberta": "AB", "British Columbia": "BC", "Manitoba": "MB", "New Brunswick": "NB", "Newfoundland and Labrador": "NL", "Northwest Territories": "NT", "Nova Scotia": "NS", "Nunavut": "NU", "Ontario": "ON", "Prince Edward Island": "PE", "Quebec": "QC", "Saskatchewan": "SK", "Yukon": "YT" };
33
12
  export const CountrySelectionTemplate = ({ component, value, onValueChange, error, language = 'en', }) => {
34
13
  const config = component.config;
35
14
  const { actions, state } = useTemplateKYCFlowContext();
36
- const idCardComponent = useMemo(() => {
37
- return state.template.components.find(c => c.type === 'id_card');
38
- }, [state.template.components]);
39
- const idCardConfig = useMemo(() => {
40
- return idCardComponent?.config;
41
- }, [idCardComponent]);
15
+ // 🚨 LOG: Track when the user reaches this step
16
+ useEffect(() => {
17
+ if (state.session?.session_id) {
18
+ sdkLogger.info("User started country and document selection step");
19
+ }
20
+ }, [state.session?.session_id]);
21
+ const idCardComponent = useMemo(() => { return state.template.components.find(c => c.type === 'id_card'); }, [state.template.components]);
22
+ const idCardConfig = useMemo(() => { return idCardComponent?.config; }, [idCardComponent]);
42
23
  const [currentStep, setCurrentStep] = useState(() => {
43
24
  if (value?.code && value?.documentType) {
44
25
  if (value.region)
@@ -107,18 +88,14 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
107
88
  if (!searchQuery.trim())
108
89
  return availableCountries;
109
90
  const cleanQuery = searchQuery.toLowerCase().trim();
110
- return availableCountries.filter(country => country.name.toLowerCase().includes(cleanQuery) ||
111
- country.name_en.toLowerCase().includes(cleanQuery) ||
112
- country.code.toLowerCase().includes(cleanQuery));
91
+ return availableCountries.filter(country => country.name.toLowerCase().includes(cleanQuery) || country.name_en.toLowerCase().includes(cleanQuery) || country.code.toLowerCase().includes(cleanQuery));
113
92
  }, [searchQuery, availableCountries]);
114
93
  const availableDocumentTypes = useMemo(() => {
115
94
  if (!selectedCountryCode)
116
95
  return [];
117
- // Check if custom layout configuration explicitly defined items for it
118
96
  if (idCardConfig?.documentTypesByCountry?.[selectedCountryCode]) {
119
97
  return idCardConfig.documentTypesByCountry[selectedCountryCode];
120
98
  }
121
- // Default Fallback: Query mapping matrix dynamically
122
99
  const rawCountryName = ISO_TO_COUNTRY_NAME[selectedCountryCode] || selectedCountryCode;
123
100
  const baseMapping = REGION_MAPPING.regionMapping || REGION_MAPPING;
124
101
  let countryMapping = baseMapping[rawCountryName];
@@ -128,13 +105,7 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
128
105
  countryMapping = baseMapping[foundKey];
129
106
  }
130
107
  if (countryMapping) {
131
- const inverseDocMap = {
132
- 'identity_card': 'nationalId',
133
- 'passport': 'passport',
134
- 'drivers_licence': 'driversLicense',
135
- 'permanent_residence': 'residencePermit',
136
- 'health_insurance_card': 'healthInsuranceCard'
137
- };
108
+ const inverseDocMap = { 'identity_card': 'nationalId', 'passport': 'passport', 'drivers_licence': 'driversLicense', 'permanent_residence': 'residencePermit', 'health_insurance_card': 'healthInsuranceCard' };
138
109
  return Object.keys(countryMapping).map(key => inverseDocMap[key] || key);
139
110
  }
140
111
  return ['nationalId', 'passport', 'driversLicense'];
@@ -162,47 +133,32 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
162
133
  }
163
134
  if (!Array.isArray(rawRegions))
164
135
  return [];
165
- return rawRegions.sort((a, b) => a.localeCompare(b)).map(region => ({
166
- label: region,
167
- value: SUB_REGION_CODES[region] || region
168
- }));
136
+ return rawRegions.sort((a, b) => a.localeCompare(b)).map(region => ({ label: region, value: SUB_REGION_CODES[region] || region }));
169
137
  }, [selectedCountryCode, selectedDocumentType, idCardConfig?.regionsByCountry]);
170
- const needsRegion = useMemo(() => {
171
- return availableRegions.length > 0;
172
- }, [availableRegions]);
173
- const getLocalizedText = (text) => {
174
- return text[state.currentLanguage] || text.en || '';
175
- };
176
- const handleCountrySelect = (countryCode) => {
177
- setSelectedCountryCode(countryCode);
178
- setSelectedDocumentType(null);
179
- setSelectedRegion(null);
180
- };
181
- const handleDocumentTypeSelect = (docType) => {
182
- setSelectedDocumentType(docType);
183
- setSelectedRegion(null);
184
- };
185
- const handleRegionSelect = (regionValue) => {
186
- setSelectedRegion(regionValue);
187
- };
138
+ const needsRegion = useMemo(() => { return availableRegions.length > 0; }, [availableRegions]);
139
+ const getLocalizedText = (text) => { return text[state.currentLanguage] || text.en || ''; };
140
+ const handleCountrySelect = (countryCode) => { setSelectedCountryCode(countryCode); setSelectedDocumentType(null); setSelectedRegion(null); };
141
+ const handleDocumentTypeSelect = (docType) => { setSelectedDocumentType(docType); setSelectedRegion(null); };
142
+ const handleRegionSelect = (regionValue) => { setSelectedRegion(regionValue); };
188
143
  const finalizeSelection = (countryCode, docType, region) => {
189
144
  const country = countryData[countryCode];
190
145
  if (!country)
191
146
  return;
147
+ // 🚨 LOG: Final payload successfully selected
148
+ sdkLogger.info("User finalized document configuration", {
149
+ countryCode,
150
+ documentType: docType,
151
+ region: region || 'none'
152
+ });
192
153
  const mapping = countryMapping[countryCode];
193
154
  const countryObj = {
194
- code: countryCode,
195
- ...country,
196
- regionMapping: mapping,
197
- documentType: docType,
198
- region: region || undefined,
155
+ code: countryCode, ...country, regionMapping: mapping, documentType: docType, region: region || undefined,
199
156
  };
200
157
  onValueChange(countryObj);
201
- setTimeout(() => {
202
- actions.nextComponent(countryObj);
203
- }, 100);
158
+ setTimeout(() => { actions.nextComponent(countryObj); }, 100);
204
159
  };
205
160
  const handleBack = () => {
161
+ sdkLogger.info("User navigated back in document selection", { fromStep: currentStep }); // 🚨 LOG
206
162
  if (currentStep === 'region') {
207
163
  setCurrentStep('documentType');
208
164
  setSelectedRegion(null);
@@ -241,40 +197,20 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
241
197
  return (<>
242
198
  <TextInput style={styles.searchBar} placeholder={state.currentLanguage === "en" ? "🔍 Search country..." : "🔍 Rechercher un pays..."} placeholderTextColor="#94A3B8" value={searchQuery} onChangeText={setSearchQuery} autoCorrect={false}/>
243
199
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
244
- {filteredCountries.map((country) => (<TouchableOpacity key={country.code} style={[
245
- styles.option,
246
- selectedCountryCode === country.code && styles.selectedOption
247
- ]} onPress={() => handleCountrySelect(country.code)}>
200
+ {filteredCountries.map((country) => (<TouchableOpacity key={country.code} style={[styles.option, selectedCountryCode === country.code && styles.selectedOption]} onPress={() => handleCountrySelect(country.code)}>
248
201
  <Text style={styles.flag}>{country.flag}</Text>
249
-
250
202
  <View style={styles.optionContent}>
251
- <Text style={[
252
- styles.optionName,
253
- selectedCountryCode === country.code && styles.selectedOptionName
254
- ]}>
255
- {state.currentLanguage === "en" ? country.name_en : country.name}
256
- </Text>
203
+ <Text style={[styles.optionName, selectedCountryCode === country.code && styles.selectedOptionName]}>{state.currentLanguage === "en" ? country.name_en : country.name}</Text>
257
204
  <Text style={styles.optionCode}>{country.code}</Text>
258
205
  </View>
259
-
260
- {selectedCountryCode === country.code && (<View style={[
261
- styles.checkmark,
262
- { backgroundColor: component.ui.themeColor || '#2DBD60' }
263
- ]}>
264
- <Text style={styles.checkmarkText}>✓</Text>
265
- </View>)}
206
+ {selectedCountryCode === country.code && (<View style={[styles.checkmark, { backgroundColor: component.ui.themeColor || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>)}
266
207
  </TouchableOpacity>))}
267
-
268
- {filteredCountries.length === 0 && (<Text style={styles.emptyText}>
269
- {state.currentLanguage === "en" ? "No matching countries found." : "Aucun pays trouvé."}
270
- </Text>)}
208
+ {filteredCountries.length === 0 && (<Text style={styles.emptyText}>{state.currentLanguage === "en" ? "No matching countries found." : "Aucun pays trouvé."}</Text>)}
271
209
  </ScrollView>
272
210
  </>);
273
211
  };
274
212
  const renderDocumentTypeSelection = () => {
275
- const instructions = selectedDocumentType && idCardConfig?.instructionsByDocumentType?.[selectedDocumentType]
276
- ? getLocalizedText(idCardConfig.instructionsByDocumentType[selectedDocumentType])
277
- : null;
213
+ const instructions = selectedDocumentType && idCardConfig?.instructionsByDocumentType?.[selectedDocumentType] ? getLocalizedText(idCardConfig.instructionsByDocumentType[selectedDocumentType]) : null;
278
214
  const documentTypeLabels = {
279
215
  'nationalId': { en: 'National ID', fr: 'Carte nationale d\'identité', icon: '🏛️' },
280
216
  'passport': { en: 'Passport', fr: 'Passeport', icon: '📘' },
@@ -283,33 +219,18 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
283
219
  'healthInsuranceCard': { en: 'Health Insurance Card', fr: 'Carte d\'assurance maladie', icon: '🗳️' },
284
220
  };
285
221
  return (<>
286
- {instructions && (<View style={styles.infoBox}>
287
- <Text style={styles.infoText}>{instructions}</Text>
288
- </View>)}
222
+ {instructions && (<View style={styles.infoBox}><Text style={styles.infoText}>{instructions}</Text></View>)}
289
223
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
290
224
  {availableDocumentTypes.map((docType) => {
291
225
  const label = documentTypeLabels[docType];
292
226
  const displayName = label ? (state.currentLanguage === "en" ? label.en : label.fr) : docType;
293
227
  const icon = label?.icon || '📄';
294
- return (<TouchableOpacity key={docType} style={[
295
- styles.option,
296
- selectedDocumentType === docType && styles.selectedOption
297
- ]} onPress={() => handleDocumentTypeSelect(docType)}>
228
+ return (<TouchableOpacity key={docType} style={[styles.option, selectedDocumentType === docType && styles.selectedOption]} onPress={() => handleDocumentTypeSelect(docType)}>
298
229
  <Text style={styles.flag}>{icon}</Text>
299
230
  <View style={styles.optionContent}>
300
- <Text style={[
301
- styles.optionName,
302
- selectedDocumentType === docType && styles.selectedOptionName
303
- ]}>
304
- {displayName}
305
- </Text>
231
+ <Text style={[styles.optionName, selectedDocumentType === docType && styles.selectedOptionName]}>{displayName}</Text>
306
232
  </View>
307
- {selectedDocumentType === docType && (<View style={[
308
- styles.checkmark,
309
- { backgroundColor: component.ui.themeColor || '#2DBD60' }
310
- ]}>
311
- <Text style={styles.checkmarkText}>✓</Text>
312
- </View>)}
233
+ {selectedDocumentType === docType && (<View style={[styles.checkmark, { backgroundColor: component.ui.themeColor || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>)}
313
234
  </TouchableOpacity>);
314
235
  })}
315
236
  </ScrollView>
@@ -319,25 +240,12 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
319
240
  return (<>
320
241
  <ScrollView style={styles.listContainer} showsVerticalScrollIndicator={false}>
321
242
  {availableRegions.map((regionObj, index) => {
322
- return (<TouchableOpacity key={index} style={[
323
- styles.option,
324
- selectedRegion === regionObj.value && styles.selectedOption
325
- ]} onPress={() => handleRegionSelect(regionObj.value)}>
243
+ return (<TouchableOpacity key={index} style={[styles.option, selectedRegion === regionObj.value && styles.selectedOption]} onPress={() => handleRegionSelect(regionObj.value)}>
326
244
  <View style={styles.optionContent}>
327
- <Text style={[
328
- styles.optionName,
329
- selectedRegion === regionObj.value && styles.selectedOptionName
330
- ]}>
331
- {regionObj.label}
332
- </Text>
245
+ <Text style={[styles.optionName, selectedRegion === regionObj.value && styles.selectedOptionName]}>{regionObj.label}</Text>
333
246
  {regionObj.value !== regionObj.label && (<Text style={styles.optionCode}>{regionObj.value}</Text>)}
334
247
  </View>
335
- {selectedRegion === regionObj.value && (<View style={[
336
- styles.checkmark,
337
- { backgroundColor: component.ui.themeColor || '#2DBD60' }
338
- ]}>
339
- <Text style={styles.checkmarkText}>✓</Text>
340
- </View>)}
248
+ {selectedRegion === regionObj.value && (<View style={[styles.checkmark, { backgroundColor: component.ui.themeColor || '#2DBD60' }]}><Text style={styles.checkmarkText}>✓</Text></View>)}
341
249
  </TouchableOpacity>);
342
250
  })}
343
251
  </ScrollView>
@@ -345,30 +253,18 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
345
253
  };
346
254
  const getStepTitle = () => {
347
255
  switch (currentStep) {
348
- case 'country':
349
- return getLocalizedText(component.labels);
350
- case 'documentType':
351
- return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
352
- case 'region':
353
- return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
354
- default:
355
- return '';
256
+ case 'country': return getLocalizedText(component.labels);
257
+ case 'documentType': return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
258
+ case 'region': return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
259
+ default: return '';
356
260
  }
357
261
  };
358
262
  const getStepDescription = () => {
359
263
  switch (currentStep) {
360
- case 'country':
361
- return getLocalizedText(component.instructions);
362
- case 'documentType':
363
- return state.currentLanguage === "en"
364
- ? "Choose the type of document you want to use"
365
- : "Choisissez le type de document que vous souhaitez utiliser";
366
- case 'region':
367
- return state.currentLanguage === "en"
368
- ? "Select the issuing province or territory"
369
- : "Sélectionnez la province ou le territoire de délivrance";
370
- default:
371
- return '';
264
+ case 'country': return getLocalizedText(component.instructions);
265
+ case 'documentType': return state.currentLanguage === "en" ? "Choose the type of document you want to use" : "Choisissez le type de document que vous souhaitez utiliser";
266
+ case 'region': return state.currentLanguage === "en" ? "Select the issuing province or territory" : "Sélectionnez la province ou le territoire de délivrance";
267
+ default: return '';
372
268
  }
373
269
  };
374
270
  const getProgressStep = () => {
@@ -378,9 +274,7 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
378
274
  return 2;
379
275
  return 3;
380
276
  };
381
- const getTotalSteps = () => {
382
- return needsRegion ? 3 : 2;
383
- };
277
+ const getTotalSteps = () => { return needsRegion ? 3 : 2; };
384
278
  const canGoNext = () => {
385
279
  if (currentStep === 'country')
386
280
  return selectedCountryCode !== null;
@@ -393,25 +287,17 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
393
287
  return (<View style={styles.root}>
394
288
  <View style={styles.container}>
395
289
  <View style={styles.progressContainer}>
396
- <Text style={styles.progressText}>
397
- {state.currentLanguage === "en"
398
- ? `Step ${getProgressStep()} of ${getTotalSteps()}`
399
- : `Étape ${getProgressStep()} sur ${getTotalSteps()}`}
400
- </Text>
290
+ <Text style={styles.progressText}>{state.currentLanguage === "en" ? `Step ${getProgressStep()} of ${getTotalSteps()}` : `Étape ${getProgressStep()} sur ${getTotalSteps()}`}</Text>
401
291
  </View>
402
-
403
292
  <Text style={styles.title}>{getStepTitle()}</Text>
404
293
  <Text style={styles.description}>{getStepDescription()}</Text>
405
-
406
294
  {currentStep === 'country' && renderCountrySelection()}
407
295
  {currentStep === 'documentType' && renderDocumentTypeSelection()}
408
296
  {currentStep === 'region' && renderRegionSelection()}
409
-
410
297
  <View style={styles.buttonContainer}>
411
298
  <Button title={state.currentLanguage === "en" ? "Back" : "Retour"} onPress={handleBack} variant={currentStep === 'country' ? "secondary" : "outline"} size="large" style={{ flex: 1, marginRight: 8 }}/>
412
299
  <Button title={state.currentLanguage === "en" ? "Next" : "Suivant"} onPress={handleNext} variant="primary" size="large" style={{ flex: 1 }} disabled={!canGoNext()}/>
413
300
  </View>
414
-
415
301
  {error && (<Text style={styles.errorText}>{error}</Text>)}
416
302
  </View>
417
303
  </View>);