react-native-inapp-inspector 2.3.15 → 2.3.16

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 (96) hide show
  1. package/README.md +1 -0
  2. package/dist/commonjs/components/Inspector/AnalyticsTab.js +0 -22
  3. package/dist/commonjs/components/Inspector/ConsoleTab.js +0 -22
  4. package/dist/commonjs/components/Inspector/CrashTab.js +0 -23
  5. package/dist/commonjs/components/Inspector/FeedbackModal.d.ts +7 -0
  6. package/dist/commonjs/components/Inspector/FeedbackModal.js +552 -0
  7. package/dist/commonjs/components/Inspector/InspectorHeader.js +56 -4
  8. package/dist/commonjs/components/Inspector/MainScreen.js +45 -3
  9. package/dist/commonjs/components/Inspector/NetworkTab.js +27 -38
  10. package/dist/commonjs/components/Inspector/NpmStarPrompt.d.ts +3 -0
  11. package/dist/commonjs/components/Inspector/NpmStarPrompt.js +494 -0
  12. package/dist/commonjs/components/Inspector/PerformanceTab.js +8 -1
  13. package/dist/commonjs/components/Inspector/ReduxTab.js +0 -22
  14. package/dist/commonjs/components/Inspector/SettingsPanel.js +1035 -173
  15. package/dist/commonjs/components/Inspector/StorageTab.js +0 -23
  16. package/dist/commonjs/components/Inspector/TabBar.js +50 -15
  17. package/dist/commonjs/components/NetworkIcons.d.ts +5 -0
  18. package/dist/commonjs/components/NetworkIcons.js +33 -2
  19. package/dist/commonjs/constants/version.d.ts +1 -1
  20. package/dist/commonjs/constants/version.js +1 -1
  21. package/dist/commonjs/helpers/index.d.ts +1 -0
  22. package/dist/commonjs/helpers/index.js +1 -0
  23. package/dist/commonjs/helpers/remoteConfig.d.ts +4 -0
  24. package/dist/commonjs/helpers/remoteConfig.js +165 -0
  25. package/dist/commonjs/helpers/searchQueryParser.js +2 -0
  26. package/dist/commonjs/helpers/telemetry.d.ts +5 -0
  27. package/dist/commonjs/helpers/telemetry.js +339 -8
  28. package/dist/commonjs/index.d.ts +1 -0
  29. package/dist/commonjs/index.js +32 -2
  30. package/dist/commonjs/styles/AppFonts.d.ts +2 -0
  31. package/dist/commonjs/styles/AppFonts.js +1 -0
  32. package/dist/commonjs/styles/index.d.ts +22 -0
  33. package/dist/commonjs/styles/index.js +19 -0
  34. package/dist/commonjs/types/enums.d.ts +1 -0
  35. package/dist/commonjs/types/enums.js +1 -0
  36. package/dist/commonjs/types/interfaces.d.ts +12 -0
  37. package/dist/esm/components/Inspector/AnalyticsTab.js +1 -23
  38. package/dist/esm/components/Inspector/ConsoleTab.js +1 -23
  39. package/dist/esm/components/Inspector/CrashTab.js +1 -24
  40. package/dist/esm/components/Inspector/FeedbackModal.d.ts +7 -0
  41. package/dist/esm/components/Inspector/FeedbackModal.js +515 -0
  42. package/dist/esm/components/Inspector/InspectorHeader.js +57 -5
  43. package/dist/esm/components/Inspector/MainScreen.js +46 -4
  44. package/dist/esm/components/Inspector/NetworkTab.js +28 -39
  45. package/dist/esm/components/Inspector/NpmStarPrompt.d.ts +3 -0
  46. package/dist/esm/components/Inspector/NpmStarPrompt.js +454 -0
  47. package/dist/esm/components/Inspector/PerformanceTab.js +8 -1
  48. package/dist/esm/components/Inspector/ReduxTab.js +1 -23
  49. package/dist/esm/components/Inspector/SettingsPanel.js +1038 -176
  50. package/dist/esm/components/Inspector/StorageTab.js +0 -23
  51. package/dist/esm/components/Inspector/TabBar.js +50 -15
  52. package/dist/esm/components/NetworkIcons.d.ts +5 -0
  53. package/dist/esm/components/NetworkIcons.js +26 -0
  54. package/dist/esm/constants/version.d.ts +1 -1
  55. package/dist/esm/constants/version.js +1 -1
  56. package/dist/esm/helpers/index.d.ts +1 -0
  57. package/dist/esm/helpers/index.js +1 -0
  58. package/dist/esm/helpers/remoteConfig.d.ts +4 -0
  59. package/dist/esm/helpers/remoteConfig.js +160 -0
  60. package/dist/esm/helpers/searchQueryParser.js +2 -0
  61. package/dist/esm/helpers/telemetry.d.ts +5 -0
  62. package/dist/esm/helpers/telemetry.js +332 -9
  63. package/dist/esm/index.d.ts +1 -0
  64. package/dist/esm/index.js +30 -2
  65. package/dist/esm/styles/AppFonts.d.ts +2 -0
  66. package/dist/esm/styles/AppFonts.js +1 -0
  67. package/dist/esm/styles/index.d.ts +22 -0
  68. package/dist/esm/styles/index.js +19 -0
  69. package/dist/esm/types/enums.d.ts +1 -0
  70. package/dist/esm/types/enums.js +1 -0
  71. package/dist/esm/types/interfaces.d.ts +12 -0
  72. package/package.json +1 -1
  73. package/src/components/Inspector/AnalyticsTab.tsx +0 -23
  74. package/src/components/Inspector/ConsoleTab.tsx +0 -23
  75. package/src/components/Inspector/CrashTab.tsx +0 -23
  76. package/src/components/Inspector/FeedbackModal.tsx +626 -0
  77. package/src/components/Inspector/InspectorHeader.tsx +78 -2
  78. package/src/components/Inspector/MainScreen.tsx +59 -3
  79. package/src/components/Inspector/NetworkTab.tsx +69 -78
  80. package/src/components/Inspector/NpmStarPrompt.tsx +532 -0
  81. package/src/components/Inspector/PerformanceTab.tsx +8 -1
  82. package/src/components/Inspector/ReduxTab.tsx +0 -23
  83. package/src/components/Inspector/SettingsPanel.tsx +1162 -197
  84. package/src/components/Inspector/StorageTab.tsx +0 -23
  85. package/src/components/Inspector/TabBar.tsx +57 -20
  86. package/src/components/NetworkIcons.tsx +92 -0
  87. package/src/constants/version.ts +1 -1
  88. package/src/helpers/index.ts +1 -0
  89. package/src/helpers/remoteConfig.ts +212 -0
  90. package/src/helpers/searchQueryParser.ts +3 -0
  91. package/src/helpers/telemetry.ts +381 -10
  92. package/src/index.tsx +42 -0
  93. package/src/styles/AppFonts.ts +2 -0
  94. package/src/styles/index.ts +20 -1
  95. package/src/types/enums.ts +1 -0
  96. package/src/types/interfaces.ts +12 -0
