@trustchex/react-native-sdk 1.250.0 → 1.253.0

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 (36) hide show
  1. package/lib/module/Screens/Static/VerificationSessionCheckScreen.js +44 -73
  2. package/lib/module/Shared/Components/FaceCamera.js +5 -3
  3. package/lib/module/Shared/Components/IdentityDocumentCamera.js +5 -3
  4. package/lib/module/Shared/Components/LanguageSelector.js +14 -10
  5. package/lib/module/Shared/Components/NavigationManager.js +2 -2
  6. package/lib/module/Shared/Components/QrCodeScannerCamera.js +4 -1
  7. package/lib/module/Shared/Components/StyledButton.js +108 -9
  8. package/lib/module/Shared/Components/StyledTextInput.js +87 -0
  9. package/lib/module/Shared/Contexts/ThemeContext.js +40 -0
  10. package/lib/module/Translation/index.js +12 -5
  11. package/lib/module/Trustchex.js +5 -12
  12. package/lib/typescript/src/Screens/Static/VerificationSessionCheckScreen.d.ts.map +1 -1
  13. package/lib/typescript/src/Shared/Components/FaceCamera.d.ts.map +1 -1
  14. package/lib/typescript/src/Shared/Components/IdentityDocumentCamera.d.ts.map +1 -1
  15. package/lib/typescript/src/Shared/Components/LanguageSelector.d.ts.map +1 -1
  16. package/lib/typescript/src/Shared/Components/QrCodeScannerCamera.d.ts.map +1 -1
  17. package/lib/typescript/src/Shared/Components/StyledButton.d.ts +12 -2
  18. package/lib/typescript/src/Shared/Components/StyledButton.d.ts.map +1 -1
  19. package/lib/typescript/src/Shared/Components/StyledTextInput.d.ts +15 -0
  20. package/lib/typescript/src/Shared/Components/StyledTextInput.d.ts.map +1 -0
  21. package/lib/typescript/src/Shared/Contexts/ThemeContext.d.ts +26 -0
  22. package/lib/typescript/src/Shared/Contexts/ThemeContext.d.ts.map +1 -0
  23. package/lib/typescript/src/Translation/index.d.ts.map +1 -1
  24. package/lib/typescript/src/Trustchex.d.ts.map +1 -1
  25. package/package.json +1 -6
  26. package/src/Screens/Static/VerificationSessionCheckScreen.tsx +53 -85
  27. package/src/Shared/Components/FaceCamera.tsx +4 -2
  28. package/src/Shared/Components/IdentityDocumentCamera.tsx +4 -2
  29. package/src/Shared/Components/LanguageSelector.tsx +12 -11
  30. package/src/Shared/Components/NavigationManager.tsx +3 -3
  31. package/src/Shared/Components/QrCodeScannerCamera.tsx +3 -1
  32. package/src/Shared/Components/StyledButton.tsx +141 -10
  33. package/src/Shared/Components/StyledTextInput.tsx +128 -0
  34. package/src/Shared/Contexts/ThemeContext.tsx +67 -0
  35. package/src/Translation/index.ts +12 -10
  36. package/src/Trustchex.tsx +11 -18
@@ -1,21 +1,127 @@
1
1
  import React from 'react';
2
- import { StyleSheet } from 'react-native';
3
- import { Button } from 'react-native-paper';
4
- import type { ButtonProps } from 'react-native-paper';
2
+ import {
3
+ StyleSheet,
4
+ TouchableOpacity,
5
+ Text,
6
+ ActivityIndicator,
7
+ type ViewStyle,
8
+ type TextStyle,
9
+ } from 'react-native';
10
+ import { useTheme } from '../Contexts/ThemeContext';
5
11
 
