@jimrising/easymerchantsdk-react-native 2.0.4 → 2.0.7

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 (111) hide show
  1. package/README.md +1016 -391
  2. package/android/.gradle/8.10/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.10/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.10/fileChanges/last-build.bin +0 -0
  5. package/android/.gradle/8.10/fileHashes/fileHashes.bin +0 -0
  6. package/android/.gradle/8.10/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/8.10/gc.properties +0 -0
  8. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  9. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  10. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  11. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  12. package/android/.gradle/8.9/gc.properties +0 -0
  13. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  14. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  15. package/android/.gradle/nb-cache/trust/0B5D6BE682AD6AEE9815EC13516BF075752CAE5AD5BECDCC00315C37622C2FD3 +1 -0
  16. package/android/.gradle/vcs-1/gc.properties +0 -0
  17. package/android/build/.transforms/15b6a8a60a6b32d0dcaf609723cf365b/transformed/classes/classes_dex/classes.dex +0 -0
  18. package/android/build/.transforms/664c2535aec304a21f4de38c6fe405c3/results.bin +1 -0
  19. package/android/build/.transforms/664c2535aec304a21f4de38c6fe405c3/transformed/classes/classes_dex/classes.dex +0 -0
  20. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  21. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  22. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  23. package/android/build/.transforms/8508f1428f740032c45a43f48b1bbe1e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  24. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/results.bin +1 -0
  25. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
  26. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  27. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  28. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  29. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  30. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
  31. package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  32. package/android/build/.transforms/eef2d06269ef2e204b4f065513034fca/transformed/classes/classes_dex/classes.dex +0 -0
  33. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
  34. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
  35. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
  36. package/android/build/.transforms/ffabb40f9809b32eb9546ce76fc51764/transformed/bundleLibRuntimeToDirRelease/bundleLibRuntimeToDirRelease_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
  37. package/android/build/intermediates/aar_main_jar/release/syncReleaseLibJars/classes.jar +0 -0
  38. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  39. package/android/build/intermediates/compile_library_classes_jar/release/bundleLibCompileToJarRelease/classes.jar +0 -0
  40. package/android/build/intermediates/full_jar/release/createFullJarRelease/full.jar +0 -0
  41. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
  42. package/android/build/intermediates/incremental/lintVitalAnalyzeRelease/release-artifact-dependencies.xml +4 -4
  43. package/android/build/intermediates/incremental/lintVitalAnalyzeRelease/release-artifact-libraries.xml +4 -4
  44. package/android/build/intermediates/incremental/release/mergeReleaseResources/compile-file-map.properties +426 -425
  45. package/android/build/intermediates/incremental/release/mergeReleaseResources/merged.dir/values/values.xml +1 -1
  46. package/android/build/intermediates/incremental/release/mergeReleaseResources/merger.xml +3 -3
  47. package/android/build/intermediates/incremental/release/packageReleaseResources/compile-file-map.properties +1 -1
  48. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  49. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  50. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  51. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  52. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  53. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  54. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  55. package/android/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  56. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/maven.google/com/android/tools/build/group-index.xml +15 -15
  57. package/android/build/intermediates/lint-cache/lintVitalAnalyzeRelease/maven.google/master-index.xml +1 -0
  58. package/android/build/intermediates/lint_model/release/generateReleaseLintModel/release-artifact-dependencies.xml +4 -4
  59. package/android/build/intermediates/lint_model/release/generateReleaseLintModel/release-artifact-libraries.xml +4 -4
  60. package/android/build/intermediates/lint_vital_lint_model/release/generateReleaseLintVitalModel/release-artifact-dependencies.xml +4 -4
  61. package/android/build/intermediates/lint_vital_lint_model/release/generateReleaseLintVitalModel/release-artifact-libraries.xml +4 -4
  62. package/android/build/intermediates/local_aar_for_lint/release/out.aar +0 -0
  63. package/android/build/intermediates/merged_res/release/mergeReleaseResources/drawable/close_icon_main.xml +16 -0
  64. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_payment_done_url.xml +2 -3
  65. package/android/build/intermediates/merged_res/release/mergeReleaseResources/layout/activity_select_payment_method.xml +24 -6
  66. package/android/build/intermediates/merged_res/release/mergeReleaseResources/values/values.xml +1 -1
  67. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/multi-v2/values-night-v8.json +19 -19
  68. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/multi-v2/values.json +102 -102
  69. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/anim-v21.json +1 -1
  70. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/anim.json +1 -1
  71. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/animator.json +8 -8
  72. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/drawable.json +319 -315
  73. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/font.json +9 -9
  74. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/layout.json +27 -27
  75. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-anydpi-v26.json +2 -2
  76. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-hdpi-v4.json +2 -2
  77. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-mdpi-v4.json +2 -2
  78. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xhdpi-v4.json +2 -2
  79. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xxhdpi-v4.json +2 -2
  80. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/mipmap-xxxhdpi-v4.json +2 -2
  81. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/raw.json +46 -46
  82. package/android/build/intermediates/merged_res_blame_folder/release/mergeReleaseResources/out/single/xml.json +2 -2
  83. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  84. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  85. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  86. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  87. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
  88. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
  89. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
  90. package/android/build/intermediates/runtime_library_classes_dir/release/bundleLibRuntimeToDirRelease/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
  91. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  92. package/android/build/intermediates/runtime_library_classes_jar/release/bundleLibRuntimeToJarRelease/classes.jar +0 -0
  93. package/android/build/intermediates/source_set_path_map/release/mapReleaseSourceSetPaths/file-map.txt +17 -17
  94. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/drawable_close_icon_main.xml.flat +0 -0
  95. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_payment_done_url.xml.flat +0 -0
  96. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/layout_activity_select_payment_method.xml.flat +0 -0
  97. package/android/build/intermediates/verified_library_resources/release/verifyReleaseResources/compiled/values_values.arsc.flat +0 -0
  98. package/android/build/outputs/aar/jimrising_easymerchantsdk-react-native-release.aar +0 -0
  99. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  100. package/android/build/tmp/compileReleaseJavaWithJavac/previous-compilation-data.bin +0 -0
  101. package/android/build.gradle +1 -1
  102. package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +9 -0
  103. package/ios/Classes/EasyMerchantSdk.m +2 -0
  104. package/ios/Classes/EasyMerchantSdk.swift +3 -1
  105. package/ios/Models/Request.swift +50 -3
  106. package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +74 -6
  107. package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +92 -20
  108. package/ios/Pods/ViewControllers/OTPVerificationVC.swift +28 -2
  109. package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +73 -564
  110. package/ios/easymerchantsdk.podspec +1 -1
  111. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@ To add the path of sdk in your project. Open your `package.json` file and inside
7
7
 
8
8
  ```json
9
9
  "dependencies": {
10
- "@jimrising/easymerchantsdk-react-native": "^2.0.4"
10
+ "@jimrising/easymerchantsdk-react-native": "^2.0.7"
11
11
  },
12
12
  ```
13
13
 
@@ -23,14 +23,7 @@ allprojects {
23
23
  repositories {
24
24
  google()
25
25
  mavenCentral()
26
- maven { url 'https://jitpack.io' }
27
- maven {
28
- url = uri(properties.getProperty('GITHUB_URL'))
29
- credentials {
30
- username = properties.getProperty('GITHUB_USERNAME')
31
- password = properties.getProperty('GITHUB_PASSWORD')
32
- }
33
- }
26
+
34
27
  }
35
28
  }