@@ -1352,29 +1352,6 @@ const AnalyticsTab = React.memo(() => {
1352
1352
  ]}
1353
1353
  keyboardShouldPersistTaps="handled"
1354
1354
  />
1355
-
1356
- <TouchableScale
1357
- onPress={() => {
1358
- try {
1359
- listRef.current?.scrollToOffset({
1360
- offset: 0,
1361
- animated: true,
1362
- });
1363
- } catch {
1364
- try {
1365
- listRef.current?.scrollToIndex({
1366
- index: 0,
1367
- animated: true,
1368
- });
1369
- } catch {}
1370
- }
1371
- }}
1372
- hitSlop={12}
1373
- style={styles.scrollTopBtn}>
1374
- <View style={{transform: [{rotate: '180deg'}]}}>
1375
- <ChevronIcon color={AppColors.white} size={18} />
1376
- </View>
1377
- </TouchableScale>
1378
1355
  </>
1379
1356
  ) : null}
1380
1357
  </View>
@@ -718,29 +718,6 @@ const ConsoleTab = React.memo(() => {
718
718
  ]}
719
719
  keyboardShouldPersistTaps="handled"
720
720
  />
721
-
722
- <TouchableScale
723
- onPress={() => {
724
- try {
725
- listRef.current?.scrollToOffset({
726
- offset: 0,
727
- animated: true,
728
- });
729
- } catch {
730
- try {
731
- listRef.current?.scrollToIndex({
732
- index: 0,
733
- animated: true,
734
- });
735
- } catch {}
736
- }
737
- }}
738
- hitSlop={12}
739
- style={styles.scrollTopBtn}>
740
- <View style={{transform: [{rotate: '180deg'}]}}>
741
- <ChevronIcon color={AppColors.white} size={18} />
742
- </View>
743
- </TouchableScale>
744
721
  </View>