6
- type StyledButtonProps = ButtonProps;
12
+ // Calculate if a color is light or dark to determine text color
13
+ const isLightColor = (color: string): boolean => {
14
+ // Remove # if present
15
+ const hex = color.replace('#', '');
16
+
17
+ // Convert to RGB
18
+ const r = parseInt(hex.substring(0, 2), 16);
19
+ const g = parseInt(hex.substring(2, 4), 16);
20
+ const b = parseInt(hex.substring(4, 6), 16);
21
+
22
+ // Calculate relative luminance using WCAG formula
23
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
24
+
25
+ // Return true if light (luminance > 0.5)
26
+ return luminance > 0.5;
27
+ };
28
+
29
+ interface StyledButtonProps {
30
+ mode?: 'text' | 'outlined' | 'contained';
31
+ onPress?: () => void;
32
+ disabled?: boolean;
33
+ loading?: boolean;
34
+ children: React.ReactNode;
35
+ style?: ViewStyle;
36
+ labelStyle?: TextStyle;
37
+ buttonColor?: string;
38
+ textColor?: string;
39
+ }
7
40
 
8
41
  const StyledButton: React.FC<StyledButtonProps> = ({
42
+ mode = 'contained',
43
+ onPress,
44
+ disabled = false,
45
+ loading = false,
46
+ children,
9
47
  style,
10
48
  labelStyle,
11
- ...props
49
+ buttonColor,
50
+ textColor,
12
51
  }) => {
52
+ const theme = useTheme();
53
+ const primaryColor = buttonColor || theme.colors.primary;
54
+
55
+ // Determine text color based on background color for contained mode
56
+ const getContainedTextColor = () => {
57
+ if (textColor) return textColor;
58
+ return isLightColor(primaryColor) ? '#000000' : '#FFFFFF';
59
+ };
60
+
61
+ const containedTextColor = getContainedTextColor();
62
+
63
+ const getButtonStyle = () => {
64
+ const baseStyle = [styles.button, style];
65
+ if (mode === 'contained') {
66
+ return [
67
+ ...baseStyle,
68
+ styles.containedButton,
69
+ { backgroundColor: primaryColor },
70
+ disabled && styles.disabledButton,
71
+ ];
72
+ }
73
+ if (mode === 'outlined') {
74
+ return [
75
+ ...baseStyle,
76
+ styles.outlinedButton,
77
+ { borderColor: primaryColor },
78
+ disabled && styles.disabledButton,
79
+ ];
80
+ }
81
+ return [...baseStyle, styles.textButton];
82
+ };
83
+
84
+ const getTextStyle = () => {
85
+ const baseStyle = [styles.label, labelStyle];
86
+ if (mode === 'contained') {
87
+ return [
88
+ ...baseStyle,
89
+ styles.containedLabel,
90
+ { color: containedTextColor },
91
+ disabled && styles.disabledLabel,
92
+ ];
93
+ }
94
+ if (mode === 'outlined') {
95
+ return [
96
+ ...baseStyle,
97
+ styles.outlinedLabel,
98
+ { color: primaryColor },
99
+ disabled && styles.disabledLabel,
100
+ ];
101
+ }
102
+ return [
103
+ ...baseStyle,
104
+ styles.textLabel,
105
+ { color: primaryColor },
106
+ disabled && styles.disabledLabel,
107
+ ];
108
+ };
109
+
110
+ const loadingColor = mode === 'contained' ? containedTextColor : primaryColor;
111
+
13
112
  return (
14
- <Button
15
- {...props}
16
- style={[styles.button, style]}
17
- labelStyle={[styles.label, labelStyle]}
18
- />
113
+ <TouchableOpacity
114
+ style={getButtonStyle()}
115
+ onPress={onPress}
116
+ disabled={disabled || loading}
117
+ activeOpacity={0.7}
118
+ >
119
+ {loading ? (
120
+ <ActivityIndicator size="small" color={loadingColor} />
121
+ ) : (
122
+ <Text style={getTextStyle()}>{children}</Text>
123
+ )}
124
+ </TouchableOpacity>
19
125
  );
20
126
  };
21
127
 