36
29
  ```
@@ -39,7 +32,7 @@ allprojects {
39
32
  Add below content inside the AppDelegate.swift File :-
40
33
 
41
34
  ## Requirements
42
- - Ruby 3.2.8
35
+ - Ruby 3.2.8
43
36
 
44
37
 
45
38
  Create a new file named AppDelegate.swift
@@ -129,10 +122,121 @@ import {
129
122
  Switch,
130
123
  TouchableOpacity,
131
124
  NativeEventEmitter,
125
+ KeyboardAvoidingView,
126
+ Keyboard,
127
+ TouchableWithoutFeedback,
128
+ Modal,
132
129
  } from 'react-native';
133
130
 
134
131
  const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
135
132
 
133
+ // Dropdown Component
134
+ const Dropdown = ({ value, onValueChange, options, placeholder }) => {
135
+ const [isOpen, setIsOpen] = useState(false);
136
+
137
+ // Handler to close modal when tapping outside
138
+ const handleClose = () => setIsOpen(false);
139
+
140
+ return (
141
+ <View style={styles.dropdownContainer} pointerEvents="box-none">
142
+ <TouchableOpacity
143
+ style={styles.dropdownButton}
144
+ onPress={() => setIsOpen(!isOpen)}
145
+ >
146
+ <Text style={styles.dropdownButtonText}>
147
+ {value || placeholder}
148
+ </Text>
149
+ <Text style={styles.dropdownArrow}>
150
+ {isOpen ? '▲' : '▼'}
151
+ </Text>
152
+ </TouchableOpacity>
153
+ {Platform.OS === 'android' ? (
154
+ <Modal
155
+ visible={isOpen}
156
+ transparent={true}
157
+ animationType="fade"
158
+ onRequestClose={handleClose}
159
+ >
160
+ <TouchableWithoutFeedback onPress={handleClose}>
161
+ <View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.2)' }}>
162
+ <View style={[styles.dropdownOptions, { position: 'absolute', top: '30%', left: 20, right: 20, maxHeight: 300, elevation: 20 }]}>
163
+ <ScrollView
164
+ style={[styles.dropdownScrollView, { maxHeight: 280 }]}
165
+ showsVerticalScrollIndicator={true}
166
+ persistentScrollbar={true}
167
+ nestedScrollEnabled={true}
168
+ keyboardShouldPersistTaps="handled"
169
+ >
170
+ {options.map((option, index) => (
171
+ <TouchableOpacity
172
+ key={index}
173
+ style={styles.dropdownOption}
174
+ onPress={() => {
175
+ onValueChange(option);
176
+ setIsOpen(false);
177
+ }}
178
+ >
179
+ <Text style={styles.dropdownOptionText}>{option}</Text>
180
+ </TouchableOpacity>
181
+ ))}
182
+ </ScrollView>
183
+ </View>
184
+ </View>
185
+ </TouchableWithoutFeedback>
186
+ </Modal>
187
+ ) : (
188
+ isOpen && (
189
+ <View style={styles.dropdownOptions}>
190
+ <ScrollView
191
+ style={styles.dropdownScrollView}
192
+ showsVerticalScrollIndicator={true}
193
+ persistentScrollbar={true}
194
+ nestedScrollEnabled={true}
195
+ keyboardShouldPersistTaps="handled"
196
+ >
197
+ {options.map((option, index) => (
198
+ <TouchableOpacity
199
+ key={index}
200
+ style={styles.dropdownOption}
201
+ onPress={() => {
202
+ onValueChange(option);
203
+ setIsOpen(false);
204
+ }}
205
+ >
206
+ <Text style={styles.dropdownOptionText}>{option}</Text>
207
+ </TouchableOpacity>
208
+ ))}
209
+ </ScrollView>
210
+ </View>
211
+ )
212
+ )}
213
+ </View>
214
+ );
215
+ };
216
+
217
+ // Custom Filled Button Component
218
+ const FilledButton = ({ title, onPress, disabled = false, style = {}, textStyle = {} }) => {
219
+ return (
220
+ <TouchableOpacity
221
+ style={[
222
+ styles.filledButton,
223
+ disabled && styles.filledButtonDisabled,
224
+ style,
225
+ ]}
226
+ onPress={onPress}
227
+ disabled={disabled}
228
+ >
229
+ <Text style={[
230
+ styles.filledButtonText,
231
+ disabled && styles.filledButtonTextDisabled,
232
+ textStyle,
233
+ ]}>
234
+ {title}
235
+ </Text>
236
+ </TouchableOpacity>
237
+ );
238
+ };
239
+
136
240
  const externalConfig = {
137
241
  amount: '',
138
242
  email: '',
@@ -141,8 +245,8 @@ const externalConfig = {
141
245
  isSecureAuthentication: false,
142
246
  isBillingVisible: false,
143
247
  isAdditionalVisible: false,
144
- emailEditable: true,
145
- isEmail: true,
248
+ emailEditable: true,
249
+ isEmail: true,
146
250
  billingInfo: {
147
251
  visibility: { billing: false, additional: false },
148
252
  billing: {
@@ -162,7 +266,7 @@ const externalConfig = {
162
266
  additional: {
163
267
  name: 'Test User',
164
268
  email_address: 'test@gmail.com',
165
- phone_number: '21408713290',
269
+ phone_number: '2140871329',
166
270
  description: 'Test',
167
271
  },
168
272
  additionalRequired: {
@@ -172,22 +276,20 @@ const externalConfig = {
172
276
  description: false,
173
277
  },
174
278
  },
175
- themeConfiguration: {
176
- bodyBackgroundColor: '#0f1715',
177
- containerBackgroundColor: '#152321',
178
- primaryFontColor: '#FFFFFF',
179
- secondaryFontColor: '#A0B5A4',
180
- primaryButtonBackgroundColor: '#10B981',
181
- primaryButtonHoverColor: '#059669',
182
- primaryButtonFontColor: '#FFFFFF',
183
- secondaryButtonBackgroundColor: '#374151',
184
- secondaryButtonHoverColor: '#4B5563',
185
- secondaryButtonFontColor: '#E5E7EB',
186
- borderRadius: '8',
187
- fontSize: '14',
188
- fontWeight: 500,
189
- fontFamily: '"Inter", sans-serif',
190
- },
279
+ themeConfiguration: {
280
+ bodyBackgroundColor: '#1E3A8A',
281
+ containerBackgroundColor: '#1E40AF',
282
+ primaryFontColor: '#FFFFFF',
283
+ secondaryFontColor: '#BFDBFE',
284
+ primaryButtonBackgroundColor: '#3B82F6',
285
+ primaryButtonHoverColor: '#2563EB',
286
+ primaryButtonFontColor: '#FFFFFF',
287
+ secondaryButtonBackgroundColor: '#1D4ED8',
288
+ secondaryButtonHoverColor: '#1E40AF',
289
+ secondaryButtonFontColor: '#FFFFFF',
290
+ borderRadius: '8',
291
+ fontSize: '14',
292
+ },
191
293
  grailPayParams: {
192
294
  role: 'business',
193
295
  timeout: 10,
@@ -198,9 +300,9 @@ const externalConfig = {
198
300
  },
199
301
  recurringData: {
200
302
  allowCycles: 2,
201
- intervals: ['daily','weekly', 'monthly'],
202
- recurringStartType: 'custom',
203
- recurringStartDate: '07/08/2030',
303
+ intervals: ['daily', 'weekly', 'monthly'],
304
+ recurringStartType: Platform.OS === 'android' ? ['Custom', 'Fixed'] : ['custom', 'fixed'],
305
+ recurringStartDate: new Date().toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }),
204
306
  },
205
307
  androidConfig: {
206
308
  currency: 'usd',
@@ -211,7 +313,7 @@ const externalConfig = {
211
313
  showTotal: true,
212
314
  showSubmitButton: true,
213
315
  paymentMethod: ['card', 'ach'],
214
- name: 'Pavan',
316
+ name: '',
215
317
  fields: {
216
318
  visibility: { billing: false, additional: false },
217
319
  billing: [
@@ -230,20 +332,20 @@ const externalConfig = {
230
332
  },
231
333
  appearanceSettings: {
232
334
  theme: 'dark',
233
- bodyBackgroundColor: '#121212',
234
- containerBackgroundColor: '#1E1E1E',
335
+ bodyBackgroundColor: '#0F5132',
336
+ containerBackgroundColor: '#166534',
235
337
  primaryFontColor: '#FFFFFF',
236
- secondaryFontColor: '#B0B0B0',
237
- primaryButtonBackgroundColor: '#2563EB',
238
- primaryButtonHoverColor: '#1D4ED8',
338
+ secondaryFontColor: '#D1FAE5',
339
+ primaryButtonBackgroundColor: '#059669',
340
+ primaryButtonHoverColor: '#047857',
239
341
  primaryButtonFontColor: '#FFFFFF',
240
- secondaryButtonBackgroundColor: '#374151',
241
- secondaryButtonHoverColor: '#4B5563',
242
- secondaryButtonFontColor: '#E5E7EB',
342
+ secondaryButtonBackgroundColor: '#065F46',
343
+ secondaryButtonHoverColor: '#064E3B',
344
+ secondaryButtonFontColor: '#FFFFFF',
243
345
  borderRadius: '8',
244
346
  fontSize: '14',
245
- fontWeight: '500',
246
- fontFamily: 'Inter, sans-serif',
347
+ fontWeight: 500,
348
+ fontFamily: '"Inter", sans-serif',
247
349
  },
248
350
  },
249
351
  };
@@ -251,6 +353,7 @@ const externalConfig = {
251
353
  const App = () => {
252
354
  const [amount, setAmount] = useState(externalConfig.amount);
253
355
  const [email, setEmail] = useState(externalConfig.email);
356
+ const [name, setName] = useState('');
254
357
  const [environment, setEnvironment] = useState('sandbox');
255
358
  const [isRecurring, setIsRecurring] = useState(externalConfig.isRecurring);
256
359
  const [isAuthenticatedACH, setAuthenticatedACH] = useState(externalConfig.isAuthenticatedACH);
@@ -268,6 +371,13 @@ const App = () => {
268
371
  const [referenceToken, setReferenceToken] = useState('');
269
372
  const [loading, setLoading] = useState(false);
270
373
  const [showSecretKey, setShowSecretKey] = useState(false);
374
+ const metadata = {
375
+ metaKey: 'metaValue',
376
+ metaKLey1: 'metaValue1',
377
+ metaKLey2: 'metaValue2',
378
+ metaKLey3: 'metaValue3',
379
+ metaKLey4: 'metaValue4',
380
+ };
271
381
 
272
382
  const [apiKeys, setApiKeys] = useState({
273
383
  sandbox: {
@@ -282,6 +392,21 @@ const [apiKeys, setApiKeys] = useState({
282
392
  const [isEnvironmentLoading, setIsEnvironmentLoading] = useState(false);
283
393
  const [showConfig, setShowConfig] = useState(true);
284
394
 
395
+ // Debug useEffect to track payment method changes
396
+ useEffect(() => {
397
+ console.log('Payment methods state changed:', androidConfig.paymentMethod);
398
+ }, [androidConfig.paymentMethod]);
399
+
400
+ // Debug useEffect to track theme configuration changes
401
+ useEffect(() => {
402
+ console.log('Theme configuration changed:', themeConfiguration);
403
+ }, [themeConfiguration]);
404
+
405
+ // Debug useEffect to track Android appearance settings changes
406
+ useEffect(() => {
407
+ console.log('Android appearance settings changed:', androidConfig.appearanceSettings);
408
+ }, [androidConfig.appearanceSettings]);
409
+
285
410
 
286
411
  useEffect(() => {
287
412
  const updateEnvironment = async () => {
@@ -450,12 +575,36 @@ const safeParseMaybeJSON = (value) => {
450
575
  };
451
576
 
452
577
  const togglePaymentMethod = (method) => {
453
- setAndroidConfig(prev => ({
454
- ...prev,
455
- paymentMethod: prev.paymentMethod.includes(method)
456
- ? prev.paymentMethod.filter(m => m !== method)
457
- : [...prev.paymentMethod, method],
458
- }));
578
+ console.log('Toggling payment method:', method);
579
+ setAndroidConfig(prev => {
580
+ const currentMethods = prev.paymentMethod;
581
+ console.log('Current payment methods before toggle:', currentMethods);
582
+ const isCurrentlySelected = currentMethods.includes(method);
583
+ console.log('Is currently selected:', isCurrentlySelected);
584
+
585
+ let newMethods;
586
+ if (isCurrentlySelected) {
587
+ // If deselecting and it's the only method, don't allow deselection
588
+ if (currentMethods.length === 1) {
589
+ console.log('Cannot deselect last payment method, keeping current state');
590
+ return prev; // Keep the current state
591
+ }
592
+ // Remove the method
593
+ newMethods = currentMethods.filter(m => m !== method);
594
+ console.log('Removing method, new methods:', newMethods);
595
+ } else {
596
+ // Add the method
597
+ newMethods = [...currentMethods, method];
598
+ console.log('Adding method, new methods:', newMethods);
599
+ }
600
+
601
+ const updatedConfig = {
602
+ ...prev,
603
+ paymentMethod: newMethods,
604
+ };
605
+ console.log('Updated android config payment methods:', updatedConfig.paymentMethod);
606
+ return updatedConfig;
607
+ });
459
608
  };
460
609
 
461
610
  const toggleInterval = (interval) => {
@@ -471,58 +620,126 @@ const safeParseMaybeJSON = (value) => {
471
620
  if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
472
621
  return Alert.alert('Error', 'Please enter a valid amount');
473
622
  }
474
- if (!email) {
475
- return Alert.alert('Error', 'Please enter an email address');
623
+
624
+ // Validate that at least one interval is selected when recurring payment is enabled
625
+ if (isRecurring && (!recurringData.intervals || recurringData.intervals.length === 0)) {
626
+ return Alert.alert('Error', 'Please select at least one interval for recurring payment');
476
627
  }
477
628
 
478
629
  setLoading(true);
479
- if (Platform.OS === 'android') {
480
- await handleAndroidBilling();
481
- } else {
482
- await handleIosBilling();
630
+
631
+ // Add a timeout to ensure loading state is reset even if SDK blocks execution
632
+ const timeoutId = setTimeout(() => {
633
+ setLoading(false);
634
+ }, 3000); // 3 second timeout
635
+
636
+ try {
637
+ if (Platform.OS === 'android') {
638
+ await handleAndroidBilling();
639
+ } else {
640
+ await handleIosBilling();
641
+ }
642
+ } finally {
643
+ clearTimeout(timeoutId);
644
+ setLoading(false);
483
645
  }
484
646
  };
485
647
 
486
648
  const handleAndroidBilling = async () => {
649
+
487
650
  const { apiKey, secretKey } = apiKeys[environment];
488
- const config = {
489
- amount,
490
- apiKey: apiKey,
491
- secretKey: apiSecret,
492
- jsonConfig: {
493
- environment,
494
- amount,
495
- tokenOnly: false,
496
- currency: androidConfig.currency,
497
- saveCard: androidConfig.saveCard,
498
- saveAccount: androidConfig.saveAccount,
499
- authenticatedACH: isAuthenticatedACH,
500
- secureAuthentication: isSecureAuthentication,
501
- showReceipt: androidConfig.showReceipt,
502
- showDonate: androidConfig.showDonate,
503
- showTotal: androidConfig.showTotal,
504
- showSubmitButton: androidConfig.showSubmitButton,
505
- paymentMethod: androidConfig.paymentMethod,
506
- emailEditable,
507
- email,
508
- name: androidConfig.name,
509
- fields: {
510
- ...androidConfig.fields,
511
- visibility: {
512
- billing: isBillingVisible,
513
- additional: isAdditionalVisible,
514
- },
515
- },
516
- ...(isRecurring && {
517
- recurring: {
518
- enableRecurring: true,
519
- recurringData,
520
- },
521
- }),
522
- grailPayParams,
523
- appearanceSettings: androidConfig.appearanceSettings,
524
- },
525
- };
651
+
652
+ console.log('Selected payment methods for Android:', androidConfig.paymentMethod);
653
+ console.log('Full androidConfig.paymentMethod:', JSON.stringify(androidConfig.paymentMethod));
654
+
655
+ // Create a fresh copy of payment methods to ensure no reference issues
656
+ const selectedPaymentMethods = [...androidConfig.paymentMethod];
657
+ console.log('Fresh copy of payment methods:', selectedPaymentMethods);
658
+ console.log('Payment method contains "ach":', selectedPaymentMethods.includes('ach'));
659
+ console.log('Payment method contains "card":', selectedPaymentMethods.includes('card'));
660
+
661
+ // Log ACH-specific configurations when ACH is selected
662
+ if (selectedPaymentMethods.includes('ach')) {
663
+ console.log('=== ACH CONFIGURATION DEBUG ===');
664
+ console.log('authenticatedACH setting:', isAuthenticatedACH);
665
+ console.log('secureAuthentication setting:', isSecureAuthentication);
666
+ console.log('saveAccount setting:', androidConfig.saveAccount);
667
+ }
668
+
669
+ // Try different payment method format for ACH-only scenario
670
+ let finalPaymentMethods = selectedPaymentMethods;
671
+ if (selectedPaymentMethods.length === 1 && selectedPaymentMethods.includes('ach')) {
672
+ // Try using a different format for ACH-only
673
+ finalPaymentMethods = ['ach'];
674
+ console.log('Using ACH-only format:', finalPaymentMethods);
675
+ }
676
+
677
+ const config = {
678
+ amount,
679
+ apiKey: apiKey,
680
+ secretKey: secretKey,
681
+ jsonConfig: {
682
+ environment,
683
+ amount,
684
+ tokenOnly: false,
685
+ currency: androidConfig.currency,
686
+ saveCard: androidConfig.saveCard,
687
+ saveAccount: androidConfig.saveAccount,
688
+ authenticatedACH: isAuthenticatedACH,
689
+ secureAuthentication: isSecureAuthentication,
690
+
691
+ showReceipt: androidConfig.showReceipt,
692
+ showDonate: androidConfig.showDonate,
693
+ showTotal: androidConfig.showTotal,
694
+ showSubmitButton: androidConfig.showSubmitButton,
695
+ paymentMethod: finalPaymentMethods,
696
+ // Try different configuration approaches for ACH-only
697
+ ...(finalPaymentMethods.length === 1 && finalPaymentMethods.includes('ach') && {
698
+ paymentMethods: ['ach'],
699
+ allowedPaymentMethods: ['ach'],
700
+ disableCard: true,
701
+ }),
702
+
703
+ emailEditable,
704
+ email,
705
+ name: name,
706
+ fields: {
707
+ ...androidConfig.fields,
708
+ visibility: {
709
+ billing: isBillingVisible,
710
+ additional: isAdditionalVisible,
711
+ },
712
+ },
713
+
714
+ metadata,
715
+
716
+
717
+ ...(isRecurring && {
718
+ recurring: {
719
+ enableRecurring: true,
720
+ recurringData,
721
+ },
722
+ }),
723
+ grailPayParams,
724
+ appearanceSettings: androidConfig.appearanceSettings,
725
+
726
+
727
+ },
728
+ };
729
+
730
+ console.log('ENV API Keys =>', {
731
+ env: environment,
732
+ apiKeyFromEnv: apiKey,
733
+ secretKeyFromEnv: secretKey,
734
+ });
735
+
736
+ console.log('Config API Key =>', config.apiKey);
737
+ console.log('Config Secret Key =>', config.secretKey);
738
+ console.log('Full config being sent to Android SDK:', JSON.stringify(config, null, 2));
739
+ console.log('=== THEME CONFIGURATION DEBUG ===');
740
+ console.log('Android appearanceSettings:', JSON.stringify(androidConfig.appearanceSettings, null, 2));
741
+
742
+
526
743
 
527
744
  try {
528
745
  const response = await RNEasymerchantsdk.makePayment(config);
@@ -546,12 +763,33 @@ setResult(JSON.stringify(parsedResponse, null, 2));
546
763
  };
547
764
 
548
765
  const handleIosBilling = async () => {
766
+
767
+ console.log('Selected payment methods for iOS:', androidConfig.paymentMethod);
768
+ console.log('Full androidConfig.paymentMethod for iOS:', JSON.stringify(androidConfig.paymentMethod));
769
+
770
+ // Create a fresh copy of payment methods for iOS and convert to iOS format
771
+ const selectedPaymentMethodsIOS = [...androidConfig.paymentMethod];
772
+ console.log('Fresh copy of payment methods for iOS:', selectedPaymentMethodsIOS);
773
+ console.log('Payment method contains "ach" (iOS):', selectedPaymentMethodsIOS.includes('ach'));
774
+ console.log('Payment method contains "card" (iOS):', selectedPaymentMethodsIOS.includes('card'));
775
+
776
+ // Convert Android payment method names to iOS format
777
+ let finalPaymentMethodsIOS = selectedPaymentMethodsIOS.map(method => {
778
+ if (method === 'card') return 'Card';
779
+ if (method === 'ach') return 'Bank';
780
+ return method;
781
+ });
782
+
783
+ console.log('Converted payment methods for iOS:', finalPaymentMethodsIOS);
784
+ console.log('=== iOS THEME CONFIGURATION DEBUG ===');
785
+ console.log('iOS themeConfiguration:', JSON.stringify(themeConfiguration, null, 2));
786
+
549
787
  try {
550
788
  const result = await EasyMerchantSdk.billing(
551
789
  amount,
552
790
  androidConfig.currency || 'usd',
553
791
  billingInfo,
554
- androidConfig.paymentMethod,
792
+ finalPaymentMethodsIOS,
555
793
  themeConfiguration,
556
794
  false, // tokenOnly
557
795
  androidConfig.saveCard,
@@ -570,7 +808,8 @@ setResult(JSON.stringify(parsedResponse, null, 2));
570
808
  androidConfig.showSubmitButton,
571
809
  isEmail,
572
810
  email,
573
- androidConfig.name
811
+ name,
812
+ metadata
574
813
  );
575
814
 
576
815
  const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
@@ -603,10 +842,6 @@ setResult(JSON.stringify(parsedResponse, null, 2));
603
842
  setResult('Payment Reference not supported on Android');
604
843
  return;
605
844
  }
606
- if (!referenceToken) {
607
- setResult('No reference token available');
608
- return;
609
- }
610
845
  try {
611
846
  const response = await EasyMerchantSdk.paymentReference(referenceToken);
612
847
  setResult(`Payment Reference:\n${JSON.stringify(response, null, 2)}`);
@@ -618,8 +853,16 @@ setResult(JSON.stringify(parsedResponse, null, 2));
618
853
  };
619
854
 
620
855
  return (
621
- <View style={styles.container}>
622
- <ScrollView contentContainerStyle={styles.scrollContent}>
856
+ <KeyboardAvoidingView
857
+ style={styles.container}
858
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
859
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
860
+ >
861
+ <ScrollView
862
+ contentContainerStyle={styles.scrollContent}
863
+ keyboardShouldPersistTaps="handled"
864
+ showsVerticalScrollIndicator={false}
865
+ >
623
866
  <Text style={styles.title}>EasyMerchant SDK</Text>
624
867
 
625
868
 
@@ -629,6 +872,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
629
872
  <TextInput
630
873
  style={styles.input}
631
874
  placeholder="Enter amount (e.g., 10.00)"
875
+ placeholderTextColor="#999999"
632
876
  keyboardType="decimal-pad"
633
877
  value={amount}
634
878
  onChangeText={setAmount}
@@ -637,18 +881,39 @@ setResult(JSON.stringify(parsedResponse, null, 2));
637
881
  <TextInput
638
882
  style={styles.input}
639
883
  placeholder="Enter email"
884
+ placeholderTextColor="#999999"
640
885
  keyboardType="email-address"
641
886
  value={email}
642
887
  onChangeText={setEmail}
643
888
  />
889
+ <Text style={styles.label}>Name</Text>
890
+ <TextInput
891
+ style={styles.input}
892
+ placeholder="Enter name"
893
+ placeholderTextColor="#999999"
894
+ value={name}
895
+ onChangeText={setName}
896
+ />
644
897
 
645
- <View style={styles.buttonGroup}>
646
- <Button title="Pay" onPress={handlePayment} />
898
+ <View style={styles.buttonGroup}>
899
+ <FilledButton
900
+ title="Pay"
901
+ onPress={handlePayment}
902
+ disabled={loading}
903
+ />
647
904
  {Platform.OS === 'ios' && (
648
- <Button title="Payment Ref" onPress={handlePaymentReference} disabled={loading} />
905
+ <FilledButton
906
+ title="Payment Ref"
907
+ onPress={handlePaymentReference}
908
+ disabled={loading}
909
+ />
649
910
  )}
650
911
  </View>
651
912
 
913
+
914
+
915
+
916
+
652
917
  <View style={styles.toggleContainer}>
653
918
  <Text style={styles.label}>Show Configurations</Text>
654
919
  <Switch
@@ -706,6 +971,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
706
971
  }))
707
972
  }
708
973
  placeholder={`Enter ${environment === 'sandbox' ? 'Sandbox' : 'Staging'} API Key`}
974
+ placeholderTextColor="#999999"
709
975
  />
710
976
  <Text style={styles.label}>Secret Key</Text>
711
977
  <View style={styles.inputContainer}>
@@ -719,6 +985,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
719
985
  }))
720
986
  }
721
987
  placeholder={`Enter ${environment === 'sandbox' ? 'Sandbox' : 'Staging'} Secret Key`}
988
+ placeholderTextColor="#999999"
722
989
  secureTextEntry={!showSecretKey}
723
990
  />
724
991
  <TouchableOpacity
@@ -779,22 +1046,45 @@ setResult(JSON.stringify(parsedResponse, null, 2));
779
1046
  thumbColor={isAdditionalVisible ? '#fff' : '#f4f3f4'}
780
1047
  />
781
1048
  </View>
782
- <Text style={styles.label}>Payment Methods (Shared)</Text>
1049
+ <Text style={styles.label}>Payment Methods (Shared)</Text>
1050
+ <Text style={styles.debugText}>
1051
+ Selected: {androidConfig.paymentMethod.join(', ') || 'None'}
1052
+ </Text>
783
1053
  <View style={styles.buttonGroup}>
784
- <Button
1054
+ <FilledButton
785
1055
  title="Card"
786
1056
  onPress={() => togglePaymentMethod('card')}
787
- color={androidConfig.paymentMethod.includes('card') ? '#ccc' :'#2563EB'}
1057
+ disabled={loading}
1058
+ style={[
1059
+ { flex: 1 },
1060
+ androidConfig.paymentMethod.includes('card')
1061
+ ? { backgroundColor: '#2563EB' }
1062
+ : { backgroundColor: '#E5E7EB' }
1063
+ ]}
1064
+ textStyle={androidConfig.paymentMethod.includes('card')
1065
+ ? { color: '#fff' }
1066
+ : { color: '#374151' }
1067
+ }
788
1068
  />
789
- <Button
1069
+ <FilledButton
790
1070
  title="ACH"
791
1071
  onPress={() => togglePaymentMethod('ach')}
792
- color={androidConfig.paymentMethod.includes('ach') ? '#ccc' :'#2563EB' }
1072
+ disabled={loading}
1073
+ style={[
1074
+ { flex: 1 },
1075
+ androidConfig.paymentMethod.includes('ach')
1076
+ ? { backgroundColor: '#2563EB' }
1077
+ : { backgroundColor: '#E5E7EB' }
1078
+ ]}
1079
+ textStyle={androidConfig.paymentMethod.includes('ach')
1080
+ ? { color: '#fff' }
1081
+ : { color: '#374151' }
1082
+ }
793
1083
  />
794
1084
  </View>
795
1085
  {Platform.OS === 'android' && (
796
1086
  <View style={styles.toggleContainer}>
797
- <Text style={styles.label}>Email Editable (Android)</Text>
1087
+ <Text style={styles.label}>Email Editable</Text>
798
1088
  <Switch
799
1089
  value={emailEditable}
800
1090
  onValueChange={setEmailEditable}
@@ -805,7 +1095,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
805
1095
  )}
806
1096
  {Platform.OS === 'ios' && (
807
1097
  <View style={styles.toggleContainer}>
808
- <Text style={styles.label}>Allow Email (iOS)</Text>
1098
+ <Text style={styles.label}>Allow Email Editable</Text>
809
1099
  <Switch
810
1100
  value={isEmail}
811
1101
  onValueChange={setIsEmail}
@@ -816,36 +1106,9 @@ setResult(JSON.stringify(parsedResponse, null, 2));
816
1106
  )}
817
1107
 
818
1108
  <Text style={styles.sectionTitle}>Billing Info</Text>
819
- <Text style={styles.label}>Billing Address</Text>
820
- <TextInput
821
- style={styles.input}
822
- value={billingInfo.billing.address}
823
- onChangeText={value => updateBillingInfo('billing', 'address', value)}
824
- />
825
- <Text style={styles.label}>Billing Country</Text>
826
- <TextInput
827
- style={styles.input}
828
- value={billingInfo.billing.country}
829
- onChangeText={value => updateBillingInfo('billing', 'country', value)}
830
- />
831
- <Text style={styles.label}>Billing State</Text>
832
- <TextInput
833
- style={styles.input}
834
- value={billingInfo.billing.state}
835
- onChangeText={value => updateBillingInfo('billing', 'state', value)}
836
- />
837
- <Text style={styles.label}>Billing City</Text>
838
- <TextInput
839
- style={styles.input}
840
- value={billingInfo.billing.city}
841
- onChangeText={value => updateBillingInfo('billing', 'city', value)}
842
- />
843
- <Text style={styles.label}>Billing Postal Code</Text>
844
- <TextInput
845
- style={styles.input}
846
- value={billingInfo.billing.postal_code}
847
- onChangeText={value => updateBillingInfo('billing', 'postal_code', value)}
848
- />
1109
+
1110
+ {/* Billing Required Switches */}
1111
+ <Text style={styles.subsectionTitle}>Billing Required Fields</Text>
849
1112
  <Text style={styles.label}>Billing Required: Address</Text>
850
1113
  <Switch
851
1114
  value={billingInfo.billingRequired.address}
@@ -863,7 +1126,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
863
1126
  <Text style={styles.label}>Billing Required: State</Text>
864
1127
  <Switch
865
1128
  value={billingInfo.billingRequired.state}
866
- onChangeText={value => updateBillingInfo('billingRequired', 'state', value)}
1129
+ onValueChange={value => updateBillingInfo('billingRequired', 'state', value)}
867
1130
  trackColor={{ false: '#ccc', true: '#2563EB' }}
868
1131
  thumbColor={billingInfo.billingRequired.state ? '#fff' : '#f4f3f4'}
869
1132
  />
@@ -881,30 +1144,123 @@ setResult(JSON.stringify(parsedResponse, null, 2));
881
1144
  trackColor={{ false: '#ccc', true: '#2563EB' }}
882
1145
  thumbColor={billingInfo.billingRequired.postal_code ? '#fff' : '#f4f3f4'}
883
1146
  />
884
- <Text style={styles.label}>Additional: Name</Text>
885
- <TextInput
886
- style={styles.input}
887
- value={billingInfo.additional.name}
888
- onChangeText={value => updateBillingInfo('additional', 'name', value)}
889
- />
890
- <Text style={styles.label}>Additional: Email Address</Text>
891
- <TextInput
892
- style={styles.input}
893
- value={billingInfo.additional.email_address}
894
- onChangeText={value => updateBillingInfo('additional', 'email_address', value)}
895
- />
896
- <Text style={styles.label}>Additional: Phone Number</Text>
897
- <TextInput
898
- style={styles.input}
899
- value={billingInfo.additional.phone_number}
900
- onChangeText={value => updateBillingInfo('additional', 'phone_number', value)}
901
- />
902
- <Text style={styles.label}>Additional: Description</Text>
903
- <TextInput
904
- style={styles.input}
905
- value={billingInfo.additional.description}
906
- onChangeText={value => updateBillingInfo('additional', 'description', value)}
907
- />
1147
+
1148
+ {/* Billing Fields Section */}
1149
+ <Text style={styles.subsectionTitle}>Billing Fields</Text>
1150
+ {billingInfo.billingRequired.address && (
1151
+ <>
1152
+ <Text style={styles.label}>Billing Address</Text>
1153
+ <TextInput
1154
+ style={styles.input}
1155
+ value={billingInfo.billing.address}
1156
+ onChangeText={value => updateBillingInfo('billing', 'address', value)}
1157
+ placeholder="Enter billing address"
1158
+ placeholderTextColor="#999999"
1159
+ />
1160
+ </>
1161
+ )}
1162
+ {billingInfo.billingRequired.country && (
1163
+ <>
1164
+ <Text style={styles.label}>Billing Country</Text>
1165
+ <Dropdown
1166
+ value={billingInfo.billing.country}
1167
+ onValueChange={value => updateBillingInfo('billing', 'country', value)}
1168
+ options={[
1169
+ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
1170
+ "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
1171
+ "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
1172
+ "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus",
1173
+ "Belgium", "Belize", "Benin", "Bermuda", "Bhutan",
1174
+ "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
1175
+ "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi",
1176
+ "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands",
1177
+ "Central African Republic", "Chad", "Chile", "China", "Christmas Island",
1178
+ "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", "Congo, Democratic Republic of the",
1179
+ "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Curaçao",
1180
+ "Cyprus", "Czech Republic", "Côte d'Ivoire", "Denmark", "Djibouti",
1181
+ "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador",
1182
+ "Equatorial Guinea", "Eritrea", "Estonia", "Eswatini", "Ethiopia",
1183
+ "Falkland Islands (Malvinas)", "Faroe Islands", "Fiji", "Finland", "France",
1184
+ "French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia",
1185
+ "Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
1186
+ "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala",
1187
+ "Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti",
1188
+ "Heard Island and McDonald Islands", "Holy See", "Honduras", "Hong Kong", "Hungary",
1189
+ "Iceland", "India", "Indonesia", "Iran", "Iraq",
1190
+ "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica",
1191
+ "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
1192
+ "Kiribati", "Korea (Democratic People's Republic of)", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
1193
+ "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia",
1194
+ "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao",
1195
+ "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali",
1196
+ "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius",
1197
+ "Mayotte", "Mexico", "Micronesia (Federated States of)", "Moldova", "Monaco",
1198
+ "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique",
1199
+ "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands",
1200
+ "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria",
1201
+ "Niue", "Norfolk Island", "North Macedonia", "Northern Mariana Islands", "Norway",
1202
+ "Oman", "Pakistan", "Palau", "Palestine, State of", "Panama",
1203
+ "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn",
1204
+ "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania",
1205
+ "Russian Federation", "Rwanda", "Réunion", "Saint Barthélemy", "Saint Helena, Ascension and Tristan da Cunha",
1206
+ "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin (French part)", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines",
1207
+ "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal",
1208
+ "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten (Dutch part)",
1209
+ "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
1210
+ "South Georgia and the South Sandwich Islands", "South Sudan", "Spain", "Sri Lanka", "Sudan",
1211
+ "Suriname", "Svalbard and Jan Mayen", "Sweden", "Switzerland", "Syrian Arab Republic",
1212
+ "Taiwan, Province of China", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste",
1213
+ "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia",
1214
+ "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine",
1215
+ "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
1216
+ "Vanuatu", "Venezuela", "Viet Nam", "Western Sahara", "Yemen",
1217
+ "Zambia", "Zimbabwe", "Åland Islands"
1218
+ ]}
1219
+ placeholder="Select country"
1220
+ />
1221
+ </>
1222
+ )}
1223
+ {billingInfo.billingRequired.state && (
1224
+ <>
1225
+ <Text style={styles.label}>Billing State</Text>
1226
+ <TextInput
1227
+ style={styles.input}
1228
+ value={billingInfo.billing.state}
1229
+ onChangeText={value => updateBillingInfo('billing', 'state', value)}
1230
+ placeholder="Enter state"
1231
+ placeholderTextColor="#999999"
1232
+ />
1233
+ </>
1234
+ )}
1235
+ {billingInfo.billingRequired.city && (
1236
+ <>
1237
+ <Text style={styles.label}>Billing City</Text>
1238
+ <TextInput
1239
+ style={styles.input}
1240
+ value={billingInfo.billing.city}
1241
+ onChangeText={value => updateBillingInfo('billing', 'city', value)}
1242
+ placeholder="Enter city"
1243
+ placeholderTextColor="#999999"
1244
+ />
1245
+ </>
1246
+ )}
1247
+ {billingInfo.billingRequired.postal_code && (
1248
+ <>
1249
+ <Text style={styles.label}>Billing Postal Code</Text>
1250
+ <TextInput
1251
+ style={styles.input}
1252
+ value={billingInfo.billing.postal_code}
1253
+ onChangeText={value => updateBillingInfo('billing', 'postal_code', value)}
1254
+ placeholder="Enter postal code"
1255
+ placeholderTextColor="#999999"
1256
+ />
1257
+ </>
1258
+ )}
1259
+
1260
+ <Text style={styles.sectionTitle}>Additional Info</Text>
1261
+
1262
+ {/* Additional Required Switches */}
1263
+ <Text style={styles.subsectionTitle}>Additional Required Fields</Text>
908
1264
  <Text style={styles.label}>Additional Required: Name</Text>
909
1265
  <Switch
910
1266
  value={billingInfo.additionalRequired.name}
@@ -934,190 +1290,217 @@ setResult(JSON.stringify(parsedResponse, null, 2));
934
1290
  thumbColor={billingInfo.additionalRequired.description ? '#fff' : '#f4f3f4'}
935
1291
  />
936
1292
 
937
- {/* Android Configuration */}
938
- {Platform.OS === 'android' && (
1293
+ {/* Additional Fields Section */}
1294
+ <Text style={styles.subsectionTitle}>Additional Fields</Text>
1295
+ {billingInfo.additionalRequired.name && (
939
1296
  <>
940
- <Text style={styles.sectionTitle}>Android Configuration</Text>
941
- <Text style={styles.label}>Currency</Text>
1297
+ <Text style={styles.label}>Additional: Name</Text>
942
1298
  <TextInput
943
1299
  style={styles.input}
944
- value={androidConfig.currency}
945
- onChangeText={value => updateAndroidConfig('currency', value)}
946
- />
947
- <Text style={styles.label}>Save Card</Text>
948
- <Switch
949
- value={androidConfig.saveCard}
950
- onValueChange={value => updateAndroidConfig('saveCard', value)}
951
- trackColor={{ false: '#ccc', true: '#2563EB' }}
952
- thumbColor={androidConfig.saveCard ? '#fff' : '#f4f3f4'}
953
- />
954
- <Text style={styles.label}>Save Account</Text>
955
- <Switch
956
- value={androidConfig.saveAccount}
957
- onValueChange={value => updateAndroidConfig('saveAccount', value)}
958
- trackColor={{ false: '#ccc', true: '#2563EB' }}
959
- thumbColor={androidConfig.saveAccount ? '#fff' : '#f4f3f4'}
960
- />
961
- <Text style={styles.label}>Show Receipt</Text>
962
- <Switch
963
- value={androidConfig.showReceipt}
964
- onValueChange={value => updateAndroidConfig('showReceipt', value)}
965
- trackColor={{ false: '#ccc', true: '#2563EB' }}
966
- thumbColor={androidConfig.showReceipt ? '#fff' : '#f4f3f4'}
1300
+ value={billingInfo.additional.name}
1301
+ onChangeText={value => updateBillingInfo('additional', 'name', value)}
1302
+ placeholder="Enter name"
1303
+ placeholderTextColor="#999999"
967
1304
  />
968
- <Text style={styles.label}>Show Donate</Text>
969
- <Switch
970
- value={androidConfig.showDonate}
971
- onValueChange={value => updateAndroidConfig('showDonate', value)}
972
- trackColor={{ false: '#ccc', true: '#2563EB' }}
973
- thumbColor={androidConfig.showDonate ? '#fff' : '#f4f3f4'}
974
- />
975
- <Text style={styles.label}>Show Total</Text>
976
- <Switch
977
- value={androidConfig.showTotal}
978
- onValueChange={value => updateAndroidConfig('showTotal', value)}
979
- trackColor={{ false: '#ccc', true: '#2563EB' }}
980
- thumbColor={androidConfig.showTotal ? '#fff' : '#f4f3f4'}
981
- />
982
- <Text style={styles.label}>Show Submit Button</Text>
983
- <Switch
984
- value={androidConfig.showSubmitButton}
985
- onValueChange={value => updateAndroidConfig('showSubmitButton', value)}
986
- trackColor={{ false: '#ccc', true: '#2563EB' }}
987
- thumbColor={androidConfig.showSubmitButton ? '#fff' : '#f4f3f4'}
988
- />
989
- <Text style={styles.label}>Name</Text>
1305
+ </>
1306
+ )}
1307
+ {billingInfo.additionalRequired.email_address && (
1308
+ <>
1309
+ <Text style={styles.label}>Additional: Email Address</Text>
990
1310
  <TextInput
991
1311
  style={styles.input}
992
- value={androidConfig.name}
993
- onChangeText={value => updateAndroidConfig('name', value)}
1312
+ value={billingInfo.additional.email_address}
1313
+ onChangeText={value => updateBillingInfo('additional', 'email_address', value)}
1314
+ placeholder="Enter email address"
1315
+ placeholderTextColor="#999999"
994
1316
  />
995
- <Text style={styles.sectionTitle}>Android Fields</Text>
996
- {androidConfig.fields.billing.map((field, index) => (
997
- <View key={`billing-${index}`}>
998
- <Text style={styles.label}>{`Billing ${field.name}`}</Text>
999
- <TextInput
1000
- style={styles.input}
1001
- value={field.value}
1002
- onChangeText={value => updateAndroidConfigFields('billing', index, 'value', value)}
1003
- />
1004
- <Text style={styles.label}>{`Billing ${field.name} Required`}</Text>
1005
- <Switch
1006
- value={field.required}
1007
- onValueChange={value => updateAndroidConfigFields('billing', index, 'required', value)}
1008
- trackColor={{ false: '#ccc', true: '#2563EB' }}
1009
- thumbColor={field.required ? '#fff' : '#f4f3f4'}
1010
- />
1011
- </View>
1012
- ))}
1013
- {androidConfig.fields.additional.map((field, index) => (
1014
- <View key={`additional-${index}`}>
1015
- <Text style={styles.label}>{`Additional ${field.name}`}</Text>
1016
- <TextInput
1017
- style={styles.input}
1018
- value={field.value}
1019
- onChangeText={value => updateAndroidConfigFields('additional', index, 'value', value)}
1020
- />
1021
- <Text style={styles.label}>{`Additional ${field.name} Required`}</Text>
1022
- <Switch
1023
- value={field.required}
1024
- onValueChange={value => updateAndroidConfigFields('additional', index, 'required', value)}
1025
- trackColor={{ false: '#ccc', true: '#2563EB' }}
1026
- thumbColor={field.required ? '#fff' : '#f4f3f4'}
1027
- />
1028
- </View>
1029
- ))}
1030
- <Text style={styles.sectionTitle}>Android Appearance Settings</Text>
1031
- <Text style={styles.label}>Theme</Text>
1317
+ </>
1318
+ )}
1319
+ {billingInfo.additionalRequired.phone_number && (
1320
+ <>
1321
+ <Text style={styles.label}>Additional: Phone Number</Text>
1322
+ <View style={styles.phoneRow}>
1323
+ <TextInput
1324
+ style={styles.countryCodeInput}
1325
+ value={billingInfo.additional.country_code || '+1'}
1326
+ onChangeText={value => {
1327
+ // Only allow a '+' at the start, followed by up to 4 digits
1328
+ let filtered = value.replace(/[^+0-9]/g, '');
1329
+ if (!filtered.startsWith('+')) filtered = '+' + filtered.replace(/\+/g, '');
1330
+ filtered = filtered.slice(0, 5);
1331
+ // Update country code and combined phone number
1332
+ const phone = billingInfo.additional.phone_number || '';
1333
+ const phoneOnly = phone.slice((billingInfo.additional.country_code || '+1').replace('+', '').length);
1334
+ const combined = filtered.replace('+', '') + phoneOnly;
1335
+ updateBillingInfo('additional', 'country_code', filtered);
1336
+ updateBillingInfo('additional', 'phone_number', combined);
1337
+ }}
1338
+ placeholder="+1"
1339
+ placeholderTextColor="#999999"
1340
+ keyboardType="phone-pad"
1341
+ maxLength={5}
1342
+ />
1343
+ <TextInput
1344
+ style={[styles.input, { flex: 1, marginBottom: 0 }]}
1345
+ value={(billingInfo.additional.phone_number || '').slice((billingInfo.additional.country_code || '+1').replace('+', '').length)}
1346
+ onChangeText={value => {
1347
+ // Only allow digits and limit to 10 characters
1348
+ const numericValue = value.replace(/[^0-9]/g, '').slice(0, 10);
1349
+ const code = (billingInfo.additional.country_code || '+1').replace('+', '');
1350
+ updateBillingInfo('additional', 'phone_number', code + numericValue);
1351
+ }}
1352
+ placeholder="Enter phone number"
1353
+ placeholderTextColor="#999999"
1354
+ keyboardType="phone-pad"
1355
+ maxLength={10}
1356
+ />
1357
+ </View>
1358
+ </>
1359
+ )}
1360
+ {billingInfo.additionalRequired.description && (
1361
+ <>
1362
+ <Text style={styles.label}>Additional: Description</Text>
1032
1363
  <TextInput
1033
1364
  style={styles.input}
1034
- value={androidConfig.appearanceSettings.theme}
1035
- onChangeText={value => updateAndroidConfigAppearanceSettings('theme', value)}
1365
+ value={billingInfo.additional.description}
1366
+ onChangeText={value => updateBillingInfo('additional', 'description', value)}
1367
+ placeholder="Enter description"
1368
+ placeholderTextColor="#999999"
1036
1369
  />
1370
+ </>
1371
+ )}
1372
+
1373
+ {/* Android Appearance Settings */}
1374
+ {Platform.OS === 'android' && (
1375
+ <>
1376
+ <Text style={styles.sectionTitle}>Android Appearance Settings</Text>
1037
1377
  <Text style={styles.label}>Body Background Color</Text>
1038
- <TextInput
1039
- style={styles.input}
1040
- value={androidConfig.appearanceSettings.bodyBackgroundColor}
1041
- onChangeText={value => updateAndroidConfigAppearanceSettings('bodyBackgroundColor', value)}
1042
- />
1378
+ <View style={styles.colorInputContainer}>
1379
+ <TextInput
1380
+ style={[styles.input, { flex: 1 }]}
1381
+ value={androidConfig.appearanceSettings.bodyBackgroundColor}
1382
+ onChangeText={value => updateAndroidConfigAppearanceSettings('bodyBackgroundColor', value)}
1383
+ placeholder="Enter body background color"
1384
+ placeholderTextColor="#999999"
1385
+ />
1386
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.bodyBackgroundColor }]} />
1387
+ </View>
1043
1388
  <Text style={styles.label}>Container Background Color</Text>
1044
- <TextInput
1045
- style={styles.input}
1046
- value={androidConfig.appearanceSettings.containerBackgroundColor}
1047
- onChangeText={value => updateAndroidConfigAppearanceSettings('containerBackgroundColor', value)}
1048
- />
1389
+ <View style={styles.colorInputContainer}>
1390
+ <TextInput
1391
+ style={[styles.input, { flex: 1 }]}
1392
+ value={androidConfig.appearanceSettings.containerBackgroundColor}
1393
+ onChangeText={value => updateAndroidConfigAppearanceSettings('containerBackgroundColor', value)}
1394
+ placeholder="Enter container background color"
1395
+ placeholderTextColor="#999999"
1396
+ />
1397
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.containerBackgroundColor }]} />
1398
+ </View>
1049
1399
  <Text style={styles.label}>Primary Font Color</Text>
1050
- <TextInput
1051
- style={styles.input}
1052
- value={androidConfig.appearanceSettings.primaryFontColor}
1053
- onChangeText={value => updateAndroidConfigAppearanceSettings('primaryFontColor', value)}
1054
- />
1400
+ <View style={styles.colorInputContainer}>
1401
+ <TextInput
1402
+ style={[styles.input, { flex: 1 }]}
1403
+ value={androidConfig.appearanceSettings.primaryFontColor}
1404
+ onChangeText={value => updateAndroidConfigAppearanceSettings('primaryFontColor', value)}
1405
+ placeholder="Enter primary font color"
1406
+ placeholderTextColor="#999999"
1407
+ />
1408
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryFontColor }]} />
1409
+ </View>
1055
1410
  <Text style={styles.label}>Secondary Font Color</Text>
1056
- <TextInput
1057
- style={styles.input}
1058
- value={androidConfig.appearanceSettings.secondaryFontColor}
1059
- onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryFontColor', value)}
1060
- />
1411
+ <View style={styles.colorInputContainer}>
1412
+ <TextInput
1413
+ style={[styles.input, { flex: 1 }]}
1414
+ value={androidConfig.appearanceSettings.secondaryFontColor}
1415
+ onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryFontColor', value)}
1416
+ placeholder="Enter secondary font color"
1417
+ placeholderTextColor="#999999"
1418
+ />
1419
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryFontColor }]} />
1420
+ </View>
1061
1421
  <Text style={styles.label}>Primary Button Background Color</Text>
1062
- <TextInput
1063
- style={styles.input}
1064
- value={androidConfig.appearanceSettings.primaryButtonBackgroundColor}
1065
- onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonBackgroundColor', value)}
1066
- />
1422
+ <View style={styles.colorInputContainer}>
1423
+ <TextInput
1424
+ style={[styles.input, { flex: 1 }]}
1425
+ value={androidConfig.appearanceSettings.primaryButtonBackgroundColor}
1426
+ onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonBackgroundColor', value)}
1427
+ placeholder="Enter primary button background color"
1428
+ placeholderTextColor="#999999"
1429
+ />
1430
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonBackgroundColor }]} />
1431
+ </View>
1067
1432
  <Text style={styles.label}>Primary Button Hover Color</Text>
1068
- <TextInput
1069
- style={styles.input}
1070
- value={androidConfig.appearanceSettings.primaryButtonHoverColor}
1071
- onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonHoverColor', value)}
1072
- />
1433
+ <View style={styles.colorInputContainer}>
1434
+ <TextInput
1435
+ style={[styles.input, { flex: 1 }]}
1436
+ value={androidConfig.appearanceSettings.primaryButtonHoverColor}
1437
+ onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonHoverColor', value)}
1438
+ placeholder="Enter primary button hover color"
1439
+ placeholderTextColor="#999999"
1440
+ />
1441
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonHoverColor }]} />
1442
+ </View>
1073
1443
  <Text style={styles.label}>Primary Button Font Color</Text>
1074
- <TextInput
1075
- style={styles.input}
1076
- value={androidConfig.appearanceSettings.primaryButtonFontColor}
1077
- onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonFontColor', value)}
1078
- />
1444
+ <View style={styles.colorInputContainer}>
1445
+ <TextInput
1446
+ style={[styles.input, { flex: 1 }]}
1447
+ value={androidConfig.appearanceSettings.primaryButtonFontColor}
1448
+ onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonFontColor', value)}
1449
+ placeholder="Enter primary button font color"
1450
+ placeholderTextColor="#999999"
1451
+ />
1452
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonFontColor }]} />
1453
+ </View>
1079
1454
  <Text style={styles.label}>Secondary Button Background Color</Text>
1080
- <TextInput
1081
- style={styles.input}
1082
- value={androidConfig.appearanceSettings.secondaryButtonBackgroundColor}
1083
- onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonBackgroundColor', value)}
1084
- />
1455
+ <View style={styles.colorInputContainer}>
1456
+ <TextInput
1457
+ style={[styles.input, { flex: 1 }]}
1458
+ value={androidConfig.appearanceSettings.secondaryButtonBackgroundColor}
1459
+ onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonBackgroundColor', value)}
1460
+ placeholder="Enter secondary button background color"
1461
+ placeholderTextColor="#999999"
1462
+ />
1463
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonBackgroundColor }]} />
1464
+ </View>
1085
1465
  <Text style={styles.label}>Secondary Button Hover Color</Text>
1086
- <TextInput
1087
- style={styles.input}
1088
- value={androidConfig.appearanceSettings.secondaryButtonHoverColor}
1089
- onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonHoverColor', value)}
1090
- />
1466
+ <View style={styles.colorInputContainer}>
1467
+ <TextInput
1468
+ style={[styles.input, { flex: 1 }]}
1469
+ value={androidConfig.appearanceSettings.secondaryButtonHoverColor}
1470
+ onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonHoverColor', value)}
1471
+ placeholder="Enter secondary button hover color"
1472
+ placeholderTextColor="#999999"
1473
+ />
1474
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonHoverColor }]} />
1475
+ </View>
1091
1476
  <Text style={styles.label}>Secondary Button Font Color</Text>
1092
- <TextInput
1093
- style={styles.input}
1094
- value={androidConfig.appearanceSettings.secondaryButtonFontColor}
1095
- onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonFontColor', value)}
1096
- />
1477
+ <View style={styles.colorInputContainer}>
1478
+ <TextInput
1479
+ style={[styles.input, { flex: 1 }]}
1480
+ value={androidConfig.appearanceSettings.secondaryButtonFontColor}
1481
+ onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonFontColor', value)}
1482
+ placeholder="Enter secondary button font color"
1483
+ placeholderTextColor="#999999"
1484
+ />
1485
+ <View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonFontColor }]} />
1486
+ </View>
1097
1487
  <Text style={styles.label}>Border Radius</Text>
1098
1488
  <TextInput
1099
1489
  style={styles.input}
1100
1490
  value={androidConfig.appearanceSettings.borderRadius}
1101
1491
  onChangeText={value => updateAndroidConfigAppearanceSettings('borderRadius', value)}
1492
+ placeholder="Enter border radius"
1493
+ placeholderTextColor="#999999"
1102
1494
  />
1103
1495
  <Text style={styles.label}>Font Size</Text>
1104
1496
  <TextInput
1105
1497
  style={styles.input}
1106
1498
  value={androidConfig.appearanceSettings.fontSize}
1107
1499
  onChangeText={value => updateAndroidConfigAppearanceSettings('fontSize', value)}
1500
+ placeholder="Enter font size"
1501
+ placeholderTextColor="#999999"
1108
1502
  />
1109
- <Text style={styles.label}>Font Weight</Text>
1110
- <TextInput
1111
- style={styles.input}
1112
- value={String(androidConfig.appearanceSettings.fontWeight)}
1113
- onChangeText={value => updateAndroidConfigAppearanceSettings('fontWeight', parseInt(value) || '500')}
1114
- />
1115
- <Text style={styles.label}>Font Family</Text>
1116
- <TextInput
1117
- style={styles.input}
1118
- value={androidConfig.appearanceSettings.fontFamily}
1119
- onChangeText={value => updateAndroidConfigAppearanceSettings('fontFamily', value)}
1120
- />
1503
+
1121
1504
  </>
1122
1505
  )}
1123
1506
 
@@ -1126,89 +1509,132 @@ setResult(JSON.stringify(parsedResponse, null, 2));
1126
1509
  <>
1127
1510
  <Text style={styles.sectionTitle}>Theme Configuration (iOS)</Text>
1128
1511
  <Text style={styles.label}>Body Background Color</Text>
1129
- <TextInput
1130
- style={styles.input}
1131
- value={themeConfiguration.bodyBackgroundColor}
1132
- onChangeText={value => updateThemeConfiguration('bodyBackgroundColor', value)}
1133
- />
1512
+ <View style={styles.colorInputContainer}>
1513
+ <TextInput
1514
+ style={[styles.input, { flex: 1 }]}
1515
+ value={themeConfiguration.bodyBackgroundColor}
1516
+ onChangeText={value => updateThemeConfiguration('bodyBackgroundColor', value)}
1517
+ placeholder="Enter body background color"
1518
+ placeholderTextColor="#999999"
1519
+ />
1520
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.bodyBackgroundColor }]} />
1521
+ </View>
1134
1522
  <Text style={styles.label}>Container Background Color</Text>
1135
- <TextInput
1136
- style={styles.input}
1137
- value={themeConfiguration.containerBackgroundColor}
1138
- onChangeText={value => updateThemeConfiguration('containerBackgroundColor', value)}
1139
- />
1523
+ <View style={styles.colorInputContainer}>
1524
+ <TextInput
1525
+ style={[styles.input, { flex: 1 }]}
1526
+ value={themeConfiguration.containerBackgroundColor}
1527
+ onChangeText={value => updateThemeConfiguration('containerBackgroundColor', value)}
1528
+ placeholder="Enter container background color"
1529
+ placeholderTextColor="#999999"
1530
+ />
1531
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.containerBackgroundColor }]} />
1532
+ </View>
1140
1533
  <Text style={styles.label}>Primary Font Color</Text>
1141
- <TextInput
1142
- style={styles.input}
1143
- value={themeConfiguration.primaryFontColor}
1144
- onChangeText={value => updateThemeConfiguration('primaryFontColor', value)}
1145
- />
1534
+ <View style={styles.colorInputContainer}>
1535
+ <TextInput
1536
+ style={[styles.input, { flex: 1 }]}
1537
+ value={themeConfiguration.primaryFontColor}
1538
+ onChangeText={value => updateThemeConfiguration('primaryFontColor', value)}
1539
+ placeholder="Enter primary font color"
1540
+ placeholderTextColor="#999999"
1541
+ />
1542
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryFontColor }]} />
1543
+ </View>
1146
1544
  <Text style={styles.label}>Secondary Font Color</Text>
1147
- <TextInput
1148
- style={styles.input}
1149
- value={themeConfiguration.secondaryFontColor}
1150
- onChangeText={value => updateThemeConfiguration('secondaryFontColor', value)}
1151
- />
1545
+ <View style={styles.colorInputContainer}>
1546
+ <TextInput
1547
+ style={[styles.input, { flex: 1 }]}
1548
+ value={themeConfiguration.secondaryFontColor}
1549
+ onChangeText={value => updateThemeConfiguration('secondaryFontColor', value)}
1550
+ placeholder="Enter secondary font color"
1551
+ placeholderTextColor="#999999"
1552
+ />
1553
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryFontColor }]} />
1554
+ </View>
1152
1555
  <Text style={styles.label}>Primary Button Background Color</Text>
1153
- <TextInput
1154
- style={styles.input}
1155
- value={themeConfiguration.primaryButtonBackgroundColor}
1156
- onChangeText={value => updateThemeConfiguration('primaryButtonBackgroundColor', value)}
1157
- />
1556
+ <View style={styles.colorInputContainer}>
1557
+ <TextInput
1558
+ style={[styles.input, { flex: 1 }]}
1559
+ value={themeConfiguration.primaryButtonBackgroundColor}
1560
+ onChangeText={value => updateThemeConfiguration('primaryButtonBackgroundColor', value)}
1561
+ placeholder="Enter primary button background color"
1562
+ placeholderTextColor="#999999"
1563
+ />
1564
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonBackgroundColor }]} />
1565
+ </View>
1158
1566
  <Text style={styles.label}>Primary Button Hover Color</Text>
1159
- <TextInput
1160
- style={styles.input}
1161
- value={themeConfiguration.primaryButtonHoverColor}
1162
- onChangeText={value => updateThemeConfiguration('primaryButtonHoverColor', value)}
1163
- />
1567
+ <View style={styles.colorInputContainer}>
1568
+ <TextInput
1569
+ style={[styles.input, { flex: 1 }]}
1570
+ value={themeConfiguration.primaryButtonHoverColor}
1571
+ onChangeText={value => updateThemeConfiguration('primaryButtonHoverColor', value)}
1572
+ placeholder="Enter primary button hover color"
1573
+ placeholderTextColor="#999999"
1574
+ />
1575
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonHoverColor }]} />
1576
+ </View>
1164
1577
  <Text style={styles.label}>Primary Button Font Color</Text>
1165
- <TextInput
1166
- style={styles.input}
1167
- value={themeConfiguration.primaryButtonFontColor}
1168
- onChangeText={value => updateThemeConfiguration('primaryButtonFontColor', value)}
1169
- />
1578
+ <View style={styles.colorInputContainer}>
1579
+ <TextInput
1580
+ style={[styles.input, { flex: 1 }]}
1581
+ value={themeConfiguration.primaryButtonFontColor}
1582
+ onChangeText={value => updateThemeConfiguration('primaryButtonFontColor', value)}
1583
+ placeholder="Enter primary button font color"
1584
+ placeholderTextColor="#999999"
1585
+ />
1586
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonFontColor }]} />
1587
+ </View>
1170
1588
  <Text style={styles.label}>Secondary Button Background Color</Text>
1171
- <TextInput
1172
- style={styles.input}
1173
- value={themeConfiguration.secondaryButtonBackgroundColor}
1174
- onChangeText={value => updateThemeConfiguration('secondaryButtonBackgroundColor', value)}
1175
- />
1589
+ <View style={styles.colorInputContainer}>
1590
+ <TextInput
1591
+ style={[styles.input, { flex: 1 }]}
1592
+ value={themeConfiguration.secondaryButtonBackgroundColor}
1593
+ onChangeText={value => updateThemeConfiguration('secondaryButtonBackgroundColor', value)}
1594
+ placeholder="Enter secondary button background color"
1595
+ placeholderTextColor="#999999"
1596
+ />
1597
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonBackgroundColor }]} />
1598
+ </View>
1176
1599
  <Text style={styles.label}>Secondary Button Hover Color</Text>
1177
- <TextInput
1178
- style={styles.input}
1179
- value={themeConfiguration.secondaryButtonHoverColor}
1180
- onChangeText={value => updateThemeConfiguration('secondaryButtonHoverColor', value)}
1181
- />
1600
+ <View style={styles.colorInputContainer}>
1601
+ <TextInput
1602
+ style={[styles.input, { flex: 1 }]}
1603
+ value={themeConfiguration.secondaryButtonHoverColor}
1604
+ onChangeText={value => updateThemeConfiguration('secondaryButtonHoverColor', value)}
1605
+ placeholder="Enter secondary button hover color"
1606
+ placeholderTextColor="#999999"
1607
+ />
1608
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonHoverColor }]} />
1609
+ </View>
1182
1610
  <Text style={styles.label}>Secondary Button Font Color</Text>
1183
- <TextInput
1184
- style={styles.input}
1185
- value={themeConfiguration.secondaryButtonFontColor}
1186
- onChangeText={value => updateThemeConfiguration('secondaryButtonFontColor', value)}
1187
- />
1611
+ <View style={styles.colorInputContainer}>
1612
+ <TextInput
1613
+ style={[styles.input, { flex: 1 }]}
1614
+ value={themeConfiguration.secondaryButtonFontColor}
1615
+ onChangeText={value => updateThemeConfiguration('secondaryButtonFontColor', value)}
1616
+ placeholder="Enter secondary button font color"
1617
+ placeholderTextColor="#999999"
1618
+ />
1619
+ <View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonFontColor }]} />
1620
+ </View>
1188
1621
  <Text style={styles.label}>Border Radius</Text>
1189
1622
  <TextInput
1190
1623
  style={styles.input}
1191
1624
  value={themeConfiguration.borderRadius}
1192
1625
  onChangeText={value => updateThemeConfiguration('borderRadius', value)}
1626
+ placeholder="Enter border radius"
1627
+ placeholderTextColor="#999999"
1193
1628
  />
1194
1629
  <Text style={styles.label}>Font Size</Text>
1195
1630
  <TextInput
1196
1631
  style={styles.input}
1197
1632
  value={themeConfiguration.fontSize}
1198
1633
  onChangeText={value => updateThemeConfiguration('fontSize', value)}
1634
+ placeholder="Enter font size"
1635
+ placeholderTextColor="#999999"
1199
1636
  />
1200
- <Text style={styles.label}>Font Weight</Text>
1201
- <TextInput
1202
- style={styles.input}
1203
- value={String(themeConfiguration.fontWeight)}
1204
- onChangeText={value => updateThemeConfiguration('fontWeight', parseInt(value) || 500)}
1205
- />
1206
- <Text style={styles.label}>Font Family</Text>
1207
- <TextInput
1208
- style={styles.input}
1209
- value={themeConfiguration.fontFamily}
1210
- onChangeText={value => updateThemeConfiguration('fontFamily', value)}
1211
- />
1637
+
1212
1638
  </>
1213
1639
  )}
1214
1640
 
@@ -1219,12 +1645,16 @@ setResult(JSON.stringify(parsedResponse, null, 2));
1219
1645
  style={styles.input}
1220
1646
  value={grailPayParams.role}
1221
1647
  onChangeText={value => updateGrailPayParams('role', value)}
1648
+ placeholder="Enter role"
1649
+ placeholderTextColor="#999999"
1222
1650
  />
1223
1651
  <Text style={styles.label}>Timeout</Text>
1224
1652
  <TextInput
1225
1653
  style={styles.input}
1226
1654
  value={String(grailPayParams.timeout)}
1227
1655
  onChangeText={value => updateGrailPayParams('timeout', parseInt(value) || 10)}
1656
+ placeholder="Enter timeout"
1657
+ placeholderTextColor="#999999"
1228
1658
  />
1229
1659
  <Text style={styles.label}>Is Sandbox</Text>
1230
1660
  <Switch
@@ -1238,52 +1668,106 @@ setResult(JSON.stringify(parsedResponse, null, 2));
1238
1668
  style={styles.input}
1239
1669
  value={grailPayParams.brandingName}
1240
1670
  onChangeText={value => updateGrailPayParams('brandingName', value)}
1671
+ placeholder="Enter branding name"
1672
+ placeholderTextColor="#999999"
1241
1673
  />
1242
1674
  <Text style={styles.label}>Finder Subtitle</Text>
1243
1675
  <TextInput
1244
1676
  style={styles.input}
1245
1677
  value={grailPayParams.finderSubtitle}
1246
1678
  onChangeText={value => updateGrailPayParams('finderSubtitle', value)}
1679
+ placeholder="Enter finder subtitle"
1680
+ placeholderTextColor="#999999"
1247
1681
  />
1248
1682
  <Text style={styles.label}>Search Placeholder</Text>
1249
1683
  <TextInput
1250
1684
  style={styles.input}
1251
1685
  value={grailPayParams.searchPlaceholder}
1252
1686
  onChangeText={value => updateGrailPayParams('searchPlaceholder', value)}
1687
+ placeholder="Enter search placeholder"
1688
+ placeholderTextColor="#999999"
1253
1689
  />
1254
1690
 
1255
1691
  {/* Recurring Data */}
1256
1692
  <Text style={styles.sectionTitle}>Recurring Data</Text>
1257
- <Text style={styles.label}>Allow Cycles</Text>
1693
+ <Text style={styles.label}>Allow Cycles (Minimum 2)</Text>
1258
1694
  <TextInput
1259
1695
  style={styles.input}
1260
1696
  value={String(recurringData.allowCycles)}
1261
1697
  onChangeText={value => updateRecurringData('allowCycles', parseInt(value) || 2)}
1698
+ placeholder="Enter allowed cycles"
1699
+ placeholderTextColor="#999999"
1262
1700
  />
1263
- <Text style={styles.label}>Intervals</Text>
1701
+ <Text style={styles.label}>Intervals</Text>
1264
1702
  <View style={styles.buttonGroup}>
1265
- <Button
1703
+ <FilledButton
1704
+ title="Daily"
1705
+ onPress={() => toggleInterval('daily')}
1706
+ disabled={loading}
1707
+ style={[
1708
+ { flex: 1 },
1709
+ recurringData.intervals.includes('daily')
1710
+ ? { backgroundColor: '#2563EB' }
1711
+ : { backgroundColor: '#E5E7EB' }
1712
+ ]}
1713
+ textStyle={[
1714
+ { fontSize: 14 },
1715
+ recurringData.intervals.includes('daily')
1716
+ ? { color: '#fff' }
1717
+ : { color: '#374151' }
1718
+ ]}
1719
+ />
1720
+ <FilledButton
1266
1721
  title="Weekly"
1267
1722
  onPress={() => toggleInterval('weekly')}
1268
- color={recurringData.intervals.includes('weekly') ? '#2563EB' : '#ccc'}
1723
+ disabled={loading}
1724
+ style={[
1725
+ { flex: 1 },
1726
+ recurringData.intervals.includes('weekly')
1727
+ ? { backgroundColor: '#2563EB' }
1728
+ : { backgroundColor: '#E5E7EB' }
1729
+ ]}
1730
+ textStyle={[
1731
+ { fontSize: 14 },
1732
+ recurringData.intervals.includes('weekly')
1733
+ ? { color: '#fff' }
1734
+ : { color: '#374151' }
1735
+ ]}
1269
1736
  />
1270
- <Button
1737
+ <FilledButton
1271
1738
  title="Monthly"
1272
1739
  onPress={() => toggleInterval('monthly')}
1273
- color={recurringData.intervals.includes('monthly') ? '#2563EB' : '#ccc'}
1740
+ disabled={loading}
1741
+ style={[
1742
+ { flex: 1 },
1743
+ recurringData.intervals.includes('monthly')
1744
+ ? { backgroundColor: '#2563EB' }
1745
+ : { backgroundColor: '#E5E7EB' }
1746
+ ]}
1747
+ textStyle={[
1748
+ { fontSize: 14 },
1749
+ recurringData.intervals.includes('monthly')
1750
+ ? { color: '#fff' }
1751
+ : { color: '#374151' }
1752
+ ]}
1274
1753
  />
1275
1754
  </View>
1276
1755
  <Text style={styles.label}>Recurring Start Type</Text>
1277
- <TextInput
1278
- style={styles.input}
1756
+ <Dropdown
1279
1757
  value={recurringData.recurringStartType}
1280
- onChangeText={value => updateRecurringData('recurringStartType', value)}
1758
+ onValueChange={value => updateRecurringData('recurringStartType', value)}
1759
+ options={Platform.OS === 'android' ? ['Custom', 'Fixed'] : ['custom', 'fixed']}
1760
+ placeholder="Select start type"
1281
1761
  />
1282
1762
  <Text style={styles.label}>Recurring Start Date</Text>
1283
1763
  <TextInput
1284
- style={styles.input}
1764
+ style={[styles.input, styles.dateInput]}
1285
1765
  value={recurringData.recurringStartDate}
1286
1766
  onChangeText={value => updateRecurringData('recurringStartDate', value)}
1767
+ placeholder="MM/DD/YYYY"
1768
+ placeholderTextColor="#999999"
1769
+ returnKeyType="done"
1770
+ onSubmitEditing={() => Keyboard.dismiss()}
1287
1771
  />
1288
1772
  </>
1289
1773
  )}
@@ -1291,7 +1775,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
1291
1775
  <Text style={styles.sectionTitle}>SDK Response</Text>
1292
1776
  <Text selectable style={styles.result}>{result || 'No response yet'}</Text>
1293
1777
  </ScrollView>
1294
- </View>
1778
+ </KeyboardAvoidingView>
1295
1779
  );
1296
1780
 
1297
1781
  };
@@ -1314,6 +1798,13 @@ const styles = StyleSheet.create({
1314
1798
  marginTop: 20,
1315
1799
  marginBottom: 10,
1316
1800
  },
1801
+ subsectionTitle: {
1802
+ fontSize: 16,
1803
+ fontWeight: '600',
1804
+ marginTop: 15,
1805
+ marginBottom: 8,
1806
+ color: '#374151',
1807
+ },
1317
1808
  input: {
1318
1809
  height: 40,
1319
1810
  borderColor: '#ccc',
@@ -1321,6 +1812,19 @@ const styles = StyleSheet.create({
1321
1812
  borderRadius: 5,
1322
1813
  paddingHorizontal: 10,
1323
1814
  marginBottom: 10,
1815
+ backgroundColor: '#FFFFFF',
1816
+ color: '#000000',
1817
+ },
1818
+ dateInput: {
1819
+ backgroundColor: '#fff',
1820
+ shadowColor: '#000',
1821
+ shadowOffset: {
1822
+ width: 0,
1823
+ height: 1,
1824
+ },
1825
+ shadowOpacity: 0.1,
1826
+ shadowRadius: 2,
1827
+ elevation: 2,
1324
1828
  },
1325
1829
  pickerContainer: {
1326
1830
  marginBottom: 20,
@@ -1379,6 +1883,127 @@ const styles = StyleSheet.create({
1379
1883
  fontSize: 20,
1380
1884
  color: '#333',
1381
1885
  },
1886
+ // New styles for FilledButton
1887
+ filledButton: {
1888
+ flex: 1,
1889
+ paddingVertical: 10,
1890
+ paddingHorizontal: 20,
1891
+ borderRadius: 5,
1892
+ marginHorizontal: 5,
1893
+ alignItems: 'center',
1894
+ justifyContent: 'center',
1895
+ backgroundColor: '#2563EB', // Primary color for filled buttons
1896
+ },
1897
+ filledButtonDisabled: {
1898
+ backgroundColor: '#ccc',
1899
+ opacity: 0.7,
1900
+ },
1901
+ filledButtonText: {
1902
+ color: '#fff',
1903
+ fontSize: 16,
1904
+ fontWeight: '500',
1905
+ },
1906
+ filledButtonTextDisabled: {
1907
+ color: '#888',
1908
+ },
1909
+ debugText: {
1910
+ fontSize: 12,
1911
+ color: '#666',
1912
+ fontStyle: 'italic',
1913
+ marginBottom: 5,
1914
+ },
1915
+ // Dropdown Styles
1916
+ dropdownContainer: {
1917
+ position: 'relative',
1918
+ marginBottom: 20,
1919
+ zIndex: 9998,
1920
+ },
1921
+ dropdownButton: {
1922
+ height: 40,
1923
+ borderColor: '#ccc',
1924
+ borderWidth: 1,
1925
+ borderRadius: 5,
1926
+ paddingHorizontal: 10,
1927
+ flexDirection: 'row',
1928
+ justifyContent: 'space-between',
1929
+ alignItems: 'center',
1930
+ backgroundColor: '#fff',
1931
+ },
1932
+ dropdownButtonText: {
1933
+ fontSize: 16,
1934
+ color: '#333',
1935
+ },
1936
+ dropdownArrow: {
1937
+ fontSize: 12,
1938
+ color: '#666',
1939
+ },
1940
+ dropdownOptions: {
1941
+ position: 'absolute',
1942
+ top: 45,
1943
+ left: 0,
1944
+ right: 0,
1945
+ backgroundColor: '#fff',
1946
+ borderColor: '#ccc',
1947
+ borderWidth: 1,
1948
+ borderRadius: 5,
1949
+ zIndex: 9999,
1950
+ maxHeight: 200,
1951
+ elevation: 5,
1952
+ shadowColor: '#000',
1953
+ shadowOffset: {
1954
+ width: 0,
1955
+ height: 2,
1956
+ },
1957
+ shadowOpacity: 0.25,
1958
+ shadowRadius: 3.84,
1959
+ },
1960
+ dropdownScrollView: {
1961
+ maxHeight: 180,
1962
+ },
1963
+ dropdownOption: {
1964
+ paddingVertical: 12,
1965
+ paddingHorizontal: 15,
1966
+ borderBottomWidth: 1,
1967
+ borderBottomColor: '#f0f0f0',
1968
+ backgroundColor: '#fff',
1969
+ },
1970
+ dropdownOptionText: {
1971
+ fontSize: 16,
1972
+ color: '#333',
1973
+ },
1974
+ // Color preview styles
1975
+ colorInputContainer: {
1976
+ flexDirection: 'row',
1977
+ alignItems: 'center',
1978
+ marginBottom: 10,
1979
+ gap: 10,
1980
+ },
1981
+ colorPreview: {
1982
+ width: 30,
1983
+ height: 30,
1984
+ borderRadius: 4,
1985
+ borderWidth: 1,
1986
+ borderColor: '#ccc',
1987
+ },
1988
+ phoneRow: {
1989
+ flexDirection: 'row',
1990
+ alignItems: 'center',
1991
+ marginBottom: 10,
1992
+ gap: 8,
1993
+ },
1994
+ countryCodeInput: {
1995
+ width: 70,
1996
+ height: 40,
1997
+ borderColor: '#ccc',
1998
+ borderWidth: 1,
1999
+ borderRadius: 5,
2000
+ paddingHorizontal: 10,
2001
+ backgroundColor: '#FFFFFF',
2002
+ color: '#000000',
2003
+ textAlign: 'center',
2004
+ alignSelf: 'stretch',
2005
+ marginBottom: 0,
2006
+ },
1382
2007
  });
1383
2008
 
1384
2009
  ```