745
722
  );
746
723
  });
@@ -613,29 +613,6 @@ const CrashTab = React.memo(() => {
613
613
  showsVerticalScrollIndicator={false}
614
614
  ListFooterComponent={<EndOfListFooter />}
615
615
  />
616
-
617
- <TouchableScale
618
- onPress={() => {
619
- try {
620
- listRef.current?.scrollToOffset({
621
- offset: 0,
622
- animated: true,
623
- });
624
- } catch {
625
- try {
626
- listRef.current?.scrollToIndex({
627
- index: 0,
628
- animated: true,
629
- });
630
- } catch {}
631
- }
632
- }}
633
- hitSlop={12}
634
- style={styles.scrollTopBtn}>
635
- <View style={{transform: [{rotate: '180deg'}]}}>
636
- <ChevronIcon color={AppColors.white} size={18} />
637
- </View>
638
- </TouchableScale>
639
616
  </>
640
617
  )}
641
618
 
@@ -0,0 +1,626 @@
1
+ import React, {useState, useEffect} from 'react';
2
+ import {
3
+ Alert,
4
+ Dimensions,
5
+ PixelRatio,
6
+ Platform,
7
+ Linking,
8
+ ScrollView,
9
+ StyleSheet,
10
+ Text,
11
+ TextInput,
12
+ TouchableOpacity,
13
+ View,
14
+ } from 'react-native';
15
+ import {AppColors} from '../../styles/AppColors';
16
+ import {AppFonts} from '../../styles/AppFonts';
17
+ import TouchableScale from '../TouchableScale';
18
+ import {LIB_VERSION} from '../../constants/version';
19
+ import {
20
+ getAppName,
21
+ getBundleIdentifier,
22
+ getAppVersionAndBuild,
23
+ copyToClipboard,
24
+ showToast,
25
+ } from '../../helpers';
26
+ import {trackTelemetryEvent} from '../../helpers/telemetry';
27
+ import {
28
+ HeadphonesIcon,
29
+ SendIcon,
30
+ StarIcon,
31
+ CopyIcon,
32
+ InfoCircleIcon,
33
+ CheckIcon,
34
+ } from '../NetworkIcons';
35
+
36
+ const DEVELOPER_EMAIL = 'vengatmacuser@gmail.com';
37
+
38
+ export interface FeedbackModalProps {
39
+ visible?: boolean;
40
+ onClose: () => void;
41
+ }
42
+
43
+ type FeedbackCategory = 'feedback' | 'bug' | 'feature' | 'performance' | 'help';
44
+
45
+ const CATEGORIES: {key: FeedbackCategory; label: string; icon: string}[] = [
46
+ {key: 'feedback', label: 'Feedback', icon: '💬'},
47
+ {key: 'bug', label: 'Bug Report', icon: '🐛'},
48
+ {key: 'feature', label: 'Feature Request', icon: '✨'},
49
+ {key: 'performance', label: 'Performance', icon: '⚡'},
50
+ {key: 'help', label: 'Support / Help', icon: '❓'},
51
+ ];
52
+
53
+ const RATING_LABELS = ['', 'Poor', 'Fair', 'Good', 'Very Good', 'Excellent!'];
54
+
55
+ export const FeedbackModal: React.FC<FeedbackModalProps> = ({onClose}) => {
56
+ const [category, setCategory] = useState<FeedbackCategory>('feedback');
57
+ const [rating, setRating] = useState<number>(5);
58
+ const [subject, setSubject] = useState<string>('');
59
+ const [message, setMessage] = useState<string>('');
60
+ const [showDiagnostics, setShowDiagnostics] = useState<boolean>(false);
61
+ const [isSending, setIsSending] = useState<boolean>(false);
62
+ const [copiedDraft, setCopiedDraft] = useState<boolean>(false);
63
+
64
+ useEffect(() => {
65
+ trackTelemetryEvent('feedback_modal_opened', {category});
66
+ }, []);
67
+
68
+ const appName = getAppName() || 'React Native App';
69
+ const bundleId = getBundleIdentifier() || 'unknown';
70
+ const appVersion = getAppVersionAndBuild() || '1.0.0';
71
+ const {width, height} = Dimensions.get('window');
72
+
73
+ const getDiagnosticsText = () => {
74
+ return [
75
+ `• Package: react-native-inapp-inspector@${LIB_VERSION}`,
76
+ `• Platform: ${Platform.OS.toUpperCase()} (${Platform.Version})`,
77
+ `• App: ${appName} (${bundleId}) v${appVersion}`,
78
+ `• Screen: ${Math.round(width)} x ${Math.round(height)} (Scale ${PixelRatio.get()})`,
79
+ `• Timestamp: ${new Date().toISOString()}`,
80
+ ].join('\n');
81
+ };
82
+
83
+ const buildEmailDraft = () => {
84
+ const activeCat = CATEGORIES.find(c => c.key === category)?.label || category;
85
+ const emailSubject = `[In-App Inspector] [${activeCat}] ${subject.trim() || 'User Feedback'}`;
86
+ const bodyLines = [
87
+ `Category: ${activeCat}`,
88
+ `Rating: ${rating} / 5 (${RATING_LABELS[rating] || ''})`,
89
+ ...(subject.trim() ? [`Subject: ${subject.trim()}`] : []),
90
+ '',
91
+ 'Feedback / Message:',
92
+ message.trim() || '(No message provided)',
93
+ '',
94
+ '----------------------------------------',
95
+ 'System & Diagnostic Info:',
96
+ getDiagnosticsText(),
97
+ '----------------------------------------',
98
+ ];
99
+ return {
100
+ activeCat,
101
+ subject: emailSubject,
102
+ body: bodyLines.join('\n'),
103
+ };
104
+ };
105
+
106
+ const handleCopyDraft = () => {
107
+ const draft = buildEmailDraft();
108
+ const fullText = `To: ${DEVELOPER_EMAIL}\nSubject: ${draft.subject}\n\n${draft.body}`;
109
+ copyToClipboard(fullText, 'Email Draft & Diagnostics');
110
+ setCopiedDraft(true);
111
+ setTimeout(() => setCopiedDraft(false), 2000);
112
+ showToast('Feedback draft copied to clipboard');
113
+ };
114
+
115
+ const handleSendEmail = async () => {
116
+ if (isSending) return;
117
+ setIsSending(true);
118
+
119
+ try {
120
+ const draft = buildEmailDraft();
121
+ const mailtoUrl = `mailto:${DEVELOPER_EMAIL}?subject=${encodeURIComponent(
122
+ draft.subject,
123
+ )}&body=${encodeURIComponent(draft.body)}`;
124
+
125
+ // Track telemetry event
126
+ trackTelemetryEvent('feedback_submitted', {
127
+ category,
128
+ rating,
129
+ has_subject: Boolean(subject.trim()),
130
+ has_message: Boolean(message.trim()),
131
+ });
132
+
133
+ let opened = false;
134
+ try {
135
+ const canOpen = await Linking.canOpenURL(mailtoUrl);
136
+ if (canOpen) {
137
+ await Linking.openURL(mailtoUrl);
138
+ opened = true;
139
+ } else {
140
+ await Linking.openURL(mailtoUrl);
141
+ opened = true;
142
+ }
143
+ } catch (err) {
144
+ opened = false;
145
+ }
146
+
147
+ if (opened) {
148
+ showToast('Opening mail client...');
149
+ onClose();
150
+ } else {
151
+ // Fallback: Copy to clipboard and alert user with action options
152
+ const fullDraft = `To: ${DEVELOPER_EMAIL}\nSubject: ${draft.subject}\n\n${draft.body}`;
153
+ copyToClipboard(fullDraft, 'Feedback Draft');
154
+ Alert.alert(
155
+ 'Email Client Not Available',
156
+ `Your feedback and diagnostics have been copied to the clipboard!\n\nYou can paste and send directly to:\n${DEVELOPER_EMAIL}`,
157
+ [
158
+ {
159
+ text: 'Copy Email Address',
160
+ onPress: () => {
161
+ copyToClipboard(DEVELOPER_EMAIL, 'Email Address');
162
+ showToast('Email address copied!');
163
+ },
164
+ },
165
+ {
166
+ text: 'Done',
167
+ style: 'default',
168
+ onPress: onClose,
169
+ },
170
+ ],
171
+ );
172
+ }
173
+ } catch (err) {
174
+ console.warn('[FeedbackModal] Error sending email:', err);
175
+ } finally {
176
+ setIsSending(false);
177
+ }
178
+ };
179
+
180
+ return (
181
+ <View style={styles.container}>
182
+ {/* Top Banner inside sheet */}
183
+ <View style={styles.bannerBar}>
184
+ <View style={styles.bannerIconBox}>
185
+ <HeadphonesIcon size={18} color={AppColors.purple} />
186
+ </View>
187
+ <View style={{flex: 1}}>
188
+ <Text style={styles.bannerTitle}>Share your feedback or report an issue</Text>
189
+ <Text style={styles.bannerSub}>
190
+ Direct communication with the maintainers. Diagnostic info is auto-attached.
191
+ </Text>
192
+ </View>
193
+ </View>
194
+
195
+ <ScrollView
196
+ style={styles.scrollContent}
197
+ contentContainerStyle={styles.scrollInner}
198
+ showsVerticalScrollIndicator={false}
199
+ keyboardShouldPersistTaps="handled">
200
+ {/* Category selection */}
201
+ <Text style={styles.sectionLabel}>WHAT CAN WE HELP WITH?</Text>
202
+ <View style={styles.categoryGrid}>
203
+ {CATEGORIES.map(cat => {
204
+ const isSelected = category === cat.key;
205
+ return (
206
+ <TouchableOpacity
207
+ key={cat.key}
208
+ activeOpacity={0.7}
209
+ onPress={() => setCategory(cat.key)}
210
+ style={[
211
+ styles.categoryChip,
212
+ isSelected && styles.categoryChipSelected,
213
+ ]}>
214
+ <Text style={styles.categoryIcon}>{cat.icon}</Text>
215
+ <Text
216
+ style={[
217
+ styles.categoryText,
218
+ isSelected && styles.categoryTextSelected,
219
+ ]}>
220
+ {cat.label}
221
+ </Text>
222
+ </TouchableOpacity>
223
+ );
224
+ })}
225
+ </View>
226
+
227
+ {/* Rating Stars */}
228
+ <View style={styles.ratingCard}>
229
+ <View style={styles.ratingHeader}>
230
+ <Text style={styles.ratingTitle}>Rate your experience</Text>
231
+ {rating > 0 && (
232
+ <Text style={styles.ratingBadge}>
233
+ {RATING_LABELS[rating]}
234
+ </Text>
235
+ )}
236
+ </View>
237
+ <View style={styles.starsRow}>
238
+ {[1, 2, 3, 4, 5].map(star => {
239
+ const filled = star <= rating;
240
+ return (
241
+ <TouchableOpacity
242
+ key={star}
243
+ activeOpacity={0.7}
244
+ onPress={() => setRating(star)}
245
+ style={styles.starTouch}>
246
+ <StarIcon
247
+ size={26}
248
+ color={filled ? '#FFB800' : AppColors.grayTextWeak}
249
+ />
250
+ </TouchableOpacity>
251
+ );
252
+ })}
253
+ </View>
254
+ </View>
255
+
256
+ {/* Subject Input */}
257
+ <Text style={styles.sectionLabel}>SUBJECT (OPTIONAL)</Text>
258
+ <View style={styles.inputWrapper}>
259
+ <TextInput
260
+ style={styles.textInput}
261
+ placeholder="Brief summary..."
262
+ placeholderTextColor={AppColors.grayTextWeak}
263
+ value={subject}
264
+ onChangeText={setSubject}
265
+ maxLength={80}
266
+ />
267
+ </View>
268
+
269
+ {/* Message Input */}
270
+ <Text style={styles.sectionLabel}>YOUR MESSAGE / DETAILS</Text>
271
+ <View style={[styles.inputWrapper, styles.textareaWrapper]}>
272
+ <TextInput
273
+ style={[styles.textInput, styles.textarea]}
274
+ placeholder="Describe your issue, feature request, or suggestion in detail..."
275
+ placeholderTextColor={AppColors.grayTextWeak}
276
+ value={message}
277
+ onChangeText={setMessage}
278
+ multiline
279
+ numberOfLines={4}
280
+ textAlignVertical="top"
281
+ />
282
+ </View>
283
+
284
+ {/* Diagnostics Card */}
285
+ <TouchableOpacity
286
+ activeOpacity={0.8}
287
+ onPress={() => setShowDiagnostics(!showDiagnostics)}
288
+ style={styles.diagnosticsToggle}>
289
+ <View style={styles.diagnosticsHeader}>
290
+ <InfoCircleIcon size={14} color={AppColors.purple} />
291
+ <Text style={styles.diagnosticsTitle}>
292
+ Diagnostics & System Details (Auto-attached)
293
+ </Text>
294
+ </View>
295
+ <Text style={styles.diagnosticsArrow}>
296
+ {showDiagnostics ? '▲' : '▼'}
297
+ </Text>
298
+ </TouchableOpacity>
299
+
300
+ {showDiagnostics && (
301
+ <View style={styles.diagnosticsBox}>
302
+ <Text style={styles.diagnosticsText}>
303
+ {getDiagnosticsText()}
304
+ </Text>
305
+ </View>
306
+ )}
307
+
308
+ {/* Recipient Notice */}
309
+ <View style={styles.recipientBadge}>
310
+ <Text style={styles.recipientText}>
311
+ 📧 Emails to: <Text style={styles.recipientHighlight}>{DEVELOPER_EMAIL}</Text>
312
+ </Text>
313
+ </View>
314
+ </ScrollView>
315
+
316
+ {/* Footer Actions */}
317
+ <View style={styles.footer}>
318
+ <TouchableOpacity
319
+ activeOpacity={0.7}
320
+ onPress={handleCopyDraft}
321
+ style={styles.copyDraftBtn}>
322
+ {copiedDraft ? (
323
+ <CheckIcon size={14} color={AppColors.emerald500} />
324
+ ) : (
325
+ <CopyIcon size={14} color={AppColors.grayText} />
326
+ )}
327
+ <Text
328
+ style={[
329
+ styles.copyDraftBtnText,
330
+ copiedDraft && {color: AppColors.emerald500},
331
+ ]}>
332
+ {copiedDraft ? 'Copied!' : 'Copy Draft'}
333
+ </Text>
334
+ </TouchableOpacity>
335
+
336
+ <View style={styles.footerRight}>
337
+ <TouchableOpacity
338
+ activeOpacity={0.7}
339
+ onPress={onClose}
340
+ style={styles.cancelBtn}>
341
+ <Text style={styles.cancelBtnText}>Cancel</Text>
342
+ </TouchableOpacity>
343
+
344
+ <TouchableOpacity
345
+ activeOpacity={0.8}
346
+ onPress={handleSendEmail}
347
+ style={styles.submitBtn}>
348
+ <SendIcon size={16} color={AppColors.white} />
349
+ <Text style={styles.submitBtnText}>
350
+ {isSending ? 'Sending...' : 'Send via Email'}
351
+ </Text>
352
+ </TouchableOpacity>
353
+ </View>
354
+ </View>
355
+ </View>
356
+ );
357
+ };
358
+
359
+ const styles = StyleSheet.create({
360
+ container: {
361
+ flex: 1,
362
+ backgroundColor: AppColors.primaryLight,
363
+ },
364
+ bannerBar: {
365
+ flexDirection: 'row',
366
+ alignItems: 'center',
367
+ gap: 10,
368
+ backgroundColor: `${AppColors.purple}12`,
369
+ paddingHorizontal: 14,
370
+ paddingVertical: 10,
371
+ borderBottomWidth: 1,
372
+ borderBottomColor: `${AppColors.purple}20`,
373
+ },
374
+ bannerIconBox: {
375
+ width: 32,
376
+ height: 32,
377
+ borderRadius: 8,
378
+ backgroundColor: `${AppColors.purple}20`,
379
+ alignItems: 'center',
380
+ justifyContent: 'center',
381
+ },
382
+ bannerTitle: {
383
+ fontFamily: AppFonts.interSemiBold,
384
+ fontSize: 12.5,
385
+ color: AppColors.purple,
386
+ },
387
+ bannerSub: {
388
+ fontFamily: AppFonts.interRegular,
389
+ fontSize: 10.5,
390
+ color: AppColors.grayText,
391
+ marginTop: 1,
392
+ },
393
+ scrollContent: {
394
+ flex: 1,
395
+ },
396
+ scrollInner: {
397
+ paddingHorizontal: 16,
398
+ paddingTop: 12,
399
+ paddingBottom: 20,
400
+ },
401
+ sectionLabel: {
402
+ fontFamily: AppFonts.interSemiBold,
403
+ fontSize: 10.5,
404
+ color: AppColors.grayText,
405
+ letterSpacing: 0.8,
406
+ marginBottom: 8,
407
+ marginTop: 10,
408
+ },
409
+ categoryGrid: {
410
+ flexDirection: 'row',
411
+ flexWrap: 'wrap',
412
+ gap: 8,
413
+ paddingBottom: 4,
414
+ },
415
+ categoryChip: {
416
+ flexDirection: 'row',
417
+ alignItems: 'center',
418
+ gap: 6,
419
+ paddingVertical: 7,
420
+ paddingHorizontal: 12,
421
+ borderRadius: 8,
422
+ backgroundColor: AppColors.grayBackground,
423
+ borderWidth: 1,
424
+ borderColor: AppColors.dividerColor,
425
+ },
426
+ categoryChipSelected: {
427
+ backgroundColor: `${AppColors.purple}15`,
428
+ borderColor: AppColors.purple,
429
+ },
430
+ categoryIcon: {
431
+ fontSize: 13,
432
+ },
433
+ categoryText: {
434
+ fontFamily: AppFonts.interMedium,
435
+ fontSize: 12,
436
+ color: AppColors.grayText,
437
+ },
438
+ categoryTextSelected: {
439
+ color: AppColors.purple,
440
+ fontFamily: AppFonts.interSemiBold,
441
+ },
442
+ ratingCard: {
443
+ backgroundColor: AppColors.grayBackground,
444
+ borderRadius: 12,
445
+ padding: 12,
446
+ marginTop: 12,
447
+ borderWidth: 1,
448
+ borderColor: AppColors.dividerColor,
449
+ },
450
+ ratingHeader: {
451
+ flexDirection: 'row',
452
+ justifyContent: 'space-between',
453
+ alignItems: 'center',
454
+ marginBottom: 8,
455
+ },
456
+ ratingTitle: {
457
+ fontFamily: AppFonts.interSemiBold,
458
+ fontSize: 12.5,
459
+ color: AppColors.primaryBlack,
460
+ },
461
+ ratingBadge: {
462
+ fontFamily: AppFonts.interSemiBold,
463
+ fontSize: 11,
464
+ color: '#D97706',
465
+ backgroundColor: '#FEF3C7',
466
+ paddingHorizontal: 8,
467
+ paddingVertical: 2,
468
+ borderRadius: 6,
469
+ },
470
+ starsRow: {
471
+ flexDirection: 'row',
472
+ alignItems: 'center',
473
+ gap: 12,
474
+ paddingVertical: 4,
475
+ },
476
+ starTouch: {
477
+ padding: 2,
478
+ },
479
+ inputWrapper: {
480
+ backgroundColor: AppColors.grayBackground,
481
+ borderRadius: 10,
482
+ borderWidth: 1,
483
+ borderColor: AppColors.dividerColor,
484
+ paddingHorizontal: 12,
485
+ paddingVertical: 8,
486
+ },
487
+ textareaWrapper: {
488
+ minHeight: 88,
489
+ paddingVertical: 10,
490
+ },
491
+ textInput: {
492
+ fontFamily: AppFonts.interRegular,
493
+ fontSize: 13,
494
+ color: AppColors.primaryBlack,
495
+ padding: 0,
496
+ },
497
+ textarea: {
498
+ height: 72,
499
+ },
500
+ diagnosticsToggle: {
501
+ flexDirection: 'row',
502
+ alignItems: 'center',
503
+ justifyContent: 'space-between',
504
+ backgroundColor: `${AppColors.purple}10`,
505
+ borderRadius: 8,
506
+ paddingHorizontal: 12,
507
+ paddingVertical: 9,
508
+ marginTop: 14,
509
+ borderWidth: 1,
510
+ borderColor: `${AppColors.purple}25`,
511
+ },
512
+ diagnosticsHeader: {
513
+ flexDirection: 'row',
514
+ alignItems: 'center',
515
+ gap: 8,
516
+ flex: 1,
517
+ },
518
+ diagnosticsTitle: {
519
+ fontFamily: AppFonts.interMedium,
520
+ fontSize: 11.5,
521
+ color: AppColors.purple,
522
+ },
523
+ diagnosticsArrow: {
524
+ fontSize: 10,
525
+ color: AppColors.purple,
526
+ },
527
+ diagnosticsBox: {
528
+ backgroundColor: '#1E1B2E',
529
+ borderRadius: 8,
530
+ padding: 10,
531
+ marginTop: 6,
532
+ borderWidth: 1,
533
+ borderColor: AppColors.dividerColor,
534
+ },
535
+ diagnosticsText: {
536
+ fontFamily: AppFonts.interRegular,
537
+ fontSize: 11,
538
+ color: '#E2DFEB',
539
+ lineHeight: 17,
540
+ },
541
+ recipientBadge: {
542
+ marginTop: 12,
543
+ paddingVertical: 6,
544
+ paddingHorizontal: 10,
545
+ borderRadius: 6,
546
+ backgroundColor: AppColors.grayBackground,
547
+ borderWidth: 1,
548
+ borderColor: AppColors.dividerColor,
549
+ alignSelf: 'flex-start',
550
+ },
551
+ recipientText: {
552
+ fontFamily: AppFonts.interRegular,
553
+ fontSize: 11,
554
+ color: AppColors.grayText,
555
+ },
556
+ recipientHighlight: {
557
+ fontFamily: AppFonts.interSemiBold,
558
+ color: AppColors.purple,
559
+ },
560
+ footer: {
561
+ flexDirection: 'row',
562
+ alignItems: 'center',
563
+ justifyContent: 'space-between',
564
+ paddingHorizontal: 14,
565
+ paddingTop: 10,
566
+ paddingBottom: 14,
567
+ borderTopWidth: 1,
568
+ borderTopColor: AppColors.dividerColor,
569
+ backgroundColor: AppColors.primaryLight,
570
+ },
571
+ copyDraftBtn: {
572
+ flexDirection: 'row',
573
+ alignItems: 'center',
574
+ gap: 5,
575
+ paddingVertical: 8,
576
+ paddingHorizontal: 10,
577
+ borderRadius: 8,
578
+ backgroundColor: AppColors.grayBackground,
579
+ borderWidth: 1,
580
+ borderColor: AppColors.dividerColor,
581
+ },
582
+ copyDraftBtnText: {
583
+ fontFamily: AppFonts.interMedium,
584
+ fontSize: 11.5,
585
+ color: AppColors.grayText,
586
+ },
587
+ footerRight: {
588
+ flexDirection: 'row',
589
+ alignItems: 'center',
590
+ gap: 8,
591
+ },
592
+ cancelBtn: {
593
+ paddingVertical: 8,
594
+ paddingHorizontal: 14,
595
+ borderRadius: 8,
596
+ backgroundColor: AppColors.grayBackground,
597
+ borderWidth: 1,
598
+ borderColor: AppColors.dividerColor,
599
+ },
600
+ cancelBtnText: {
601
+ fontFamily: AppFonts.interMedium,
602
+ fontSize: 12.5,
603
+ color: AppColors.grayText,
604
+ },
605
+ submitBtn: {
606
+ flexDirection: 'row',
607
+ alignItems: 'center',
608
+ gap: 6,
609
+ backgroundColor: AppColors.purple,
610
+ paddingVertical: 8,
611
+ paddingHorizontal: 15,
612
+ borderRadius: 8,
613
+ shadowColor: AppColors.purple,
614
+ shadowOffset: {width: 0, height: 2},
615
+ shadowOpacity: 0.35,
616
+ shadowRadius: 6,
617
+ elevation: 4,
618
+ },
619
+ submitBtnText: {
620
+ fontFamily: AppFonts.interSemiBold,
621
+ fontSize: 12.5,
622
+ color: AppColors.white,
623
+ },
624
+ });
625
+
626
+ export default FeedbackModal;