@@ -24,11 +130,36 @@ const styles = StyleSheet.create({
24
130
  borderRadius: 8,
25
131
  height: 56,
26
132
  justifyContent: 'center',
133
+ alignItems: 'center',
134
+ paddingHorizontal: 16,
135
+ },
136
+ containedButton: {
27
137
  elevation: 2,
138
+ shadowColor: '#000',
139
+ shadowOffset: { width: 0, height: 2 },
140
+ shadowOpacity: 0.25,
141
+ shadowRadius: 3.84,
142
+ },
143
+ outlinedButton: {
144
+ backgroundColor: 'transparent',
145
+ borderWidth: 2,
146
+ },
147
+ textButton: {
148
+ backgroundColor: 'transparent',
149
+ },
150
+ disabledButton: {
151
+ opacity: 0.5,
28
152
  },
29
153
  label: {
30
154
  fontWeight: 'bold',
31
155
  fontSize: 16,
156
+ textAlign: 'center',
157
+ },
158
+ containedLabel: {},
159
+ outlinedLabel: {},
160
+ textLabel: {},
161
+ disabledLabel: {
162
+ opacity: 0.6,
32
163
  },
33
164
  });
34
165
 
@@ -0,0 +1,128 @@
1
+ import React from 'react';
2
+ import {
3
+ StyleSheet,
4
+ TextInput,
5
+ View,
6
+ Text,
7
+ type TextInputProps,
8
+ type ViewStyle,
9
+ type TextStyle,
10
+ } from 'react-native';
11
+
12
+ interface StyledTextInputProps extends TextInputProps {
13
+ containerStyle?: ViewStyle;
14
+ inputStyle?: TextStyle;
15
+ placeholderStyle?: TextStyle;
16
+ borderColor?: string;
17
+ focusedBorderColor?: string;
18
+ backgroundColor?: string;
19
+ textColor?: string;
20
+ placeholderColor?: string;
21
+ }
22
+
23
+ const StyledTextInput = React.forwardRef<TextInput, StyledTextInputProps>(
24
+ (
25
+ {
26
+ containerStyle,
27
+ inputStyle,
28
+ placeholderStyle,
29
+ borderColor = '#DDDDDD',
30
+ focusedBorderColor,
31
+ backgroundColor = '#FFFFFF',
32
+ textColor = '#000000',
33
+ placeholderColor = '#999999',
34
+ style,
35
+ placeholderTextColor,
36
+ onFocus,
37
+ onBlur,
38
+ value,
39
+ ...props
40
+ },
41
+ ref
42
+ ) => {
43
+ const [isFocused, setIsFocused] = React.useState(false);
44
+ const hasValue = value !== undefined && value !== '';
45
+
46
+ const handleFocus = (e: any) => {
47
+ setIsFocused(true);
48
+ onFocus?.(e);
49
+ };
50
+
51
+ const handleBlur = (e: any) => {
52
+ setIsFocused(false);
53
+ onBlur?.(e);
54
+ };
55
+
56
+ const currentBorderColor = isFocused
57
+ ? focusedBorderColor || borderColor
58
+ : borderColor;
59
+
60
+ return (
61
+ <View style={[styles.container, containerStyle]}>
62
+ <TextInput
63
+ ref={ref}
64
+ {...props}
65
+ value={value}
66
+ placeholder=""
67
+ style={[
68
+ styles.input,
69
+ {
70
+ backgroundColor,
71
+ borderColor: currentBorderColor,
72
+ color: textColor,
73
+ },
74
+ inputStyle,
75
+ style,
76
+ ]}
77
+ onFocus={handleFocus}
78
+ onBlur={handleBlur}
79
+ />
80
+ {!hasValue && props.placeholder && (
81
+ <View style={styles.placeholderContainer} pointerEvents="none">
82
+ <Text
83
+ style={[
84
+ styles.placeholderText,
85
+ { color: placeholderColor || placeholderTextColor || '#999' },
86
+ placeholderStyle,
87
+ ]}
88
+ >
89
+ {props.placeholder}
90
+ </Text>
91
+ </View>
92
+ )}
93
+ </View>
94
+ );
95
+ }
96
+ );
97
+
98
+ StyledTextInput.displayName = 'StyledTextInput';
99
+
100
+ const styles = StyleSheet.create({
101
+ container: {
102
+ width: '100%',
103
+ position: 'relative',
104
+ },
105
+ input: {
106
+ borderWidth: 2,
107
+ borderRadius: 8,
108
+ height: 56,
109
+ paddingHorizontal: 16,
110
+ fontSize: 16,
111
+ fontWeight: '400',
112
+ },
113
+ placeholderContainer: {
114
+ position: 'absolute',
115
+ top: 0,
116
+ left: 0,
117
+ right: 0,
118
+ bottom: 0,
119
+ justifyContent: 'center',
120
+ paddingHorizontal: 16,
121
+ },
122
+ placeholderText: {
123
+ fontSize: 16,
124
+ fontWeight: '400',
125
+ },
126
+ });
127
+
128
+ export default StyledTextInput;
@@ -0,0 +1,67 @@
1
+ import React, { createContext, useContext, useMemo } from 'react';
2
+
3
+ export interface ThemeColors {
4
+ primary: string;
5
+ secondary: string;
6
+ tertiary: string;
7
+ background: string;
8
+ surface: string;
9
+ text: string;
10
+ textSecondary: string;
11
+ border: string;
12
+ error: string;
13
+ success: string;
14
+ }
15
+
16
+ interface ThemeContextType {
17
+ colors: ThemeColors;
18
+ }
19
+
20
+ const defaultColors: ThemeColors = {
21
+ primary: '#000000',
22
+ secondary: '#CCCCCC',
23
+ tertiary: '#FF0000',
24
+ background: '#FFFFFF',
25
+ surface: '#F5F5F5',
26
+ text: '#000000',
27
+ textSecondary: '#666666',
28
+ border: '#DDDDDD',
29
+ error: '#E53935',
30
+ success: '#43A047',
31
+ };
32
+
33
+ const ThemeContext = createContext<ThemeContextType>({
34
+ colors: defaultColors,
35
+ });
36
+
37
+ export const useTheme = () => useContext(ThemeContext);
38
+
39
+ interface ThemeProviderProps {
40
+ children: React.ReactNode;
41
+ primaryColor?: string;
42
+ secondaryColor?: string;
43
+ tertiaryColor?: string;
44
+ }
45
+
46
+ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
47
+ children,
48
+ primaryColor,
49
+ secondaryColor,
50
+ tertiaryColor,
51
+ }) => {
52
+ const colors = useMemo(
53
+ () => ({
54
+ ...defaultColors,
55
+ primary: primaryColor || defaultColors.primary,
56
+ secondary: secondaryColor || defaultColors.secondary,
57
+ tertiary: tertiaryColor || defaultColors.tertiary,
58
+ }),
59
+ [primaryColor, secondaryColor, tertiaryColor]
60
+ );
61
+
62
+ const value = useMemo(() => ({ colors }), [colors]);
63
+
64
+ return (
65
+ <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
66
+ );
67
+ };
@@ -1,20 +1,22 @@
1
1
  import i18n from 'i18next';
