@sanctum-key/react-native-sdk 1.0.18 → 1.0.20

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 (48) hide show
  1. package/README.md +1 -1
  2. package/build/package.json +3 -2
  3. package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
  4. package/build/src/components/EnhancedCameraView.js +19 -182
  5. package/build/src/components/EnhancedCameraView.js.map +1 -1
  6. package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
  7. package/build/src/components/KYCElements/CountrySelectionTemplate.js +40 -128
  8. package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
  9. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  10. package/build/src/components/KYCElements/IDCardCapture.js +224 -189
  11. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  12. package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
  13. package/build/src/components/KYCElements/PhoneVerificationTemplate.js +0 -2
  14. package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
  15. package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
  16. package/build/src/components/KYCElements/VerificationProgressTemplate.js +38 -33
  17. package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
  18. package/build/src/components/OverLay/IdCard.d.ts +6 -1
  19. package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
  20. package/build/src/components/OverLay/IdCard.js +36 -34
  21. package/build/src/components/OverLay/IdCard.js.map +1 -1
  22. package/build/src/config/countriesData.d.ts.map +1 -1
  23. package/build/src/config/countriesData.js.map +1 -1
  24. package/build/src/hooks/useTemplateKYCFlow.js +1 -1
  25. package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
  26. package/build/src/modules/api/CardAuthentification.d.ts +5 -0
  27. package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
  28. package/build/src/modules/api/CardAuthentification.js +67 -14
  29. package/build/src/modules/api/CardAuthentification.js.map +1 -1
  30. package/build/src/modules/api/KYCService.d.ts +10 -0
  31. package/build/src/modules/api/KYCService.d.ts.map +1 -1
  32. package/build/src/modules/api/KYCService.js +135 -49
  33. package/build/src/modules/api/KYCService.js.map +1 -1
  34. package/build/src/web/WebKYCEntry.d.ts.map +1 -1
  35. package/build/src/web/WebKYCEntry.js +34 -6
  36. package/build/src/web/WebKYCEntry.js.map +1 -1
  37. package/package.json +3 -2
  38. package/src/components/EnhancedCameraView.tsx +28 -219
  39. package/src/components/KYCElements/CountrySelectionTemplate.tsx +53 -133
  40. package/src/components/KYCElements/IDCardCapture.tsx +606 -570
  41. package/src/components/KYCElements/PhoneVerificationTemplate.tsx +0 -2
  42. package/src/components/KYCElements/VerificationProgressTemplate.tsx +54 -66
  43. package/src/components/OverLay/IdCard.tsx +48 -36
  44. package/src/config/countriesData.ts +0 -4
  45. package/src/hooks/useTemplateKYCFlow.tsx +14 -14
  46. package/src/modules/api/CardAuthentification.ts +133 -67
  47. package/src/modules/api/KYCService.ts +189 -66
  48. package/src/web/WebKYCEntry.tsx +42 -7
@@ -23,6 +23,9 @@ type ExtendedIDCardConfig = IDCardConfig & {
23
23
  instructionsByDocumentType?: Record<string, LocalizedText>;
24
24
  };
25
25
 
