@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
@@ -8,8 +8,9 @@ import httpClient, { NotFoundError } from "../../Shared/Libs/http-client.js";
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import LanguageSelector from "../../Shared/Components/LanguageSelector.js";
10
10
  import NavigationManager from "../../Shared/Components/NavigationManager.js";
11
- import { TextInput, useTheme } from 'react-native-paper';
12
11
  import StyledButton from "../../Shared/Components/StyledButton.js";
12
+ import StyledTextInput from "../../Shared/Components/StyledTextInput.js";
13
+ import { useTheme } from "../../Shared/Contexts/ThemeContext.js";
13
14
  import LottieView from 'lottie-react-native';
14
15
  import { getSimulatedDemoData, isDemoSession } from "../../Shared/Libs/demo.utils.js";
15
16
  import { useNavigation } from '@react-navigation/native';
@@ -28,9 +29,10 @@ const VerificationSessionCheckScreen = () => {
28
29
  } = useTranslation();
29
30
  const navigationManagerRef = React.useRef(null);
30
31
  const navigation = useNavigation();
31
- const theme = useTheme();
32
32
  const initialized = useRef(false);
33
33
  const insets = useSafeAreaInsets();
34
+ const theme = useTheme();
35
+ const primaryColor = theme.colors.primary;
34
36
  const apiUrl = useMemo(() => `${appContext.baseUrl}/api/app/mobile`, [appContext.baseUrl]);
35
37
  const validateSessionCode = useCallback(value => {
36
38
  return SESSION_CODE_VALIDATION_PATTERN.test(value.toUpperCase());
@@ -109,9 +111,6 @@ const VerificationSessionCheckScreen = () => {
109
111
  appContext.workflowSteps = session?.workflowSteps;
110
112
  if (session?.branding) {
111
113
  appContext.branding = appContext.branding || session.branding;
112
- theme.colors.primary = appContext.branding.primaryColor;
113
- theme.colors.secondary = appContext.branding.secondaryColor;
114
- theme.colors.tertiary = appContext.branding.tertiaryColor;
115
114
  }
116
115
  if (session?.sendOTP) {
117
116
  return sendOTPCode(session.id);
@@ -125,7 +124,7 @@ const VerificationSessionCheckScreen = () => {
125
124
  }, 1000);
126
125
  });
127
126
  }