2
2
  import { initReactI18next } from 'react-i18next';
3
3
  import * as resources from './Resources';
4
- import { Platform, NativeModules } from 'react-native';
5
4
 
6
5
  const getCurrentLanguage = () => {
7
- let deviceLanguage =
8
- Platform.OS === 'ios'
9
- ? NativeModules?.SettingsManager?.settings?.AppleLocale
10
- : NativeModules?.I18nManager?.localeIdentifier;
6
+ try {
7
+ if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
8
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale;
9
+ if (locale) {
10
+ // Extract language code from locale (e.g., "en-US" -> "en", "tr-TR" -> "tr")
11
+ return locale.split(/[-_]/)[0].toLowerCase();
12
+ }
13
+ }
11
14
 
12
- if (!deviceLanguage) {
13
- deviceLanguage =
14
- NativeModules?.SettingsManager?.settings?.AppleLanguages[0];
15
+ return 'en';
16
+ } catch (error) {
17
+ console.error('Error detecting language:', error);
18
+ return 'en';
15
19
  }
16
-
17
- return deviceLanguage;
18
20
  };
19
21
 
20
22
  i18n.use(initReactI18next).init({
package/src/Trustchex.tsx CHANGED
@@ -2,8 +2,8 @@ import React, { useEffect, useState, useMemo } from 'react';
2
2
  import { NavigationContainer } from '@react-navigation/native';
3
3
  import { createNativeStackNavigator } from '@react-navigation/native-stack';
4
4
  import { View, ActivityIndicator, StyleSheet } from 'react-native';
5
- import { MD3LightTheme, PaperProvider } from 'react-native-paper';
6
5
  import 'react-native-get-random-values';
6
+ import { ThemeProvider } from './Shared/Contexts/ThemeContext';
7
7
 
8
8
  import IdentityDocumentEIDScanningScreen from './Screens/Dynamic/IdentityDocumentEIDScanningScreen';
9
9
  import IdentityDocumentScanningScreen from './Screens/Dynamic/IdentityDocumentScanningScreen';
@@ -51,7 +51,9 @@ const Trustchex: React.FC<TrustchexProps> = ({
51
51
  }) => {
52
52
  const [baseUrl, setBaseUrl] = useState<string | null>(null);
53
53
  const [sessionId, setSessionId] = useState<string | null>(null);
54
- const [locale, setLocale] = useState(propLocale || i18n.language);
54
+ const [locale, setLocale] = useState(
55
+ propLocale || (i18n.language as 'en' | 'tr')
56
+ );
55
57
  const [isInitialized, setIsInitialized] = useState(false);
56
58
 
57
59
  const branding = useMemo(
@@ -62,19 +64,6 @@ const Trustchex: React.FC<TrustchexProps> = ({
62
64
  [propBranding]
63
65
  );
64
66
 
65
- const theme = useMemo(
66
- () => ({
67
- ...MD3LightTheme,
68
- colors: {
69
- ...MD3LightTheme.colors,
70
- primary: branding.primaryColor,
71
- secondary: branding.secondaryColor,
72
- tertiary: branding.tertiaryColor,
73
- },
74
- }),
75
- [branding]
76
- );
77
-
78
67
  const contextValue = useMemo(
79
68
  () => ({
80
69
  isDemoSession: false,
@@ -88,7 +77,7 @@ const Trustchex: React.FC<TrustchexProps> = ({
88
77
  contractIds: [],
89
78
  deviceInfo: '',
90
79
  },
91
- locale: propLocale || i18n.language,
80
+ locale: propLocale || (i18n.language as 'en' | 'tr'),
92
81
  },
93
82
  onCompleted,
94
83
  onError,
@@ -131,7 +120,11 @@ const Trustchex: React.FC<TrustchexProps> = ({
131
120
  }
132
121
 
133
122
  return (
134
- <PaperProvider theme={theme}>
123
+ <ThemeProvider
124
+ primaryColor={branding.primaryColor}
125
+ secondaryColor={branding.secondaryColor}
126
+ tertiaryColor={branding.tertiaryColor}
127
+ >
135
128
  <AppContext.Provider value={contextValue}>
136
129
  <NavigationContainer>
137
130
  <Stack.Navigator
@@ -170,7 +163,7 @@ const Trustchex: React.FC<TrustchexProps> = ({
170
163
  </Stack.Navigator>
171
164
  </NavigationContainer>
172
165
  </AppContext.Provider>
173
- </PaperProvider>
166
+ </ThemeProvider>
174
167
  );
175
168
  };
176
169