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

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 +1 @@
1
- {"version":3,"file":"KYC.types.js","sourceRoot":"","sources":["../../../src/types/KYC.types.ts"],"names":[],"mappings":"AA+UA,MAAM,CAAC,MAAM,6BAA6B,GAA2C;IACnF,aAAa,EAAE,IAAI;IACnB,QAAQ,EAAE,IAAI;IACd,eAAe,EAAE,IAAI;IACrB,qBAAqB,EAAE,KAAK;IAC5B,mBAAmB,EAAE,IAAI;IACzB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;IACjB,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;CACT,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAA2C;IACnF,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,iBAAiB;IACjC,mBAAmB,EAAE,uBAAuB;IAC5C,kBAAkB,EAAE,qBAAqB;IACzC,UAAU,EAAE,aAAa;IACzB,eAAe,EAAE,qBAAqB;CACvC,CAAA","sourcesContent":["import { VerificationResult } from \"../modules/api/types\";\n\n// Types pour les documents\nexport interface Document {\n id: string;\n type: DocumentType;\n imageUri: string;\n uploadedAt: Date;\n validated: boolean;\n extractedData?: DocumentData;\n\n}\n\nexport type DocumentType = 'passport' | 'id_card' | 'drivers_license';\n\nexport interface DocumentData {\n firstName?: string;\n lastName?: string;\n dateOfBirth?: string;\n documentNumber?: string;\n expiryDate?: string;\n nationality?: string;\n}\n\n// Types pour les selfies\nexport interface Selfie {\n id: string;\n imageUri: string;\n capturedAt: Date;\n validated: boolean;\n faceDetected: boolean;\n}\n\n// Types pour la session KYC\nexport interface KYCSession {\n id: string;\n userId: string;\n status: KYCStatus;\n currentStep: number;\n documents: Document[];\n selfie?: Selfie;\n verificationId?: string;\n createdAt: Date;\n updatedAt: Date;\n completedAt?: Date;\n}\n\nexport type KYCStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'rejected';\n\n// Types pour les étapes du processus\nexport interface KYCStep {\n id: number;\n title: string;\n description: string;\n isCompleted: boolean;\n isRequired: boolean;\n}\n\n// Types pour les erreurs\nexport interface KYCError {\n code: string;\n message: string;\n field?: string;\n details?: any;\n}\n\n// Types pour les réponses API\nexport interface KYCResponse {\n success: boolean;\n data?: any;\n error?: KYCError;\n message?: string;\n}\n\n// Types pour les événements\nexport interface KYCEvent {\n type: 'step_completed' | 'document_uploaded' | 'selfie_captured' | 'verification_started' | 'verification_completed';\n timestamp: Date;\n data?: any;\n}\n\n// Types pour les configurations\nexport interface KYCConfig {\n apiBaseUrl: string;\n apiKey: string;\n timeout: number;\n retryAttempts: number;\n enableDebug: boolean;\n}\n\n// Types pour les hooks\nexport interface UseKYCReturn {\n session: KYCSession | null;\n currentStep: number;\n isProcessing: boolean;\n error: KYCError | null;\n startSession: (userId: string) => void;\n nextStep: () => void;\n previousStep: () => void;\n uploadDocument: (document: Document) => Promise<void>;\n captureSelfie: (selfie: Selfie) => Promise<void>;\n submitVerification: () => Promise<void>;\n resetSession: () => void;\n}\n\n// ===== NOUVEAUX TYPES POUR CONFIGURATION AUTOMATIQUE =====\n\n// Types d'éléments KYC configurables\nexport type KYCElementType =\n | 'country_selection'\n | 'document_type_selection'\n | 'camera_capture'\n | 'file_upload'\n | 'selfie_capture'\n | 'verification'\n | 'completion';\n//KYCElementType shorted\n\n\n// Configuration d'un élément KYC\nexport interface KYCElement {\n id: string;\n type: KYCElementType;\n title: string;\n description: string;\n isRequired: boolean;\n isVisible: boolean;\n order: number;\n validation?: KYCValidation;\n options?: KYCElementOption[];\n cameraConfig?: KYCCameraConfig;\n uploadConfig?: KYCUploadConfig;\n}\n\n// Options pour les éléments de sélection\nexport interface KYCElementOption {\n value: string;\n label: string;\n icon?: string;\n description?: string;\n}\n\n// Configuration de validation\nexport interface KYCValidation {\n required: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n customValidator?: (value: any) => boolean | string;\n}\n\n// Configuration de la caméra\nexport interface KYCCameraConfig {\n aspectRatio?: number;\n quality?: number;\n flashMode?: 'on' | 'off' | 'auto';\n cameraType?: 'front' | 'back';\n allowRetake: boolean;\n maxRetakes?: number;\n overlay?: {\n showGuide: boolean;\n guideText?: string;\n guideImage?: string;\n };\n}\n\n// Configuration d'upload\nexport interface KYCUploadConfig {\n allowedTypes: string[];\n maxFiles: number;\n maxFileSize?: number;\n allowMultiple: boolean;\n}\n\n// Configuration complète du flux KYC\nexport interface KYCFlowConfig {\n id: string;\n name: string;\n description: string;\n version: string;\n elements: KYCElement[];\n settings: {\n allowBackNavigation: boolean;\n showProgressBar: boolean;\n showStepNumbers: boolean;\n autoAdvance: boolean;\n enableRetry: boolean;\n maxRetries: number;\n };\n styling: {\n primaryColor: string;\n secondaryColor: string;\n backgroundColor: string;\n textColor: string;\n borderRadius: number;\n fontFamily?: string;\n };\n localization: {\n language: string;\n translations: Record<string, Record<string, string>>;\n };\n}\n\n// État du flux KYC\nexport interface KYCFlowState {\n config: KYCFlowConfig;\n currentElementIndex: number;\n completedElements: string[];\n elementData: Record<string, any>;\n errors: Record<string, string>;\n isProcessing: boolean;\n}\n\n// Actions pour le flux KYC\nexport interface KYCFlowActions {\n initializeFlow: (config: KYCFlowConfig) => void;\n nextElement: () => void;\n previousElement: () => void;\n goToElement: (elementId: string) => void;\n updateElementData: (elementId: string, data: any) => void;\n validateElement: (elementId: string) => boolean;\n submitFlow: () => Promise<void>;\n resetFlow: () => void;\n}\n\n// Hook pour le flux KYC\nexport interface UseKYCFlowReturn {\n state: KYCFlowState;\n actions: KYCFlowActions;\n currentElement: KYCElement | null;\n progress: number;\n canGoNext: boolean;\n canGoPrevious: boolean;\n isComplete: boolean;\n}\n\n// ===== TYPES FOR ORIENTATION VIDEO PROCESSING =====\n\n// Orientation types for liveness detection\nexport type OrientationType = 'center' | 'left' | 'right';\n\n// Individual orientation capture result\nexport interface OrientationCapture {\n captured: boolean;\n frame: number | null;\n}\n\n// Complete orientation video processing result\nexport interface OrientationVideoResult {\n center: OrientationCapture;\n right: OrientationCapture;\n left: OrientationCapture;\n}\n\n// Orientation video processing request\nexport interface OrientationVideoRequest {\n file: string; // Base64 encoded video or file path\n}\n\n// Orientation video processing response\nexport interface OrientationVideoResponse {\n success: boolean;\n data?: OrientationVideoResult;\n error?: KYCError;\n message?: string;\n}\n\n// Configuration for orientation video capture\nexport interface OrientationVideoConfig {\n duration: number; // Duration in seconds\n orientations: OrientationType[];\n instructions: Record<OrientationType, string>;\n showPreview: boolean;\n allowRetake: boolean;\n maxRetakes: number;\n quality: number;\n aspectRatio: number;\n}\n\n// State for orientation video capture\nexport interface OrientationVideoState {\n isRecording: boolean;\n currentOrientation: OrientationType | null;\n recordedVideo: string | null;\n processingResult: OrientationVideoResult | null;\n isProcessing: boolean;\n error: string | null;\n retakeCount: number;\n}\n\n// Actions for orientation video capture\nexport interface OrientationVideoActions {\n startRecording: () => void;\n stopRecording: () => void;\n processVideo: () => Promise<OrientationVideoResult>;\n retake: () => void;\n reset: () => void;\n setCurrentOrientation: (orientation: OrientationType) => void;\n}\n\n// ===== NOUVEAUX TYPES POUR TEMPLATE JSON =====\n\n// Types pour les labels et instructions multilingues\nexport interface LocalizedText {\n en: string;\n fr: string;\n [key: string]: string; // Support pour d'autres langues\n}\n\n// Configuration UI pour les composants\nexport interface ComponentUI {\n icon?: string;\n themeColor?: string;\n buttonText: LocalizedText | Record<string, LocalizedText>;\n backgroundColor?: string;\n textColor?: string;\n borderRadius?: number;\n}\n\n// Types de documents gouvernementaux supportés\nexport type GovernmentDocumentType =\n | 'identity_card'\n | 'passport'\n | 'drivers_licence'\n | 'health_insurance_card'\n | 'permanent_residence'\n | 'national_id'\n | 'work_permit'\n | 'id'\n | 'pp'\n | 'dl'\n | 'hic'\n | 'pr'\n | 'wp'\n\nexport const GovernmentDocumentTypeShorted: Record<GovernmentDocumentType, string> = {\n identity_card: 'id',\n passport: 'pp',\n drivers_licence: 'dl',\n health_insurance_card: 'hic',\n permanent_residence: 'pr',\n national_id: 'id',\n work_permit: 'wp',\n id: 'id',\n pp: 'pp',\n dl: 'dl',\n hic: 'hic',\n pr: 'pr',\n wp: 'wp',\n}\n\nexport const GovernmentDocumentTypeBackend: Record<string, GovernmentDocumentType> = {\n national_id: 'identity_card',\n passport: 'passport',\n driversLicense: 'drivers_licence',\n healthInsuranceCard: 'health_insurance_card',\n permanentResidence: 'permanent_residence',\n workPermit: 'work_permit',\n residencePermit: 'permanent_residence',\n}\n\n// Configuration spécifique pour chaque type de composant\nexport interface IDCardConfig {\n sides: string[];\n allowed_formats: string[];\n max_size_mb: number;\n document_types: GovernmentDocumentType[]; // Types de documents disponibles\n bbox_configs?: Record<GovernmentDocumentType, {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n }>;\n}\n\n\nexport interface SelfieConfig {\n liveness_check: boolean;\n max_attempts: number;\n orientations: ('center' | 'left' | 'right')[]; // Tableau d'orientations à capturer\n}\n\nexport interface FileUploadConfig {\n allowed_formats: string[];\n max_size_mb: number;\n required: boolean;\n}\n\nexport interface LocationConfig {\n accuracy: string;\n required: boolean;\n}\n\nexport interface CountrySelectionConfig {\n allowed_countries: string[];\n default_country: string;\n required: boolean;\n}\n\n// Union type pour toutes les configurations\nexport type ComponentConfig =\n | IDCardConfig\n | SelfieConfig\n | FileUploadConfig\n | LocationConfig\n | CountrySelectionConfig\n | CountrySelectionConfig\n | WelcomeConfig\n | EmailVerificationConfig\n | PhoneVerificationConfig\n | PersonalInformationConfig\n | AdditionalDocumentsConfig;\n\n// Nouveau type de composant basé sur le template JSON\nexport interface TemplateComponent {\n id: number;\n type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome' | 'email_verification' | 'phone_verification' | 'personal_information' | 'additional_documents';\n order: number;\n templateId?: number;\n labels: LocalizedText | Record<string, LocalizedText>;\n instructions: LocalizedText | Record<string, LocalizedText>;\n ui: ComponentUI | Record<string, ComponentUI>;\n config: ComponentConfig;\n}\n\n// Template KYC complet\nexport interface KYCTemplate {\n id: number;\n name: LocalizedText;\n description: LocalizedText;\n version: string;\n components: TemplateComponent[];\n}\n\n// État pour le template KYC\nexport interface TemplateState {\n template: KYCTemplate;\n currentComponentIndex: number;\n completedComponents: number[];\n componentData: Record<number, any>;\n errors: Record<number, string>;\n isProcessing: boolean;\n currentLanguage: string;\n showCustomStepper: boolean;\n session: SessionState;\n verification: VerificationState;\n}\n\nexport interface SessionState {\n session_id: string;\n token: string;\n isInitialized: boolean;\n isProcessing: boolean;\n error: string | null;\n /** True once loadSessionData has run (for resume flow); allows UI to show loading until country/data restored */\n sessionDataRestored?: boolean;\n}\n\nexport type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';\n\n\n\nexport interface VerificationState {\n status: VerificationStatus;\n result?: VerificationResult;\n}\n\n// Actions pour le template KYC\nexport interface TemplateActions {\n initializeTemplate: (template: KYCTemplate) => void;\n nextComponent: (overrideData?: any) => void;\n previousComponent: () => void;\n goToComponent: (componentId: number) => void;\n updateComponentData: (componentId: number, data: any) => void;\n validateComponent: (componentId: number, dataOverride?: any) => boolean;\n submitTemplate: () => Promise<void>;\n resetTemplate: () => void;\n restartSession: () => void;\n setLanguage: (language: string) => void;\n showCustomStepper: (show: boolean) => void;\n setVerificationState: (state: VerificationState) => void;\n submitVerification: () => Promise<void>;\n}\n\n// Hook pour le template KYC (return type of useTemplateKYCFlow)\nexport interface UseTemplateReturn {\n state: TemplateState;\n actions: TemplateActions;\n currentComponent: TemplateComponent | null;\n progress: number;\n canGoNext: boolean;\n canGoPrevious: boolean;\n isComplete: boolean;\n getLocalizedText: (text: LocalizedText) => string;\n initializeSession: () => Promise<void>;\n env: 'PRODUCTION' | 'SANDBOX';\n /** Optional API key for backend auth (e.g. email verification endpoints). */\n apiKey?: string;\n}\n\n\nexport interface ISilentCaptureResult {\n success: boolean;\n path?: string;\n mrz?: string;\n barcode?: string | any; \n error?: string;\n isAnalyzing?: boolean;\n bbox?: IBbox;\n country?: string;\n documentType?: string;\n templatePath?: string;\n lpipsScore?: number;\n}\n\nexport interface IBbox {\n minX: number;\n minY: number;\n width: number;\n height: number;\n}\n\nexport interface ICountryMapping {\n py_file?: string;\n front?: string;\n back?: string;\n keys_found?: string | null;\n mrz_type?: string;\n}\n\nexport interface Country {\n code?: string; // ISO 3166-1 alpha-2\n name: string;\n name_en: string;\n flag: string;\n regionMapping?: ICountryMapping;\n hasRegions?: boolean;\n}\n\n// ===== TYPES FOR BACKEND TEMPLATE FORMAT =====\n\n// Backend component configuration types\nexport interface WelcomeConfig {\n subtitle?: string;\n buttonText?: string;\n requirements?: string[];\n estimatedTime?: string;\n consentOptions?: {\n showPrivacyPolicy?: boolean;\n showTermsOfService?: boolean;\n showMarketingConsent?: boolean;\n };\n welcomeMessage?: string;\n showEstimatedTime?: boolean;\n}\n\nexport interface LocationCaptureConfig {\n showMap?: boolean;\n accuracy?: string;\n required?: boolean;\n maxDistance?: number;\n captureMethod?: string;\n allowManualEntry?: boolean;\n countryRestrictions?: string[];\n}\n\nexport interface GovernmentIdConfig {\n required?: boolean;\n allowSkip?: boolean;\n cameraOverlay?: {\n bbox?: {\n xMax?: number;\n xMin?: number;\n yMax?: number;\n yMin?: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n };\n };\n documentTypes?: string[];\n requiredSides?: string;\n cameraSettings?: {\n quality?: number;\n flashMode?: string;\n maxRetakes?: number;\n allowRetake?: boolean;\n aspectRatio?: number;\n };\n validationRules?: string[];\n regionsByCountry?: Record<string, any>;\n selectedCountries?: string[];\n authenticationMethods?: Record<string, Record<string, {\n back?: string[];\n front?: string[];\n mrzTypes?: string[];\n }>>;\n documentTypesByCountry?: Record<string, string[]>;\n instructionsByDocumentType?: Record<string, LocalizedText>;\n}\n\nexport interface SelfieCaptureConfig {\n timeout?: number;\n maxAttempts?: number;\n faceMatching?: boolean;\n captureMethod?: string;\n qualityChecks?: string[];\n livenessChecks?: string[];\n matchThreshold?: string;\n livenessEnabled?: boolean;\n}\n\nexport interface ReviewSubmitConfig {\n allowEditing?: boolean;\n displayOptions?: string[];\n requireConsent?: boolean;\n postSubmitActions?: string[];\n}\n\nexport type BackendComponentConfig =\n | WelcomeConfig\n | LocationCaptureConfig\n | GovernmentIdConfig\n | SelfieCaptureConfig\n | ReviewSubmitConfig\n | Record<string, any>;\n\n// Backend component translation structure\nexport interface BackendComponentTranslations {\n en?: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n };\n fr?: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n };\n [key: string]: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n } | undefined;\n}\n\n// Backend template component\nexport interface BackendTemplateComponent {\n id: string;\n type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress' | 'email-verification' | 'phone-verification' | 'personal-information' | 'additional-documents';\n order: number;\n config: BackendComponentConfig;\n required?: boolean;\n translations: BackendComponentTranslations;\n}\n\n// Backend template structure\nexport interface BackendKYCTemplate {\n id: string;\n name: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n status?: string;\n version?: string;\n components: BackendTemplateComponent[];\n description?: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n}\n\n// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====\n\nexport interface EmailVerificationConfig {\n allowResend: boolean;\n otpSettings: {\n codeLength: number;\n expiryTime: number;\n };\n resendCooldown: number;\n emailValidation: {\n corporateOnly: boolean;\n validateFormat: boolean;\n checkDisposable: boolean;\n checkDeliverability: boolean;\n };\n verificationMethod: string;\n required?: boolean;\n}\n\nexport interface PhoneVerificationConfig {\n required: boolean;\n codeExpiry: number;\n codeLength: number;\n maxAttempts: number;\n resendDelay: number;\n countryRestrictions: string;\n verificationMethods: string[];\n allowSkipForVerified: boolean;\n}\n\nexport interface PersonalInfoField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n placeholder?: string;\n autoFillFromId?: boolean;\n minAge?: number;\n verifyAge?: boolean;\n dateFormat?: string;\n}\n\nexport interface PersonalInformationConfig {\n fields: PersonalInfoField[];\n validationSettings: {\n validateOnBlur: boolean;\n showAllErrorsAtOnce: boolean;\n preventSubmissionWithErrors: boolean;\n };\n required?: boolean;\n}\n\nexport interface DocumentCategory {\n enabled: boolean;\n category: string;\n documentTypes: string[];\n}\n\nexport interface AdditionalDocumentsConfig {\n required: boolean;\n maxSizeEach: string;\n maxDocuments: number;\n minDocuments: number;\n documentCategories: DocumentCategory[];\n customDocumentTypes: any[];\n showBasedOnUserProfile: boolean;\n}\n\n// API response for template\nexport interface TemplateAPIResponse {\n id: string;\n name: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n status?: string;\n version?: string;\n components: BackendTemplateComponent[];\n description?: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n}\n\n// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====\n\nexport interface EmailVerificationConfig {\n allowResend: boolean;\n otpSettings: {\n codeLength: number;\n expiryTime: number;\n };\n resendCooldown: number;\n emailValidation: {\n corporateOnly: boolean;\n validateFormat: boolean;\n checkDisposable: boolean;\n checkDeliverability: boolean;\n };\n verificationMethod: string;\n required?: boolean;\n}\n\nexport interface PhoneVerificationConfig {\n required: boolean;\n codeExpiry: number;\n codeLength: number;\n maxAttempts: number;\n resendDelay: number;\n countryRestrictions: string;\n verificationMethods: string[];\n allowSkipForVerified: boolean;\n}\n\nexport interface PersonalInfoField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n placeholder?: string;\n autoFillFromId?: boolean;\n minAge?: number;\n verifyAge?: boolean;\n dateFormat?: string;\n}\n\nexport interface PersonalInformationConfig {\n fields: PersonalInfoField[];\n validationSettings: {\n validateOnBlur: boolean;\n showAllErrorsAtOnce: boolean;\n preventSubmissionWithErrors: boolean;\n };\n required?: boolean;\n}\n\nexport interface DocumentCategory {\n enabled: boolean;\n category: string;\n documentTypes: string[];\n}\n\nexport interface AdditionalDocumentsConfig {\n required: boolean;\n maxSizeEach: string;\n maxDocuments: number;\n minDocuments: number;\n documentCategories: DocumentCategory[];\n customDocumentTypes: any[];\n showBasedOnUserProfile: boolean;\n}"]}
1
+ {"version":3,"file":"KYC.types.js","sourceRoot":"","sources":["../../../src/types/KYC.types.ts"],"names":[],"mappings":"AA+UA,MAAM,CAAC,MAAM,6BAA6B,GAA2C;IACnF,aAAa,EAAE,IAAI;IACnB,QAAQ,EAAE,IAAI;IACd,eAAe,EAAE,IAAI;IACrB,qBAAqB,EAAE,KAAK;IAC5B,mBAAmB,EAAE,IAAI;IACzB,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;IACjB,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;CACT,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAA2C;IACnF,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,iBAAiB;IACjC,mBAAmB,EAAE,uBAAuB;IAC5C,kBAAkB,EAAE,qBAAqB;IACzC,UAAU,EAAE,aAAa;IACzB,eAAe,EAAE,qBAAqB;CACvC,CAAA","sourcesContent":["import { VerificationResult } from \"../modules/api/types\";\n\n// Types pour les documents\nexport interface Document {\n id: string;\n type: DocumentType;\n imageUri: string;\n uploadedAt: Date;\n validated: boolean;\n extractedData?: DocumentData;\n\n}\n\nexport type DocumentType = 'passport' | 'id_card' | 'drivers_license';\n\nexport interface DocumentData {\n firstName?: string;\n lastName?: string;\n dateOfBirth?: string;\n documentNumber?: string;\n expiryDate?: string;\n nationality?: string;\n}\n\n// Types pour les selfies\nexport interface Selfie {\n id: string;\n imageUri: string;\n capturedAt: Date;\n validated: boolean;\n faceDetected: boolean;\n}\n\n// Types pour la session KYC\nexport interface KYCSession {\n id: string;\n userId: string;\n status: KYCStatus;\n currentStep: number;\n documents: Document[];\n selfie?: Selfie;\n verificationId?: string;\n createdAt: Date;\n updatedAt: Date;\n completedAt?: Date;\n}\n\nexport type KYCStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'rejected';\n\n// Types pour les étapes du processus\nexport interface KYCStep {\n id: number;\n title: string;\n description: string;\n isCompleted: boolean;\n isRequired: boolean;\n}\n\n// Types pour les erreurs\nexport interface KYCError {\n code: string;\n message: string;\n field?: string;\n details?: any;\n}\n\n// Types pour les réponses API\nexport interface KYCResponse {\n success: boolean;\n data?: any;\n error?: KYCError;\n message?: string;\n}\n\n// Types pour les événements\nexport interface KYCEvent {\n type: 'step_completed' | 'document_uploaded' | 'selfie_captured' | 'verification_started' | 'verification_completed';\n timestamp: Date;\n data?: any;\n}\n\n// Types pour les configurations\nexport interface KYCConfig {\n apiBaseUrl: string;\n apiKey: string;\n timeout: number;\n retryAttempts: number;\n enableDebug: boolean;\n}\n\n// Types pour les hooks\nexport interface UseKYCReturn {\n session: KYCSession | null;\n currentStep: number;\n isProcessing: boolean;\n error: KYCError | null;\n startSession: (userId: string) => void;\n nextStep: () => void;\n previousStep: () => void;\n uploadDocument: (document: Document) => Promise<void>;\n captureSelfie: (selfie: Selfie) => Promise<void>;\n submitVerification: () => Promise<void>;\n resetSession: () => void;\n}\n\n// ===== NOUVEAUX TYPES POUR CONFIGURATION AUTOMATIQUE =====\n\n// Types d'éléments KYC configurables\nexport type KYCElementType =\n | 'country_selection'\n | 'document_type_selection'\n | 'camera_capture'\n | 'file_upload'\n | 'selfie_capture'\n | 'verification'\n | 'completion';\n//KYCElementType shorted\n\n\n// Configuration d'un élément KYC\nexport interface KYCElement {\n id: string;\n type: KYCElementType;\n title: string;\n description: string;\n isRequired: boolean;\n isVisible: boolean;\n order: number;\n validation?: KYCValidation;\n options?: KYCElementOption[];\n cameraConfig?: KYCCameraConfig;\n uploadConfig?: KYCUploadConfig;\n}\n\n// Options pour les éléments de sélection\nexport interface KYCElementOption {\n value: string;\n label: string;\n icon?: string;\n description?: string;\n}\n\n// Configuration de validation\nexport interface KYCValidation {\n required: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n customValidator?: (value: any) => boolean | string;\n}\n\n// Configuration de la caméra\nexport interface KYCCameraConfig {\n aspectRatio?: number;\n quality?: number;\n flashMode?: 'on' | 'off' | 'auto';\n cameraType?: 'front' | 'back';\n allowRetake: boolean;\n maxRetakes?: number;\n overlay?: {\n showGuide: boolean;\n guideText?: string;\n guideImage?: string;\n };\n}\n\n// Configuration d'upload\nexport interface KYCUploadConfig {\n allowedTypes: string[];\n maxFiles: number;\n maxFileSize?: number;\n allowMultiple: boolean;\n}\n\n// Configuration complète du flux KYC\nexport interface KYCFlowConfig {\n id: string;\n name: string;\n description: string;\n version: string;\n elements: KYCElement[];\n settings: {\n allowBackNavigation: boolean;\n showProgressBar: boolean;\n showStepNumbers: boolean;\n autoAdvance: boolean;\n enableRetry: boolean;\n maxRetries: number;\n };\n styling: {\n primaryColor: string;\n secondaryColor: string;\n backgroundColor: string;\n textColor: string;\n borderRadius: number;\n fontFamily?: string;\n };\n localization: {\n language: string;\n translations: Record<string, Record<string, string>>;\n };\n}\n\n// État du flux KYC\nexport interface KYCFlowState {\n config: KYCFlowConfig;\n currentElementIndex: number;\n completedElements: string[];\n elementData: Record<string, any>;\n errors: Record<string, string>;\n isProcessing: boolean;\n}\n\n// Actions pour le flux KYC\nexport interface KYCFlowActions {\n initializeFlow: (config: KYCFlowConfig) => void;\n nextElement: () => void;\n previousElement: () => void;\n goToElement: (elementId: string) => void;\n updateElementData: (elementId: string, data: any) => void;\n validateElement: (elementId: string) => boolean;\n submitFlow: () => Promise<void>;\n resetFlow: () => void;\n}\n\n// Hook pour le flux KYC\nexport interface UseKYCFlowReturn {\n state: KYCFlowState;\n actions: KYCFlowActions;\n currentElement: KYCElement | null;\n progress: number;\n canGoNext: boolean;\n canGoPrevious: boolean;\n isComplete: boolean;\n}\n\n// ===== TYPES FOR ORIENTATION VIDEO PROCESSING =====\n\n// Orientation types for liveness detection\nexport type OrientationType = 'center' | 'left' | 'right';\n\n// Individual orientation capture result\nexport interface OrientationCapture {\n captured: boolean;\n frame: number | null;\n}\n\n// Complete orientation video processing result\nexport interface OrientationVideoResult {\n center: OrientationCapture;\n right: OrientationCapture;\n left: OrientationCapture;\n}\n\n// Orientation video processing request\nexport interface OrientationVideoRequest {\n file: string; // Base64 encoded video or file path\n}\n\n// Orientation video processing response\nexport interface OrientationVideoResponse {\n success: boolean;\n data?: OrientationVideoResult;\n error?: KYCError;\n message?: string;\n}\n\n// Configuration for orientation video capture\nexport interface OrientationVideoConfig {\n duration: number; // Duration in seconds\n orientations: OrientationType[];\n instructions: Record<OrientationType, string>;\n showPreview: boolean;\n allowRetake: boolean;\n maxRetakes: number;\n quality: number;\n aspectRatio: number;\n}\n\n// State for orientation video capture\nexport interface OrientationVideoState {\n isRecording: boolean;\n currentOrientation: OrientationType | null;\n recordedVideo: string | null;\n processingResult: OrientationVideoResult | null;\n isProcessing: boolean;\n error: string | null;\n retakeCount: number;\n}\n\n// Actions for orientation video capture\nexport interface OrientationVideoActions {\n startRecording: () => void;\n stopRecording: () => void;\n processVideo: () => Promise<OrientationVideoResult>;\n retake: () => void;\n reset: () => void;\n setCurrentOrientation: (orientation: OrientationType) => void;\n}\n\n// ===== NOUVEAUX TYPES POUR TEMPLATE JSON =====\n\n// Types pour les labels et instructions multilingues\nexport interface LocalizedText {\n en: string;\n fr: string;\n [key: string]: string; // Support pour d'autres langues\n}\n\n// Configuration UI pour les composants\nexport interface ComponentUI {\n icon?: string;\n themeColor?: string;\n buttonText: LocalizedText | Record<string, LocalizedText>;\n backgroundColor?: string;\n textColor?: string;\n borderRadius?: number;\n}\n\n// Types de documents gouvernementaux supportés\nexport type GovernmentDocumentType =\n | 'identity_card'\n | 'passport'\n | 'drivers_licence'\n | 'health_insurance_card'\n | 'permanent_residence'\n | 'national_id'\n | 'work_permit'\n | 'id'\n | 'pp'\n | 'dl'\n | 'hic'\n | 'pr'\n | 'wp'\n\nexport const GovernmentDocumentTypeShorted: Record<GovernmentDocumentType, string> = {\n identity_card: 'id',\n passport: 'pp',\n drivers_licence: 'dl',\n health_insurance_card: 'hic',\n permanent_residence: 'pr',\n national_id: 'id',\n work_permit: 'wp',\n id: 'id',\n pp: 'pp',\n dl: 'dl',\n hic: 'hic',\n pr: 'pr',\n wp: 'wp',\n}\n\nexport const GovernmentDocumentTypeBackend: Record<string, GovernmentDocumentType> = {\n national_id: 'identity_card',\n passport: 'passport',\n driversLicense: 'drivers_licence',\n healthInsuranceCard: 'health_insurance_card',\n permanentResidence: 'permanent_residence',\n workPermit: 'work_permit',\n residencePermit: 'permanent_residence',\n}\n\n// Configuration spécifique pour chaque type de composant\nexport interface IDCardConfig {\n sides: string[];\n allowed_formats: string[];\n max_size_mb: number;\n document_types: GovernmentDocumentType[]; // Types de documents disponibles\n bbox_configs?: Record<GovernmentDocumentType, {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n }>;\n}\n\n\nexport interface SelfieConfig {\n liveness_check: boolean;\n max_attempts: number;\n orientations: ('center' | 'left' | 'right')[]; // Tableau d'orientations à capturer\n}\n\nexport interface FileUploadConfig {\n allowed_formats: string[];\n max_size_mb: number;\n required: boolean;\n}\n\nexport interface LocationConfig {\n accuracy: string;\n required: boolean;\n}\n\nexport interface CountrySelectionConfig {\n allowed_countries: string[];\n default_country: string;\n required: boolean;\n}\n\n// Union type pour toutes les configurations\nexport type ComponentConfig =\n | IDCardConfig\n | SelfieConfig\n | FileUploadConfig\n | LocationConfig\n | CountrySelectionConfig\n | CountrySelectionConfig\n | WelcomeConfig\n | EmailVerificationConfig\n | PhoneVerificationConfig\n | PersonalInformationConfig\n | AdditionalDocumentsConfig;\n\n// Nouveau type de composant basé sur le template JSON\nexport interface TemplateComponent {\n id: number;\n type: 'id_card' | 'selfie' | 'file_upload' | 'location' | 'country_selection' | 'initialization' | 'review_submit' | 'verification_progress' | 'welcome' | 'email_verification' | 'phone_verification' | 'personal_information' | 'additional_documents';\n order: number;\n templateId?: number;\n labels: LocalizedText | Record<string, LocalizedText>;\n instructions: LocalizedText | Record<string, LocalizedText>;\n ui: ComponentUI | Record<string, ComponentUI>;\n config: ComponentConfig;\n}\n\n// Template KYC complet\nexport interface KYCTemplate {\n id: number;\n name: LocalizedText;\n description: LocalizedText;\n version: string;\n components: TemplateComponent[];\n}\n\n// État pour le template KYC\nexport interface TemplateState {\n template: KYCTemplate;\n currentComponentIndex: number;\n completedComponents: number[];\n componentData: Record<number, any>;\n errors: Record<number, string>;\n isProcessing: boolean;\n currentLanguage: string;\n showCustomStepper: boolean;\n session: SessionState;\n verification: VerificationState;\n}\n\nexport interface SessionState {\n session_id: string;\n token: string;\n isInitialized: boolean;\n isProcessing: boolean;\n error: string | null;\n /** True once loadSessionData has run (for resume flow); allows UI to show loading until country/data restored */\n sessionDataRestored?: boolean;\n}\n\nexport type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';\n\n\nexport interface VerificationState {\n status: VerificationStatus;\n result?: VerificationResult;\n}\n\n// Actions pour le template KYC\nexport interface TemplateActions {\n initializeTemplate: (template: KYCTemplate) => void;\n nextComponent: (overrideData?: any) => void;\n previousComponent: () => void;\n goToComponent: (componentId: number) => void;\n updateComponentData: (componentId: number, data: any) => void;\n validateComponent: (componentId: number, dataOverride?: any) => boolean;\n submitTemplate: () => Promise<void>;\n resetTemplate: () => void;\n restartSession: () => void;\n setLanguage: (language: string) => void;\n showCustomStepper: (show: boolean) => void;\n setVerificationState: (state: VerificationState) => void;\n submitVerification: () => Promise<void>;\n}\n\n// Hook pour le template KYC (return type of useTemplateKYCFlow)\nexport interface UseTemplateReturn {\n state: TemplateState;\n actions: TemplateActions;\n currentComponent: TemplateComponent | null;\n progress: number;\n canGoNext: boolean;\n canGoPrevious: boolean;\n isComplete: boolean;\n getLocalizedText: (text: LocalizedText) => string;\n initializeSession: () => Promise<void>;\n env: 'PRODUCTION' | 'SANDBOX';\n /** Optional API key for backend auth (e.g. email verification endpoints). */\n apiKey?: string;\n}\n\n\nexport interface ISilentCaptureResult {\n success: boolean;\n path?: string;\n mrz?: string;\n barcode?: string | any; \n error?: string;\n isAnalyzing?: boolean;\n bbox?: IBbox;\n country?: string;\n documentType?: string;\n templatePath?: string;\n lpipsScore?: number;\n}\n\nexport interface IBbox {\n minX: number;\n minY: number;\n width: number;\n height: number;\n}\n\nexport interface ICountryMapping {\n py_file?: string;\n front?: string;\n back?: string;\n keys_found?: string | null;\n mrz_type?: string;\n}\n\nexport interface Country {\n code?: string; // ISO 3166-1 alpha-2\n name: string;\n name_en: string;\n flag: string;\n regionMapping?: ICountryMapping;\n hasRegions?: boolean;\n}\n\n// ===== TYPES FOR BACKEND TEMPLATE FORMAT =====\n\n// Backend component configuration types\nexport interface WelcomeConfig {\n subtitle?: string;\n buttonText?: string;\n requirements?: string[];\n estimatedTime?: string;\n consentOptions?: {\n showPrivacyPolicy?: boolean;\n showTermsOfService?: boolean;\n showMarketingConsent?: boolean;\n };\n welcomeMessage?: string;\n showEstimatedTime?: boolean;\n}\n\nexport interface LocationCaptureConfig {\n showMap?: boolean;\n accuracy?: string;\n required?: boolean;\n maxDistance?: number;\n captureMethod?: string;\n allowManualEntry?: boolean;\n countryRestrictions?: string[];\n}\n\nexport interface GovernmentIdConfig {\n required?: boolean;\n allowSkip?: boolean;\n cameraOverlay?: {\n bbox?: {\n xMax?: number;\n xMin?: number;\n yMax?: number;\n yMin?: number;\n borderColor?: string;\n borderWidth?: number;\n cornerRadius?: number;\n };\n };\n documentTypes?: string[];\n requiredSides?: string;\n cameraSettings?: {\n quality?: number;\n flashMode?: string;\n maxRetakes?: number;\n allowRetake?: boolean;\n aspectRatio?: number;\n };\n validationRules?: string[];\n regionsByCountry?: Record<string, any>;\n selectedCountries?: string[];\n authenticationMethods?: Record<string, Record<string, {\n back?: string[];\n front?: string[];\n mrzTypes?: string[];\n }>>;\n documentTypesByCountry?: Record<string, string[]>;\n instructionsByDocumentType?: Record<string, LocalizedText>;\n}\n\nexport interface SelfieCaptureConfig {\n timeout?: number;\n maxAttempts?: number;\n faceMatching?: boolean;\n captureMethod?: string;\n qualityChecks?: string[];\n livenessChecks?: string[];\n matchThreshold?: string;\n livenessEnabled?: boolean;\n}\n\nexport interface ReviewSubmitConfig {\n allowEditing?: boolean;\n displayOptions?: string[];\n requireConsent?: boolean;\n postSubmitActions?: string[];\n}\n\nexport type BackendComponentConfig =\n | WelcomeConfig\n | LocationCaptureConfig\n | GovernmentIdConfig\n | SelfieCaptureConfig\n | ReviewSubmitConfig\n | Record<string, any>;\n\n// Backend component translation structure\nexport interface BackendComponentTranslations {\n en?: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n };\n fr?: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n };\n [key: string]: {\n title?: string;\n description?: string;\n instructions?: string;\n buttonText?: string;\n consentText?: string;\n successMessage?: string;\n } | undefined;\n}\n\n// Backend template component\nexport interface BackendTemplateComponent {\n id: string;\n type: 'welcome' | 'location-capture' | 'government-id' | 'selfie-capture' | 'review-submit' | 'verification-progress' | 'email-verification' | 'phone-verification' | 'personal-information' | 'additional-documents';\n order: number;\n config: BackendComponentConfig;\n required?: boolean;\n translations: BackendComponentTranslations;\n}\n\n// Backend template structure\nexport interface BackendKYCTemplate {\n id: string;\n name: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n status?: string;\n version?: string;\n components: BackendTemplateComponent[];\n description?: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n}\n\n// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====\n\nexport interface EmailVerificationConfig {\n allowResend: boolean;\n otpSettings: {\n codeLength: number;\n expiryTime: number;\n };\n resendCooldown: number;\n emailValidation: {\n corporateOnly: boolean;\n validateFormat: boolean;\n checkDisposable: boolean;\n checkDeliverability: boolean;\n };\n verificationMethod: string;\n required?: boolean;\n}\n\nexport interface PhoneVerificationConfig {\n required: boolean;\n codeExpiry: number;\n codeLength: number;\n maxAttempts: number;\n resendDelay: number;\n countryRestrictions: string;\n verificationMethods: string[];\n allowSkipForVerified: boolean;\n}\n\nexport interface PersonalInfoField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n placeholder?: string;\n autoFillFromId?: boolean;\n minAge?: number;\n verifyAge?: boolean;\n dateFormat?: string;\n}\n\nexport interface PersonalInformationConfig {\n fields: PersonalInfoField[];\n validationSettings: {\n validateOnBlur: boolean;\n showAllErrorsAtOnce: boolean;\n preventSubmissionWithErrors: boolean;\n };\n required?: boolean;\n}\n\nexport interface DocumentCategory {\n enabled: boolean;\n category: string;\n documentTypes: string[];\n}\n\nexport interface AdditionalDocumentsConfig {\n required: boolean;\n maxSizeEach: string;\n maxDocuments: number;\n minDocuments: number;\n documentCategories: DocumentCategory[];\n customDocumentTypes: any[];\n showBasedOnUserProfile: boolean;\n}\n\n// API response for template\nexport interface TemplateAPIResponse {\n id: string;\n name: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n status?: string;\n version?: string;\n components: BackendTemplateComponent[];\n description?: {\n en: string;\n fr: string;\n [key: string]: string;\n };\n}\n\n// ===== NEW CONFIG TYPES FOR INPUT VERIFICATION =====\n\nexport interface EmailVerificationConfig {\n allowResend: boolean;\n otpSettings: {\n codeLength: number;\n expiryTime: number;\n };\n resendCooldown: number;\n emailValidation: {\n corporateOnly: boolean;\n validateFormat: boolean;\n checkDisposable: boolean;\n checkDeliverability: boolean;\n };\n verificationMethod: string;\n required?: boolean;\n}\n\nexport interface PhoneVerificationConfig {\n required: boolean;\n codeExpiry: number;\n codeLength: number;\n maxAttempts: number;\n resendDelay: number;\n countryRestrictions: string;\n verificationMethods: string[];\n allowSkipForVerified: boolean;\n}\n\nexport interface PersonalInfoField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n placeholder?: string;\n autoFillFromId?: boolean;\n minAge?: number;\n verifyAge?: boolean;\n dateFormat?: string;\n}\n\nexport interface PersonalInformationConfig {\n fields: PersonalInfoField[];\n validationSettings: {\n validateOnBlur: boolean;\n showAllErrorsAtOnce: boolean;\n preventSubmissionWithErrors: boolean;\n };\n required?: boolean;\n}\n\nexport interface DocumentCategory {\n enabled: boolean;\n category: string;\n documentTypes: string[];\n}\n\nexport interface AdditionalDocumentsConfig {\n required: boolean;\n maxSizeEach: string;\n maxDocuments: number;\n minDocuments: number;\n documentCategories: DocumentCategory[];\n customDocumentTypes: any[];\n showBasedOnUserProfile: boolean;\n}"]}
@@ -1,7 +1,3 @@
1
- /**
2
- * Logger utility that only logs in development mode
3
- * In production, all logs are suppressed
4
- */
5
1
  export declare const logger: {
6
2
  log: (...args: any[]) => void;
7
3
  error: (...args: any[]) => void;
@@ -9,4 +5,16 @@ export declare const logger: {
9
5
  info: (...args: any[]) => void;
10
6
  debug: (...args: any[]) => void;
11
7
  };
8
+ export declare const sdkLogger: {
9
+ setSessionId: (id: string) => void;
10
+ clearSessionId: () => void;
11
+ flush: () => Promise<void>;
12
+ destroy: () => void;
13
+ setApiKey: (key: string) => void;
14
+ log: (...args: any[]) => void;
15
+ info: (...args: any[]) => void;
16
+ warn: (...args: any[]) => void;
17
+ error: (...args: any[]) => void;
18
+ debug: (...args: any[]) => void;
19
+ };
12
20
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAiBH,eAAO,MAAM,MAAM;mBACF,GAAG,EAAE;qBAKH,GAAG,EAAE;oBAKN,GAAG,EAAE;oBAKL,GAAG,EAAE;qBAKJ,GAAG,EAAE;CAKvB,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,MAAM;mBACF,GAAG,EAAE;qBACH,GAAG,EAAE;oBACN,GAAG,EAAE;oBACL,GAAG,EAAE;qBACJ,GAAG,EAAE;CACvB,CAAC;AAqKF,eAAO,MAAM,SAAS;uBACD,MAAM;;;;qBAIR,MAAM;mBAER,GAAG,EAAE;oBACJ,GAAG,EAAE;oBAEL,GAAG,EAAE;qBACJ,GAAG,EAAE;qBACL,GAAG,EAAE;CACvB,CAAC"}
@@ -1,45 +1,173 @@
1
- /**
2
- * Logger utility that only logs in development mode
3
- * In production, all logs are suppressed
4
- */
1
+ import { Platform, AppState } from 'react-native';
2
+ import axios from 'axios';
3
+ import KYCConfig from '../config/KYCConfig';
5
4
  const isProduction = () => {
6
- // Check for React Native __DEV__ flag
7
5
  if (typeof __DEV__ !== 'undefined') {
8
6
  return !__DEV__;
9
7
  }
10
- // Check for Node.js environment
11
8
  if (typeof process !== 'undefined' && process.env) {
12
9
  return process.env.NODE_ENV === 'production';
13
10
  }
14
- // Default to development mode if we can't determine
15
11
  return false;
16
12
  };
17
- const shouldLog = !isProduction();
13
+ const IS_PROD = isProduction();
18
14
  export const logger = {
19
- log: (...args) => {
20
- if (shouldLog) {
21
- console.log(...args);
15
+ log: (...args) => { if (!IS_PROD)
16
+ console.log(...args); },
17
+ error: (...args) => { if (!IS_PROD)
18
+ console.error(...args); },
19
+ warn: (...args) => { if (!IS_PROD)
20
+ console.warn(...args); },
21
+ info: (...args) => { if (!IS_PROD)
22
+ console.info(...args); },
23
+ debug: (...args) => { if (!IS_PROD)
24
+ console.debug(...args); },
25
+ };
26
+ class SDKTelemetryLogger {
27
+ queue = [];
28
+ isFlushing = false;
29
+ maxQueueSize = 3;
30
+ flushIntervalMs = 3000;
31
+ sessionId;
32
+ apiKey;
33
+ timerId;
34
+ appStateSubscription;
35
+ constructor() {
36
+ this.timerId = setInterval(() => this.flush(), this.flushIntervalMs);
37
+ if (Platform.OS !== 'web') {
38
+ this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);
22
39
  }
23
- },
24
- error: (...args) => {
25
- if (shouldLog) {
26
- console.error(...args);
40
+ }
41
+ handleAppStateChange = (nextAppState) => {
42
+ if (nextAppState === 'background' || nextAppState === 'inactive') {
43
+ this.flush();
27
44
  }
28
- },
29
- warn: (...args) => {
30
- if (shouldLog) {
31
- console.warn(...args);
45
+ };
46
+ setSessionId(id) {
47
+ this.sessionId = id;
48
+ this.queue = this.queue.map(log => {
49
+ if (!log.session_id) {
50
+ return { ...log, session_id: id };
51
+ }
52
+ return log;
53
+ });
54
+ this.flush();
55
+ }
56
+ clearSessionId() {
57
+ this.sessionId = undefined;
58
+ }
59
+ setApiKey(key) {
60
+ this.apiKey = key;
61
+ }
62
+ parseArgs(args) {
63
+ let message = '';
64
+ let metadata = {};
65
+ args.forEach(arg => {
66
+ if (typeof arg === 'string') {
67
+ message += (message ? ' ' : '') + arg;
68
+ }
69
+ else if (arg instanceof Error) {
70
+ message += (message ? ' ' : '') + arg.message;
71
+ metadata.error_stack = arg.stack;
72
+ }
73
+ else if (typeof arg === 'object' && arg !== null) {
74
+ Object.assign(metadata, arg);
75
+ }
76
+ else {
77
+ message += (message ? ' ' : '') + String(arg);
78
+ }
79
+ });
80
+ return { message: message || 'No message provided', metadata };
81
+ }
82
+ processLog(level, ...args) {
83
+ const { message, metadata } = this.parseArgs(args);
84
+ if (!IS_PROD) {
85
+ const devPrefix = `[SDK_TELEMETRY_${level.toUpperCase()}]`;
86
+ if (level === 'error')
87
+ console.error(devPrefix, message, metadata);
88
+ else if (level === 'warning')
89
+ console.warn(devPrefix, message, metadata); // Match updated level
90
+ else
91
+ console.log(devPrefix, message, metadata);
32
92
  }
33
- },
34
- info: (...args) => {
35
- if (shouldLog) {
36
- console.info(...args);
93
+ const entry = {
94
+ level,
95
+ message: message.substring(0, 500),
96
+ timestamp: new Date().toISOString(),
97
+ session_id: this.sessionId,
98
+ metadata: {
99
+ ...metadata,
100
+ os: Platform.OS,
101
+ osVersion: Platform.Version,
102
+ }
103
+ };
104
+ this.queue.push(entry);
105
+ const isError = level === 'error';
106
+ const hitLimit = this.queue.length >= this.maxQueueSize;
107
+ if (isError || (this.sessionId && hitLimit)) {
108
+ this.flush();
37
109
  }
38
- },
39
- debug: (...args) => {
40
- if (shouldLog) {
41
- console.debug(...args);
110
+ }
111
+ async flush() {
112
+ if (this.queue.length === 0 || this.isFlushing)
113
+ return;
114
+ const batch = this.queue.map(log => ({
115
+ ...log,
116
+ session_id: log.session_id || 'pre-session-startup'
117
+ }));
118
+ this.isFlushing = true;
119
+ this.queue = [];
120
+ try {
121
+ const url = `${KYCConfig.getBackendUrl()}/core/sdk/logs/`;
122
+ const headers = { 'Content-Type': 'application/json' };
123
+ if (this.apiKey) {
124
+ headers['Authorization'] = `ApiKey ${this.apiKey}`;
125
+ }
126
+ await axios.post(url, { logs: batch }, {
127
+ headers,
128
+ timeout: 5000
129
+ });
130
+ }
131
+ catch (error) {
132
+ // 🚨 FIX 2: Stop Infinite Loops
133
+ // If the backend actively rejects our payload (400-499 error code), do NOT requeue it.
134
+ const isClientError = error.response && error.response.status >= 400 && error.response.status < 500;
135
+ if (!isClientError) {
136
+ // Only retry if it's a network failure or a 5xx Server Error
137
+ if (this.queue.length < 50) {
138
+ this.queue = [...batch, ...this.queue].slice(0, 50);
139
+ }
140
+ }
141
+ else {
142
+ if (!IS_PROD) {
143
+ console.error("[SDK_TELEMETRY] Backend rejected log payload. Dropping batch to prevent infinite loop.", error.response.data);
144
+ }
145
+ }
146
+ }
147
+ finally {
148
+ this.isFlushing = false;
42
149
  }
43
- },
150
+ }
151
+ destroy() {
152
+ if (this.timerId)
153
+ clearInterval(this.timerId);
154
+ if (this.appStateSubscription)
155
+ this.appStateSubscription.remove();
156
+ this.flush();
157
+ }
158
+ }
159
+ const telemetryInstance = new SDKTelemetryLogger();
160
+ export const sdkLogger = {
161
+ setSessionId: (id) => telemetryInstance.setSessionId(id),
162
+ clearSessionId: () => telemetryInstance.clearSessionId(),
163
+ flush: () => telemetryInstance.flush(),
164
+ destroy: () => telemetryInstance.destroy(),
165
+ setApiKey: (key) => telemetryInstance.setApiKey(key),
166
+ log: (...args) => telemetryInstance.processLog('info', ...args),
167
+ info: (...args) => telemetryInstance.processLog('info', ...args),
168
+ // 🚨 FIX 1 (Continued): Map warn() function to send 'warning' to backend
169
+ warn: (...args) => telemetryInstance.processLog('warning', ...args),
170
+ error: (...args) => telemetryInstance.processLog('error', ...args),
171
+ debug: (...args) => telemetryInstance.processLog('debug', ...args),
44
172
  };
45
173
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,YAAY,GAAG,GAAY,EAAE;IACjC,sCAAsC;IACtC,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,CAAC,OAAO,CAAC;IAClB,CAAC;IACD,gCAAgC;IAChC,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAClD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;IAC/C,CAAC;IACD,oDAAoD;IACpD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,YAAY,EAAE,CAAC;AAElC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,GAAG,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACtB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACxB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACvB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACxB,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;CACF,CAAC","sourcesContent":["/**\n * Logger utility that only logs in development mode\n * In production, all logs are suppressed\n */\n\nconst isProduction = (): boolean => {\n // Check for React Native __DEV__ flag\n if (typeof __DEV__ !== 'undefined') {\n return !__DEV__;\n }\n // Check for Node.js environment\n if (typeof process !== 'undefined' && process.env) {\n return process.env.NODE_ENV === 'production';\n }\n // Default to development mode if we can't determine\n return false;\n};\n\nconst shouldLog = !isProduction();\n\nexport const logger = {\n log: (...args: any[]) => {\n if (shouldLog) {\n console.log(...args);\n }\n },\n error: (...args: any[]) => {\n if (shouldLog) {\n console.error(...args);\n }\n },\n warn: (...args: any[]) => {\n if (shouldLog) {\n console.warn(...args);\n }\n },\n info: (...args: any[]) => {\n if (shouldLog) {\n console.info(...args);\n }\n },\n debug: (...args: any[]) => {\n if (shouldLog) {\n console.debug(...args);\n }\n },\n};\n\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform, AppState, AppStateStatus } from 'react-native';\nimport axios from 'axios';\nimport KYCConfig from '../config/KYCConfig';\n\nconst isProduction = (): boolean => {\n if (typeof __DEV__ !== 'undefined') {\n return !__DEV__;\n }\n if (typeof process !== 'undefined' && process.env) {\n return process.env.NODE_ENV === 'production';\n }\n return false;\n};\n\nconst IS_PROD = isProduction();\n\nexport const logger = {\n log: (...args: any[]) => { if (!IS_PROD) console.log(...args); },\n error: (...args: any[]) => { if (!IS_PROD) console.error(...args); },\n warn: (...args: any[]) => { if (!IS_PROD) console.warn(...args); },\n info: (...args: any[]) => { if (!IS_PROD) console.info(...args); },\n debug: (...args: any[]) => { if (!IS_PROD) console.debug(...args); },\n};\n\n// ==========================================\n// 2. SDK TELEMETRY LOGGER (REMOTE)\n// ==========================================\n// 🚨 FIX 1: Changed 'warn' to 'warning' to match backend enums\ntype LogLevel = 'info' | 'warning' | 'error' | 'debug'; \n\ninterface LogEntry {\n level: LogLevel;\n message: string;\n timestamp: string;\n session_id?: string;\n metadata?: any;\n}\n\nclass SDKTelemetryLogger {\n private queue: LogEntry[] = [];\n private isFlushing = false;\n private maxQueueSize = 3;\n private flushIntervalMs = 3000;\n private sessionId: string | undefined;\n private apiKey: string | undefined;\n private timerId?: ReturnType<typeof setInterval>;\n private appStateSubscription: any;\n\n constructor() {\n this.timerId = setInterval(() => this.flush(), this.flushIntervalMs);\n\n if (Platform.OS !== 'web') {\n this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);\n }\n }\n\n private handleAppStateChange = (nextAppState: AppStateStatus) => {\n if (nextAppState === 'background' || nextAppState === 'inactive') {\n this.flush();\n }\n };\n\n public setSessionId(id: string) {\n this.sessionId = id;\n \n this.queue = this.queue.map(log => {\n if (!log.session_id) {\n return { ...log, session_id: id };\n }\n return log;\n });\n\n this.flush();\n }\n\n public clearSessionId() {\n this.sessionId = undefined;\n }\n\n public setApiKey(key: string) {\n this.apiKey = key;\n }\n\n private parseArgs(args: any[]): { message: string, metadata: any } {\n let message = '';\n let metadata: any = {};\n\n args.forEach(arg => {\n if (typeof arg === 'string') {\n message += (message ? ' ' : '') + arg;\n } else if (arg instanceof Error) {\n message += (message ? ' ' : '') + arg.message;\n metadata.error_stack = arg.stack;\n } else if (typeof arg === 'object' && arg !== null) {\n Object.assign(metadata, arg);\n } else {\n message += (message ? ' ' : '') + String(arg);\n }\n });\n\n return { message: message || 'No message provided', metadata };\n }\n\n public processLog(level: LogLevel, ...args: any[]) {\n const { message, metadata } = this.parseArgs(args);\n\n if (!IS_PROD) {\n const devPrefix = `[SDK_TELEMETRY_${level.toUpperCase()}]`;\n if (level === 'error') console.error(devPrefix, message, metadata);\n else if (level === 'warning') console.warn(devPrefix, message, metadata); // Match updated level\n else console.log(devPrefix, message, metadata);\n }\n\n const entry: LogEntry = {\n level,\n message: message.substring(0, 500),\n timestamp: new Date().toISOString(),\n session_id: this.sessionId,\n metadata: {\n ...metadata,\n os: Platform.OS,\n osVersion: Platform.Version,\n }\n };\n\n this.queue.push(entry);\n\n const isError = level === 'error';\n const hitLimit = this.queue.length >= this.maxQueueSize;\n\n if (isError || (this.sessionId && hitLimit)) {\n this.flush();\n }\n }\n\n public async flush() {\n if (this.queue.length === 0 || this.isFlushing) return;\n\n const batch = this.queue.map(log => ({\n ...log,\n session_id: log.session_id || 'pre-session-startup' \n }));\n\n this.isFlushing = true;\n this.queue = [];\n\n try {\n const url = `${KYCConfig.getBackendUrl()}/core/sdk/logs/`; \n \n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.apiKey) {\n headers['Authorization'] = `ApiKey ${this.apiKey}`;\n }\n\n await axios.post(url, { logs: batch }, {\n headers,\n timeout: 5000 \n });\n } catch (error: any) {\n // 🚨 FIX 2: Stop Infinite Loops\n // If the backend actively rejects our payload (400-499 error code), do NOT requeue it.\n const isClientError = error.response && error.response.status >= 400 && error.response.status < 500;\n\n if (!isClientError) {\n // Only retry if it's a network failure or a 5xx Server Error\n if (this.queue.length < 50) {\n this.queue = [...batch, ...this.queue].slice(0, 50);\n }\n } else {\n if (!IS_PROD) {\n console.error(\"[SDK_TELEMETRY] Backend rejected log payload. Dropping batch to prevent infinite loop.\", error.response.data);\n }\n }\n } finally {\n this.isFlushing = false;\n }\n }\n\n public destroy() {\n if (this.timerId) clearInterval(this.timerId);\n if (this.appStateSubscription) this.appStateSubscription.remove();\n this.flush();\n }\n}\n\nconst telemetryInstance = new SDKTelemetryLogger();\n\nexport const sdkLogger = {\n setSessionId: (id: string) => telemetryInstance.setSessionId(id),\n clearSessionId: () => telemetryInstance.clearSessionId(),\n flush: () => telemetryInstance.flush(),\n destroy: () => telemetryInstance.destroy(),\n setApiKey: (key: string) => telemetryInstance.setApiKey(key),\n \n log: (...args: any[]) => telemetryInstance.processLog('info', ...args),\n info: (...args: any[]) => telemetryInstance.processLog('info', ...args),\n // 🚨 FIX 1 (Continued): Map warn() function to send 'warning' to backend\n warn: (...args: any[]) => telemetryInstance.processLog('warning', ...args), \n error: (...args: any[]) => telemetryInstance.processLog('error', ...args),\n debug: (...args: any[]) => telemetryInstance.processLog('debug', ...args),\n};"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanctum-key/react-native-sdk",
3
- "version": "1.0.49",
3
+ "version": "1.0.51",
4
4
  "description": "Sanctum Key React Native SDK",
5
5
  "main": "build/src/index.js",
6
6
  "types": "build/src/index.d.ts",
@@ -1,6 +1,8 @@
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
3
  import { KYCElement, KYCElementOption } from '../../types/KYC.types';
4
+ import { sdkLogger } from '../../utils/logger';
5
+ import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
4
6
 
5
7
  interface CountrySelectionProps {
6
8
  element: KYCElement;
@@ -16,9 +18,17 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
16
18
  error,
17
19
  }) => {
18
20
  const countries = element.options || [];
19
- console.log(`Countries options: ${countries}`)
20
-
21
21
  const [searchQuery, setSearchQuery] = useState('');
22
+
23
+ const { state } = useTemplateKYCFlowContext();
24
+
25
+ useEffect(() => {
26
+ if (state.session?.session_id) {
27
+ sdkLogger.info("User started country selection step", {
28
+ availableCountriesCount: countries.length
29
+ });
30
+ }
31
+ }, [state.session?.session_id, countries.length]);
22
32
 
23
33
  // Filter countries based on user input
24
34
  const filteredCountries = useMemo(() => {
@@ -38,7 +48,10 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
38
48
  styles.option,
39
49
  isSelected && styles.selectedOption
40
50
  ]}
41
- onPress={() => onValueChange(country.value)}
51
+ onPress={() => {
52
+ sdkLogger.info("User selected country", { countryCode: country.value }); // 🚨 LOG
53
+ onValueChange(country.value);
54
+ }}
42
55
  activeOpacity={0.7}
43
56
  // Accessibility Enhancements
44
57
  accessible={true}
@@ -48,7 +61,6 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
48
61
  accessibilityHint={`Tap to select ${country.label} as your country`}
49
62
  >
50
63
  <Text style={styles.optionIcon}>{country.icon}</Text>
51
-
52
64
  <View style={styles.optionContent}>
53
65
  <Text style={[
54
66
  styles.optionLabel,
@@ -60,7 +72,6 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
60
72
  <Text style={styles.optionDescription}>{country.description}</Text>
61
73
  )}
62
74
  </View>
63
-
64
75
  {isSelected && (
65
76
  <View style={styles.checkmark}>
66
77
  <Text style={styles.checkmarkText}>✓</Text>
@@ -75,7 +86,7 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
75
86
  <View style={styles.headerContainer}>
76
87
  <Text style={styles.title} accessibilityRole="header">{element.title}</Text>
77
88
  <Text style={styles.description}>{element.description}</Text>
78
-
89
+
79
90
  {/* Search Bar */}
80
91
  <TextInput
81
92
  style={styles.searchInput}
@@ -84,6 +95,7 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
84
95
  value={searchQuery}
85
96
  onChangeText={setSearchQuery}
86
97
  clearButtonMode="while-editing" // Adds a clear 'x' on iOS
98
+
87
99
  // Accessibility for Search
88
100
  accessibilityRole="search"
89
101
  accessibilityLabel="Search countries"
@@ -110,7 +122,6 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
110
122
  </Text>
111
123
  }
112
124
  />
113
-
114
125
  {error && (
115
126
  <Text style={styles.errorText} accessibilityRole="alert">{error}</Text>
116
127
  )}
@@ -119,105 +130,21 @@ export const CountrySelection: React.FC<CountrySelectionProps> = ({
119
130
  };
120
131
 
121
132
  const styles = StyleSheet.create({
122
- container: {
123
- flex: 1,
124
- backgroundColor: '#fff',
125
- },
126
- headerContainer: {
127
- paddingHorizontal: 16,
128
- paddingTop: 16,
129
- paddingBottom: 8,
130
- },
131
- title: {
132
- fontSize: 24,
133
- fontWeight: 'bold',
134
- color: '#333',
135
- marginBottom: 8,
136
- textAlign: 'center',
137
- },
138
- description: {
139
- fontSize: 16,
140
- color: '#666',
141
- textAlign: 'center',
142
- marginBottom: 16,
143
- lineHeight: 22,
144
- },
145
- searchInput: {
146
- backgroundColor: '#f5f5f5',
147
- borderRadius: 10,
148
- padding: 12,
149
- fontSize: 16,
150
- color: '#333',
151
- borderWidth: 1,
152
- borderColor: '#e5e5e5',
153
- marginBottom: 8,
154
- },
155
- listContent: {
156
- paddingHorizontal: 16,
157
- paddingBottom: 24,
158
- },
159
- emptyText: {
160
- textAlign: 'center',
161
- color: '#999',
162
- marginTop: 20,
163
- fontSize: 16,
164
- },
165
- option: {
166
- flexDirection: 'row',
167
- alignItems: 'center',
168
- padding: 16,
169
- backgroundColor: 'white',
170
- borderRadius: 12,
171
- marginBottom: 12,
172
- borderWidth: 2,
173
- borderColor: '#e5e5e5',
174
- shadowColor: '#000',
175
- shadowOffset: { width: 0, height: 2 },
176
- shadowOpacity: 0.05,
177
- shadowRadius: 3.84,
178
- elevation: 3,
179
- },
180
- selectedOption: {
181
- borderColor: '#4CAF50',
182
- backgroundColor: '#f0f9f0',
183
- },
184
- optionIcon: {
185
- fontSize: 32,
186
- marginRight: 16,
187
- },
188
- optionContent: {
189
- flex: 1,
190
- },
191
- optionLabel: {
192
- fontSize: 18,
193
- fontWeight: '600',
194
- color: '#333',
195
- },
196
- selectedOptionLabel: {
197
- color: '#4CAF50',
198
- },
199
- optionDescription: {
200
- fontSize: 14,
201
- color: '#666',
202
- marginTop: 4,
203
- },
204
- checkmark: {
205
- width: 24,
206
- height: 24,
207
- borderRadius: 12,
208
- backgroundColor: '#4CAF50',
209
- justifyContent: 'center',
210
- alignItems: 'center',
211
- },
212
- checkmarkText: {
213
- color: 'white',
214
- fontSize: 16,
215
- fontWeight: 'bold',
216
- },
217
- errorText: {
218
- color: '#dc2626',
219
- fontSize: 14,
220
- margin: 16,
221
- textAlign: 'center',
222
- },
133
+ container: { flex: 1, backgroundColor: '#fff', },
134
+ headerContainer: { paddingHorizontal: 16, paddingTop: 16, paddingBottom: 8, },
135
+ title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center', },
136
+ description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 16, lineHeight: 22, },
137
+ searchInput: { backgroundColor: '#f5f5f5', borderRadius: 10, padding: 12, fontSize: 16, color: '#333', borderWidth: 1, borderColor: '#e5e5e5', marginBottom: 8, },
138
+ listContent: { paddingHorizontal: 16, paddingBottom: 24, },
139
+ emptyText: { textAlign: 'center', color: '#999', marginTop: 20, fontSize: 16, },
140
+ 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, },
141
+ selectedOption: { borderColor: '#4CAF50', backgroundColor: '#f0f9f0', },
142
+ optionIcon: { fontSize: 32, marginRight: 16, },
143
+ optionContent: { flex: 1, },
144
+ optionLabel: { fontSize: 18, fontWeight: '600', color: '#333', },
145
+ selectedOptionLabel: { color: '#4CAF50', },
146
+ optionDescription: { fontSize: 14, color: '#666', marginTop: 4, },
147
+ checkmark: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#4CAF50', justifyContent: 'center', alignItems: 'center', },
148
+ checkmarkText: { color: 'white', fontSize: 16, fontWeight: 'bold', },
149
+ errorText: { color: '#dc2626', fontSize: 14, margin: 16, textAlign: 'center', },
223
150
  });