26
+ // Standard ISO 3166-2:CA codes for Canadian provinces and territories
27
+ const CANADIAN_PROVINCES = ['AB', 'BC', 'MB', 'NB', 'NL', 'NT', 'NS', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT'];
28
+
26
29
  export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> = ({
27
30
  component,
28
31
  value,
@@ -58,11 +61,17 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
58
61
  setSelectedCountryCode(value.code);
59
62
  setSelectedDocumentType(value.documentType);
60
63
  setSelectedRegion(value.region || null);
64
+
61
65
  if (value.region) {
62
66
  setCurrentStep('region');
63
67
  } else {
64
- const needsRegionCheck = value.code && value.documentType && idCardConfig?.regionsByCountry?.[value.code]?.[value.documentType];
65
- if (needsRegionCheck && Array.isArray(needsRegionCheck) && needsRegionCheck.length > 0) {
68
+ // Check config regions OR enforce Canadian provinces for non-passports
69
+ let regionsCheck = idCardConfig?.regionsByCountry?.[value.code]?.[value.documentType] || [];
70
+ if (regionsCheck.length === 0 && value.code === 'CA' && value.documentType !== 'passport') {
71
+ regionsCheck = CANADIAN_PROVINCES;
72
+ }
73
+
74
+ if (Array.isArray(regionsCheck) && regionsCheck.length > 0) {
66
75
  setCurrentStep('region');
67
76
  } else {
68
77
  setCurrentStep('documentType');
@@ -78,7 +87,7 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
78
87
 
79
88
  useEffect(() => {
80
89
  if (error) {
81
- actions.updateComponentData(component.id, value);
90
+ actions.updateComponentData(component.id, value);
82
91
  }
83
92
  }, []);
84
93
 
@@ -96,10 +105,19 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
96
105
  }, [selectedCountryCode, idCardConfig?.documentTypesByCountry]);
97
106
 
98
107
  const availableRegions = useMemo(() => {
99
- if (!selectedCountryCode || !selectedDocumentType || !idCardConfig?.regionsByCountry) return [];
100
- const regions = idCardConfig.regionsByCountry[selectedCountryCode];
101
- if (!regions) return [];
102
- return Array.isArray(regions[selectedDocumentType]) ? regions[selectedDocumentType] : [];
108
+ if (!selectedCountryCode || !selectedDocumentType) return [];
109
+
110
+ let regions: string[] = [];
111
+ if (idCardConfig?.regionsByCountry?.[selectedCountryCode]?.[selectedDocumentType]) {
112
+ regions = idCardConfig.regionsByCountry[selectedCountryCode][selectedDocumentType];
113
+ }
114
+
115
+
116
+ if (regions.length === 0 && selectedCountryCode === 'CA' && selectedDocumentType !== 'passport') {
117
+ regions = CANADIAN_PROVINCES;
118
+ }
119
+
120
+ return Array.isArray(regions) ? regions : [];
103
121
  }, [selectedCountryCode, selectedDocumentType, idCardConfig?.regionsByCountry]);
104
122
 
105
123
  const needsRegion = useMemo(() => {
@@ -110,20 +128,17 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
110
128
  return text[state.currentLanguage] || text.en || '';
111
129
  };
112
130
 
113
- // 1. Only highlights the country
114
131
  const handleCountrySelect = (countryCode: string) => {
115
132
  setSelectedCountryCode(countryCode);
116
133
  setSelectedDocumentType(null);
117
134
  setSelectedRegion(null);
118
135
  };
119
136
 
120
- // 2. Only highlights the document type
121
137
  const handleDocumentTypeSelect = (docType: string) => {
122
138
  setSelectedDocumentType(docType);
123
139
  setSelectedRegion(null);
124
140
  };
125
141
 
126
- // 3. Only highlights the region
127
142
  const handleRegionSelect = (region: string) => {
128
143
  setSelectedRegion(region);
129
144
  };
@@ -142,9 +157,9 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
142
157
  };
143
158
 
144
159
  onValueChange(countryObj);
145
-
160
+
146
161
  setTimeout(() => {
147
- actions.nextComponent(countryObj);
162
+ actions.nextComponent(countryObj);
148
163
  }, 100);
149
164
  };
150
165
 
@@ -323,7 +338,7 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
323
338
  case 'documentType':
324
339
  return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
325
340
  case 'region':
326
- return state.currentLanguage === "en" ? "Select Region" : "Sélectionnez la région";
341
+ return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
327
342
  default:
328
343
  return '';
329
344
  }
@@ -334,13 +349,13 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
334
349
  case 'country':
335
350
  return getLocalizedText(component.instructions as LocalizedText);
336
351
  case 'documentType':
337
- return state.currentLanguage === "en"
352
+ return state.currentLanguage === "en"
338
353
  ? "Choose the type of document you want to use"
339
354
  : "Choisissez le type de document que vous souhaitez utiliser";
340
355
  case 'region':
341
356
  return state.currentLanguage === "en"
342
- ? "Select your region"
343
- : "Sélectionnez votre région";
357
+ ? "Select the issuing province or territory"
358
+ : "Sélectionnez la province ou le territoire de délivrance";
344
359
  default:
345
360
  return '';
346
361
  }
@@ -368,7 +383,7 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
368
383
  <View style={styles.container}>
369
384
  <View style={styles.progressContainer}>
370
385
  <Text style={styles.progressText}>
371
- {state.currentLanguage === "en"
386
+ {state.currentLanguage === "en"
372
387
  ? `Step ${getProgressStep()} of ${getTotalSteps()}`
373
388
  : `Étape ${getProgressStep()} sur ${getTotalSteps()}`}
374
389
  </Text>
@@ -387,9 +402,8 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
387
402
  onPress={handleBack}
388
403
  variant={currentStep === 'country' ? "secondary" : "outline"}
389
404
  size="large"
390
- style={{ flex: 1, marginRight: 8 }}
405
+ style={{ flex: 1, marginRight: 8 }}
391
406
  />
392
-
393
407
  <Button
394
408
  title={state.currentLanguage === "en" ? "Next" : "Suivant"}
395
409
  onPress={handleNext}
@@ -409,118 +423,24 @@ export const CountrySelectionTemplate: React.FC<CountrySelectionTemplateProps> =
409
423
  };
410
424
 
411
425
  const styles = StyleSheet.create({
412
- root: {
413
- flex: 1,
414
- maxWidth: 760,
415
- width: '100%',
416
- },
417
- container: {
418
- backgroundColor: 'white',
419
- margin: 10,
420
- borderRadius: 10,
421
- paddingVertical: 16,
422
- paddingHorizontal: 16,
423
- shadowColor: '#000',
424
- shadowOffset: { width: 0, height: 2 },
425
- shadowOpacity: 0.35,
426
- shadowRadius: 4.84,
427
- elevation: 10,
428
- },
429
- progressContainer: {
430
- marginBottom: 16,
431
- alignItems: 'center',
432
- },
433
- progressText: {
434
- fontSize: 14,
435
- color: '#666',
436
- fontWeight: '500',
437
- },
438
- title: {
439
- fontSize: 24,
440
- fontWeight: 'bold',
441
- color: '#333',
442
- marginBottom: 8,
443
- textAlign: 'center',
444
- },
445
- description: {
446
- fontSize: 16,
447
- color: '#666',
448
- textAlign: 'center',
449
- marginBottom: 24,
450
- lineHeight: 22,
451
- },
452
- listContainer: {
453
- maxHeight: 400,
454
- marginBottom: 24,
455
- },
456
- option: {
457
- flexDirection: 'row',
458
- alignItems: 'center',
459
- padding: 16,
460
- backgroundColor: '#F8F9FA',
461
- borderRadius: 12,
462
- marginBottom: 12,
463
- borderWidth: 2,
464
- borderColor: '#E9ECEF',
465
- minHeight: 64,
466
- },
467
- selectedOption: {
468
- borderColor: '#2DBD60',
469
- backgroundColor: '#F0F9F0',
470
- },
471
- flag: {
472
- fontSize: 32,
473
- marginRight: 16,
474
- },
475
- optionContent: {
476
- flex: 1,
477
- },
478
- optionName: {
479
- fontSize: 18,
480
- fontWeight: '600',
481
- color: '#333',
482
- },
483
- selectedOptionName: {
484
- color: '#2DBD60',
485
- },
486
- optionCode: {
487
- fontSize: 14,
488
- color: '#666',
489
- marginTop: 4,
490
- fontWeight: '500',
491
- },
492
- checkmark: {
493
- width: 24,
494
- height: 24,
495
- borderRadius: 12,
496
- justifyContent: 'center',
497
- alignItems: 'center',
498
- },
499
- checkmarkText: {
500
- color: 'white',
501
- fontSize: 16,
502
- fontWeight: 'bold',
503
- },
504
- infoBox: {
505
- backgroundColor: '#F9FAFB',
506
- padding: 12,
507
- borderRadius: 12,
508
- marginBottom: 16,
509
- },
510
- infoText: {
511
- fontSize: 14,
512
- color: '#666',
513
- lineHeight: 20,
514
- },
515
- buttonContainer: {
516
- flexDirection: 'row',
517
- marginTop: 24,
518
- gap: 12,
519
- },
520
- errorText: {
521
- color: '#dc2626',
522
- fontSize: 14,
523
- marginTop: 8,
524
- textAlign: 'center',
525
- },
426
+ root: { flex: 1, maxWidth: 760, width: '100%' },
427
+ container: { backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.35, shadowRadius: 4.84, elevation: 10 },
428
+ progressContainer: { marginBottom: 16, alignItems: 'center' },
429
+ progressText: { fontSize: 14, color: '#666', fontWeight: '500' },
430
+ title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center' },
431
+ description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 22 },
432
+ listContainer: { maxHeight: 400, marginBottom: 24 },
433
+ option: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: '#F8F9FA', borderRadius: 12, marginBottom: 12, borderWidth: 2, borderColor: '#E9ECEF', minHeight: 64 },
434
+ selectedOption: { borderColor: '#2DBD60', backgroundColor: '#F0F9F0' },
435
+ flag: { fontSize: 32, marginRight: 16 },
436
+ optionContent: { flex: 1 },
437
+ optionName: { fontSize: 18, fontWeight: '600', color: '#333' },
438
+ selectedOptionName: { color: '#2DBD60' },
439
+ optionCode: { fontSize: 14, color: '#666', marginTop: 4, fontWeight: '500' },
440
+ checkmark: { width: 24, height: 24, borderRadius: 12, justifyContent: 'center', alignItems: 'center' },
441
+ checkmarkText: { color: 'white', fontSize: 16, fontWeight: 'bold' },
442
+ infoBox: { backgroundColor: '#F9FAFB', padding: 12, borderRadius: 12, marginBottom: 16 },
443
+ infoText: { fontSize: 14, color: '#666', lineHeight: 20 },
444
+ buttonContainer: { flexDirection: 'row', marginTop: 24, gap: 12 },
445
+ errorText: { color: '#dc2626', fontSize: 14, marginTop: 8, textAlign: 'center' },
526
446
  });