128
- }, [appContext, appContext.identificationInfo.sessionId, getSession, sendOTPCode, theme.colors, theme.colors.primary, theme.colors.secondary, theme.colors.tertiary]);
127
+ }, [appContext, appContext.identificationInfo.sessionId, getSession, sendOTPCode]);
129
128
  return /*#__PURE__*/_jsx(SafeAreaView, {
130
129
  style: styles.safeAreaContainer,
131
130
  children: /*#__PURE__*/_jsx(KeyboardAvoidingView, {
@@ -160,57 +159,50 @@ const VerificationSessionCheckScreen = () => {
160
159
  children: [/*#__PURE__*/_jsx(Text, {
161
160
  style: styles.mainText,
162
161
  children: t('verificationSessionCheckScreen.mainText')
163
- }), /*#__PURE__*/_jsxs(View, {
164
- style: styles.inputContainer,
165
- children: [/*#__PURE__*/_jsx(TextInput, {
166
- mode: "outlined",
167
- autoCapitalize: "characters",
168
- placeholder: "",
169
- outlineColor: theme.colors.primary,
170
- activeOutlineColor: theme.colors.primary,
171
- style: styles.sessionCodeTextInput,
172
- contentStyle: styles.sessionCodeInputWithText,
173
- onChangeText: async text => {
174
- const alphanumericText = text.toUpperCase().replace(SESSION_CODE_CHARSET_PATTERN, '');
175
- if (alphanumericText.length <= 8) {
176
- setSessionCode(alphanumericText);
177
- if (validateSessionCode(alphanumericText) && alphanumericText.length === 8) {
178
- try {
179
- setIsCheckingSession(true);
180
- const session = await getSessionByCode(alphanumericText);
181
- if (session?.id) {
182
- appContext.identificationInfo.sessionId = session.id;
183
- } else {
184
- setSessionCode('');
185
- }
186
- } catch {
162
+ }), /*#__PURE__*/_jsx(StyledTextInput, {
163
+ autoCapitalize: "characters",
164
+ placeholder: t('verificationSessionCheckScreen.enterSessionCode'),
165
+ borderColor: primaryColor,
166
+ focusedBorderColor: primaryColor,
167
+ inputStyle: styles.sessionCodeTextInput,
168
+ placeholderStyle: styles.sessionCodeTextInputPlaceholder,
169
+ value: sessionCode.toUpperCase(),
170
+ onChangeText: async text => {
171
+ const alphanumericText = text.toUpperCase().replace(SESSION_CODE_CHARSET_PATTERN, '');
172
+ if (alphanumericText.length <= 8) {
173
+ setSessionCode(alphanumericText);
174
+ if (validateSessionCode(alphanumericText) && alphanumericText.length === 8) {
175
+ try {
176
+ setIsCheckingSession(true);
177
+ const session = await getSessionByCode(alphanumericText);
178
+ if (session?.id) {
179
+ appContext.identificationInfo.sessionId = session.id;
180
+ } else {
187
181
  setSessionCode('');
188
- } finally {
189
- setTimeout(() => {
190
- setIsCheckingSession(false);
191
- }, 1000);
192
182
  }
183
+ } catch {
184
+ setSessionCode('');
185
+ } finally {
186
+ setTimeout(() => {
187
+ setIsCheckingSession(false);
188
+ }, 1000);
193
189
  }
194
190
  }
195
- },
196
- value: sessionCode.toUpperCase(),
197
- maxLength: 8
198
- }), !sessionCode && /*#__PURE__*/_jsx(Text, {
199
- style: styles.placeholderText,
200
- children: t('verificationSessionCheckScreen.enterSessionCode')
201
- })]
191
+ }
192
+ },
193
+ maxLength: 8
202
194
  }), /*#__PURE__*/_jsxs(View, {
203
195
  style: styles.horizontalLineContainer,
204
196
  children: [/*#__PURE__*/_jsx(View, {
205
197
  style: [styles.horizontalLine, {
206
- backgroundColor: theme.colors.primary
198
+ backgroundColor: primaryColor
207
199
  }]
208
200
  }), /*#__PURE__*/_jsx(Text, {
209
201
  style: styles.mainText,
210
202
  children: t('verificationSessionCheckScreen.or')
211
203
  }), /*#__PURE__*/_jsx(View, {
212
204
  style: [styles.horizontalLine, {
213
- backgroundColor: theme.colors.primary
205
+ backgroundColor: primaryColor
214
206
  }]
215
207
  })]
216
208
  }), /*#__PURE__*/_jsx(StyledButton, {
@@ -224,14 +216,12 @@ const VerificationSessionCheckScreen = () => {
224
216
  children: [/*#__PURE__*/_jsx(Text, {
225
217
  style: styles.mainText,
226
218
  children: t('verificationSessionCheckScreen.codeText')
227
- }), /*#__PURE__*/_jsx(TextInput, {
228
- mode: "outlined",
219
+ }), /*#__PURE__*/_jsx(StyledTextInput, {
229
220
  autoFocus: true,
230
221
  placeholder: "",
231
- outlineColor: theme.colors.primary,
232
- activeOutlineColor: theme.colors.primary,
233
- style: styles.otpCodeTextInput,
234
- contentStyle: styles.otpCodeInputWithText,
222
+ borderColor: primaryColor,
223
+ focusedBorderColor: primaryColor,
224
+ inputStyle: styles.otpCodeTextInput,
235
225
  keyboardType: "number-pad",
236
226
  textContentType: "oneTimeCode",
237
227
  autoComplete: "sms-otp",
@@ -313,7 +303,7 @@ const styles = StyleSheet.create({
313
303
  },
314
304
  horizontalLine: {
315
305
  flex: 1,
316
- height: 2
306
+ height: 1
317
307
  },
318
308
  loadingAnimation: {
319
309
  width: '100%',
@@ -382,40 +372,21 @@ const styles = StyleSheet.create({
382
372
  alignItems: 'center',
383
373
  position: 'absolute'
384
374
  },
385
- inputContainer: {
386
- position: 'relative',
387
- width: '100%'
388
- },
389
375
  sessionCodeTextInput: {
390
- backgroundColor: 'white'
391
- },
392
- sessionCodeInputWithText: {
393
376
  textTransform: 'uppercase',
394
377
  fontWeight: '800',
395
378
  fontSize: 28,
396
379
  textAlign: 'center',
397
380
  letterSpacing: 8
398
381
  },
399
- placeholderText: {
400
- position: 'absolute',
401
- top: 0,
402
- left: 0,
403
- right: 0,
404
- height: '100%',
405
- lineHeight: 56,
382
+ sessionCodeTextInputPlaceholder: {
406
383
  fontSize: 16,
407
- color: '#666',
384
+ fontWeight: '400',
385
+ letterSpacing: 0,
408
386
  textAlign: 'center',
409
- pointerEvents: 'none'
410
- },
411
- sessionCodeInputPlaceholder: {
412
- fontSize: 16,
413
- textAlign: 'center'
387
+ textTransform: 'none'
414
388
  },
415
389
  otpCodeTextInput: {
416
- backgroundColor: 'white'
417
- },
418
- otpCodeInputWithText: {
419
390
  fontWeight: '800',
420
391
  fontSize: 28,
421
392
  textAlign: 'center',
@@ -3,7 +3,7 @@
3
3
  import { useIsFocused } from '@react-navigation/native';
4
4
  import { useKeepAwake } from "../Libs/native-keep-awake.utils.js";
5
5
  import React, { useEffect, useState } from 'react';
6
- import { StyleSheet, Text, View, Platform, Linking, Dimensions } from 'react-native';
6
+ import { StyleSheet, Text, View, Platform, Linking, Dimensions, ActivityIndicator } from 'react-native';
7
7
  import { useCameraDevice, useCameraPermission, Camera, useFrameProcessor, useCameraFormat, runAtTargetFps, useMicrophonePermission } from 'react-native-vision-camera';
8
8
  import { runAsync } from "../Libs/worklet.utils.js";
9
9
  import { useFaceDetector } from "../VisionCameraPlugins/FaceDetector/index.js";
@@ -11,8 +11,8 @@ import { Worklets, useSharedValue } from 'react-native-worklets-core';
11
11
  import { crop } from "../VisionCameraPlugins/Cropper/index.js";
12
12
  import { isFrameBright } from "../Libs/camera.utils.js";
13
13
  import { useTranslation } from 'react-i18next';
14
- import { ActivityIndicator } from 'react-native-paper';
15
14
  import StyledButton from "./StyledButton.js";
15
+ import { useTheme } from "../Contexts/ThemeContext.js";
16
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
17
  const VIDEO_WIDTH = 1280;
18
18
  const VIDEO_HEIGHT = 720;
@@ -23,6 +23,7 @@ const FaceCamera = ({
23
23
  onCameraInitialized
24
24
  }) => {
25
25
  useKeepAwake();
26
+ const theme = useTheme();
26
27
  const cameraPermission = useCameraPermission();
27
28
  const microphonePermission = useMicrophonePermission();
28
29
  const [permissionsRequested, setPermissionsRequested] = useState(false);
@@ -132,7 +133,8 @@ const FaceCamera = ({
132
133
  return /*#__PURE__*/_jsx(View, {
133
134
  style: styles.permissionContainer,
134
135
  children: /*#__PURE__*/_jsx(ActivityIndicator, {
135
- size: "large"
136
+ size: "large",
137
+ color: theme.colors.primary
136
138
  })
137
139
  });
138
140
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  /* eslint-disable react-native/no-inline-styles */
4
4
  import React, { useEffect, useState } from 'react';
5
- import { View, StyleSheet, Text as TextView, Platform, Vibration, TouchableOpacity, Text, Linking, Image } from 'react-native';
5
+ import { View, StyleSheet, Text as TextView, Platform, Vibration, TouchableOpacity, Text, Linking, Image, ActivityIndicator } from 'react-native';
6
6
  import { Camera, runAtTargetFps, useCameraDevice, useCameraFormat, useCameraPermission, useFrameProcessor } from 'react-native-vision-camera';
7
7
  import { runAsync } from "../Libs/worklet.utils.js";
8
8
  import { useRunOnJS, useSharedValue } from 'react-native-worklets-core';
@@ -17,11 +17,11 @@ import { AdaptiveThresholdTypes, ColorConversionCodes, DataTypes, ObjectType, Op
17
17
  import { getAverageBrightness } from "../Libs/camera.utils.js";
18
18
  import { useTranslation } from 'react-i18next';
19
19
  import LottieView from 'lottie-react-native';
20
- import { ActivityIndicator } from 'react-native-paper';
21
20
  import StyledButton from "./StyledButton.js";
22
21
  import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
23
22
  import { speakWithDebounce } from "../Libs/tts.utils.js";
24
23
  import AppContext from "../Contexts/AppContext.js";
24
+ import { useTheme } from "../Contexts/ThemeContext.js";
25
25
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
26
26
  // const windowWidth = Dimensions.get('window').width;
27
27
  // const windowHeight = Dimensions.get('window').height;
@@ -38,6 +38,7 @@ const IdentityDocumentCamera = ({
38
38
  showDebugImages = false
39
39
  }) => {
40
40
  useKeepAwake();
41
+ const theme = useTheme();
41
42
  const appContext = React.useContext(AppContext);
42
43
  const cameraRef = React.useRef(null);
43
44
  const cameraPermission = useCameraPermission();
@@ -622,7 +623,8 @@ const IdentityDocumentCamera = ({
622
623
  return /*#__PURE__*/_jsx(View, {
623
624
  style: styles.permissionContainer,
624
625
  children: /*#__PURE__*/_jsx(ActivityIndicator, {
625
- size: "large"
626
+ size: "large",
627
+ color: theme.colors.primary
626
628
  })
627
629
  });
628
630
  }
@@ -3,26 +3,32 @@
3
3
  import React from 'react';
4
4
  import { Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import i18n from "../../Translation/index.js";
6
- import AppContext from "../Contexts/AppContext.js";
6
+ import { useTheme } from "../Contexts/ThemeContext.js";
7
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  const LanguageSelector = () => {
9
- const appContext = React.useContext(AppContext);
9
+ const theme = useTheme();
10
+ const isEnglish = i18n.language.startsWith('en');
11
+ const isTurkish = i18n.language.startsWith('tr');
10
12
  return /*#__PURE__*/_jsxs(View, {
11
13
  style: styles.container,
12
14
  children: [/*#__PURE__*/_jsx(Pressable, {
13
15
  onPress: () => i18n.changeLanguage('en'),
14
16
  children: /*#__PURE__*/_jsx(Text, {
15
- style: [styles.buttonText, i18n.language.startsWith('en') ? styles.buttonTextSelected : null, {
16
- color: appContext.branding.primaryColor
17
+ style: [styles.buttonText, isEnglish && styles.buttonTextSelected, isEnglish && {
18
+ color: theme.colors.primary
17
19
  }],
18
20
  children: "EN"
19
21
  })
20
22
  }), /*#__PURE__*/_jsx(View, {
21
- style: styles.verticalSeperator
23
+ style: [styles.verticalSeperator, {
24
+ borderColor: theme.colors.border
25
+ }]
22
26
  }), /*#__PURE__*/_jsx(Pressable, {
23
27
  onPress: () => i18n.changeLanguage('tr'),
24
28
  children: /*#__PURE__*/_jsx(Text, {
25
- style: [styles.buttonText, i18n.language.startsWith('tr') ? styles.buttonTextSelected : null],
29
+ style: [styles.buttonText, isTurkish && styles.buttonTextSelected, isTurkish && {
30
+ color: theme.colors.primary
31
+ }],
26
32
  children: "TR"
27
33
  })
28
34
  })]
@@ -38,16 +44,14 @@ const styles = StyleSheet.create({
38
44
  },
39
45
  buttonText: {
40
46
  fontSize: 18,
41
- color: 'black'
47
+ color: '#999999'
42
48
  },
43
49
  buttonTextSelected: {
44
- color: '#000000',
45
50
  fontWeight: 'bold'
46
51
  },
47
52
  verticalSeperator: {
48
53
  borderLeftWidth: 1,
49
- height: 24,
50
- borderColor: 'black'
54
+ height: 24
51
55
  }
52
56
  });
53
57
  export default LanguageSelector;
@@ -6,7 +6,7 @@ import { CommonActions, useNavigation, usePreventRemove } from '@react-navigatio
6
6
  import { View, StyleSheet, Alert } from 'react-native';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import i18n from "../../Translation/index.js";
9
- import { Button } from 'react-native-paper';
9
+ import StyledButton from "./StyledButton.js";
10
10
 
11
11
  // Simple global navigation lock
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -150,7 +150,7 @@ const NavigationManager = /*#__PURE__*/forwardRef(({
150
150
  }));
151
151
  return appContext.currentWorkflowStep && (!appContext.currentWorkflowStep?.required || canSkipStep) && /*#__PURE__*/_jsx(View, {
152
152
  style: styles.container,
153
- children: /*#__PURE__*/_jsx(Button, {
153
+ children: /*#__PURE__*/_jsx(StyledButton, {
154
154
  mode: "text",
155
155
  onPress: goToNextRouteWithAlert,
156
156
  children: t('navigationManager.skipStepLabel')
@@ -10,11 +10,13 @@ import { useTranslation } from 'react-i18next';
10
10
  import LottieView from 'lottie-react-native';
11
11
  import { scanCodes } from "../VisionCameraPlugins/BarcodeScanner/index.js";
12
12
  import StyledButton from "./StyledButton.js";
13
+ import { useTheme } from "../Contexts/ThemeContext.js";
13
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
15
  const QrCodeScannerCamera = ({
15
16
  onQrCodeScanned
16
17
  }) => {
17
18
  useKeepAwake();
19
+ const theme = useTheme();
18
20
  const cameraPermission = useCameraPermission();
19
21
  const [permissionsRequested, setPermissionsRequested] = React.useState(false);
20
22
  const [isActive, setIsActive] = React.useState(false);
@@ -123,7 +125,8 @@ const QrCodeScannerCamera = ({
123
125
  return /*#__PURE__*/_jsx(View, {
124
126
  style: styles.permissionContainer,
125
127
  children: /*#__PURE__*/_jsx(ActivityIndicator, {
126
- size: "large"
128
+ size: "large",
129
+ color: theme.colors.primary
127
130
  })
128
131
  });
129
132
  }
@@ -1,18 +1,89 @@
1
1
  "use strict";
2
2
 
3
3
  import React from 'react';
4
- import { StyleSheet } from 'react-native';
5
- import { Button } from 'react-native-paper';
4
+ import { StyleSheet, TouchableOpacity, Text, ActivityIndicator } from 'react-native';
5
+ import { useTheme } from "../Contexts/ThemeContext.js";
6
+
7
+ // Calculate if a color is light or dark to determine text color
6
8
  import { jsx as _jsx } from "react/jsx-runtime";
9
+ const isLightColor = color => {
10
+ // Remove # if present
11
+ const hex = color.replace('#', '');
12
+
13
+ // Convert to RGB
14
+ const r = parseInt(hex.substring(0, 2), 16);
15
+ const g = parseInt(hex.substring(2, 4), 16);
16
+ const b = parseInt(hex.substring(4, 6), 16);
17
+
18
+ // Calculate relative luminance using WCAG formula
19
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
20
+
21
+ // Return true if light (luminance > 0.5)
22
+ return luminance > 0.5;
23
+ };
7
24
  const StyledButton = ({
25
+ mode = 'contained',
26
+ onPress,
27
+ disabled = false,
28
+ loading = false,
29
+ children,
8
30
  style,
9
31
  labelStyle,
10
- ...props
32
+ buttonColor,
33
+ textColor
11
34
  }) => {
12
- return /*#__PURE__*/_jsx(Button, {
13
- ...props,
14
- style: [styles.button, style],
15
- labelStyle: [styles.label, labelStyle]
35
+ const theme = useTheme();
36
+ const primaryColor = buttonColor || theme.colors.primary;
37
+
38
+ // Determine text color based on background color for contained mode
39
+ const getContainedTextColor = () => {
40
+ if (textColor) return textColor;
41
+ return isLightColor(primaryColor) ? '#000000' : '#FFFFFF';
42
+ };
43
+ const containedTextColor = getContainedTextColor();
44
+ const getButtonStyle = () => {
45
+ const baseStyle = [styles.button, style];
46
+ if (mode === 'contained') {
47
+ return [...baseStyle, styles.containedButton, {
48
+ backgroundColor: primaryColor
49
+ }, disabled && styles.disabledButton];
50
+ }
51
+ if (mode === 'outlined') {
52
+ return [...baseStyle, styles.outlinedButton, {
53
+ borderColor: primaryColor
54
+ }, disabled && styles.disabledButton];
55
+ }
56
+ return [...baseStyle, styles.textButton];
57
+ };
58
+ const getTextStyle = () => {
59
+ const baseStyle = [styles.label, labelStyle];
60
+ if (mode === 'contained') {
61
+ return [...baseStyle, styles.containedLabel, {
62
+ color: containedTextColor
63
+ }, disabled && styles.disabledLabel];
64
+ }
65
+ if (mode === 'outlined') {
66
+ return [...baseStyle, styles.outlinedLabel, {
67
+ color: primaryColor
68
+ }, disabled && styles.disabledLabel];
69
+ }
70
+ return [...baseStyle, styles.textLabel, {
71
+ color: primaryColor
72
+ }, disabled && styles.disabledLabel];
73
+ };
74
+ const loadingColor = mode === 'contained' ? containedTextColor : primaryColor;
75
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
76
+ style: getButtonStyle(),
77
+ onPress: onPress,
78
+ disabled: disabled || loading,
79
+ activeOpacity: 0.7,
80
+ children: loading ? /*#__PURE__*/_jsx(ActivityIndicator, {
81
+ size: "small",
82
+ color: loadingColor
83
+ }) : /*#__PURE__*/_jsx(Text, {
84
+ style: getTextStyle(),
85
+ children: children
86
+ })
16
87
  });
17
88
  };
18
89
  const styles = StyleSheet.create({
@@ -20,11 +91,39 @@ const styles = StyleSheet.create({
20
91
  borderRadius: 8,
21
92
  height: 56,
22
93
  justifyContent: 'center',
23
- elevation: 2
94
+ alignItems: 'center',
95
+ paddingHorizontal: 16
96
+ },
97
+ containedButton: {
98
+ elevation: 2,
99
+ shadowColor: '#000',
100
+ shadowOffset: {
101
+ width: 0,
102
+ height: 2
103
+ },
104
+ shadowOpacity: 0.25,
105
+ shadowRadius: 3.84
106
+ },
107
+ outlinedButton: {
108
+ backgroundColor: 'transparent',
109
+ borderWidth: 2
110
+ },
111
+ textButton: {
112
+ backgroundColor: 'transparent'
113
+ },
114
+ disabledButton: {
115
+ opacity: 0.5
24
116
  },
25
117
  label: {
26
118
  fontWeight: 'bold',
27
- fontSize: 16
119
+ fontSize: 16,
120
+ textAlign: 'center'
121
+ },
122
+ containedLabel: {},
123
+ outlinedLabel: {},
124
+ textLabel: {},
125
+ disabledLabel: {
126
+ opacity: 0.6
28
127
  }
29
128
  });
30
129
  export default StyledButton;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { StyleSheet, TextInput, View, Text } from 'react-native';
5
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
+ const StyledTextInput = /*#__PURE__*/React.forwardRef(({
7
+ containerStyle,
8
+ inputStyle,
9
+ placeholderStyle,
10
+ borderColor = '#DDDDDD',
11
+ focusedBorderColor,
12
+ backgroundColor = '#FFFFFF',
13
+ textColor = '#000000',
14
+ placeholderColor = '#999999',
15
+ style,
16
+ placeholderTextColor,
17
+ onFocus,
18
+ onBlur,
19
+ value,
20
+ ...props
21
+ }, ref) => {
22
+ const [isFocused, setIsFocused] = React.useState(false);
23
+ const hasValue = value !== undefined && value !== '';
24
+ const handleFocus = e => {
25
+ setIsFocused(true);
26
+ onFocus?.(e);
27
+ };
28
+ const handleBlur = e => {
29
+ setIsFocused(false);
30
+ onBlur?.(e);
31
+ };
32
+ const currentBorderColor = isFocused ? focusedBorderColor || borderColor : borderColor;
33
+ return /*#__PURE__*/_jsxs(View, {
34
+ style: [styles.container, containerStyle],
35
+ children: [/*#__PURE__*/_jsx(TextInput, {
36
+ ref: ref,
37
+ ...props,
38
+ value: value,
39
+ placeholder: "",
40
+ style: [styles.input, {
41
+ backgroundColor,
42
+ borderColor: currentBorderColor,
43
+ color: textColor
44
+ }, inputStyle, style],
45
+ onFocus: handleFocus,
46
+ onBlur: handleBlur
47
+ }), !hasValue && props.placeholder && /*#__PURE__*/_jsx(View, {
48
+ style: styles.placeholderContainer,
49
+ pointerEvents: "none",
50
+ children: /*#__PURE__*/_jsx(Text, {
51
+ style: [styles.placeholderText, {
52
+ color: placeholderColor || placeholderTextColor || '#999'
53
+ }, placeholderStyle],
54
+ children: props.placeholder
55
+ })
56
+ })]
57
+ });
58
+ });
59
+ StyledTextInput.displayName = 'StyledTextInput';
60
+ const styles = StyleSheet.create({
61
+ container: {
62
+ width: '100%',
63
+ position: 'relative'
64
+ },
65
+ input: {
66
+ borderWidth: 2,
67
+ borderRadius: 8,
68
+ height: 56,
69
+ paddingHorizontal: 16,
70
+ fontSize: 16,
71
+ fontWeight: '400'
72
+ },
73
+ placeholderContainer: {
74
+ position: 'absolute',
75
+ top: 0,
76
+ left: 0,
77
+ right: 0,
78
+ bottom: 0,
79
+ justifyContent: 'center',
80
+ paddingHorizontal: 16
81
+ },
82
+ placeholderText: {
83
+ fontSize: 16,
84
+ fontWeight: '400'
85
+ }
86
+ });
87
+ export default StyledTextInput;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ import React, { createContext, useContext, useMemo } from 'react';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ const defaultColors = {
6
+ primary: '#000000',
7
+ secondary: '#CCCCCC',
8
+ tertiary: '#FF0000',
9
+ background: '#FFFFFF',
10
+ surface: '#F5F5F5',
11
+ text: '#000000',
12
+ textSecondary: '#666666',
13
+ border: '#DDDDDD',
14
+ error: '#E53935',
15
+ success: '#43A047'
16
+ };
17
+ const ThemeContext = /*#__PURE__*/createContext({
18
+ colors: defaultColors
19
+ });
20
+ export const useTheme = () => useContext(ThemeContext);
21
+ export const ThemeProvider = ({
22
+ children,
23
+ primaryColor,
24
+ secondaryColor,
25
+ tertiaryColor
26
+ }) => {
27
+ const colors = useMemo(() => ({
28
+ ...defaultColors,
29
+ primary: primaryColor || defaultColors.primary,
30
+ secondary: secondaryColor || defaultColors.secondary,
31
+ tertiary: tertiaryColor || defaultColors.tertiary
32
+ }), [primaryColor, secondaryColor, tertiaryColor]);
33
+ const value = useMemo(() => ({
34
+ colors
35
+ }), [colors]);
36
+ return /*#__PURE__*/_jsx(ThemeContext.Provider, {
37
+ value: value,
38
+ children: children
39
+ });
40
+ };
@@ -3,13 +3,20 @@
3
3
  import i18n from 'i18next';
4
4
  import { initReactI18next } from 'react-i18next';
5
5
  import * as resources from "./Resources/index.js";
6
- import { Platform, NativeModules } from 'react-native';
7
6
  const getCurrentLanguage = () => {
8
- let deviceLanguage = Platform.OS === 'ios' ? NativeModules?.SettingsManager?.settings?.AppleLocale : NativeModules?.I18nManager?.localeIdentifier;
9
- if (!deviceLanguage) {
10
- deviceLanguage = NativeModules?.SettingsManager?.settings?.AppleLanguages[0];
7
+ try {
8
+ if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) {
9
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale;
10
+ if (locale) {
11
+ // Extract language code from locale (e.g., "en-US" -> "en", "tr-TR" -> "tr")
12
+ return locale.split(/[-_]/)[0].toLowerCase();
13
+ }
14
+ }
15
+ return 'en';
16
+ } catch (error) {
17
+ console.error('Error detecting language:', error);
18
+ return 'en';
11
19
  }
12
- return deviceLanguage;
13
20
  };
14
21
  i18n.use(initReactI18next).init({
15
22
  compatibilityJSON: 'v4',