react-native-inapp-inspector 2.3.14 → 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 (125) hide show
  1. package/README.md +1 -0
  2. package/dist/commonjs/components/AnimatedEntrance.js +3 -3
  3. package/dist/commonjs/components/ConsoleLogCard.js +174 -100
  4. package/dist/commonjs/components/Inspector/AnalyticsTab.js +0 -22
  5. package/dist/commonjs/components/Inspector/ConsoleTab.js +25 -38
  6. package/dist/commonjs/components/Inspector/CrashTab.js +19 -28
  7. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +198 -98
  8. package/dist/commonjs/components/Inspector/FeedbackModal.d.ts +7 -0
  9. package/dist/commonjs/components/Inspector/FeedbackModal.js +552 -0
  10. package/dist/commonjs/components/Inspector/InspectorHeader.js +58 -6
  11. package/dist/commonjs/components/Inspector/MainScreen.js +100 -58
  12. package/dist/commonjs/components/Inspector/NetworkTab.js +26 -371
  13. package/dist/commonjs/components/Inspector/NpmStarPrompt.d.ts +3 -0
  14. package/dist/commonjs/components/Inspector/NpmStarPrompt.js +494 -0
  15. package/dist/commonjs/components/Inspector/PerformanceTab.js +40 -7
  16. package/dist/commonjs/components/Inspector/ReduxTab.js +3 -23
  17. package/dist/commonjs/components/Inspector/SettingsPanel.js +1035 -173
  18. package/dist/commonjs/components/Inspector/StorageTab.js +23 -28
  19. package/dist/commonjs/components/Inspector/TabBar.js +50 -15
  20. package/dist/commonjs/components/JsonViewer.js +14 -2
  21. package/dist/commonjs/components/LogCard.js +428 -227
  22. package/dist/commonjs/components/NetworkIcons.d.ts +5 -0
  23. package/dist/commonjs/components/NetworkIcons.js +33 -2
  24. package/dist/commonjs/constants/version.d.ts +1 -1
  25. package/dist/commonjs/constants/version.js +1 -1
  26. package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
  27. package/dist/commonjs/customHooks/consoleLogger.js +34 -2
  28. package/dist/commonjs/customHooks/crashHandler.js +1 -1
  29. package/dist/commonjs/customHooks/networkLogger.js +184 -26
  30. package/dist/commonjs/helpers/index.d.ts +1 -0
  31. package/dist/commonjs/helpers/index.js +1 -0
  32. package/dist/commonjs/helpers/remoteConfig.d.ts +4 -0
  33. package/dist/commonjs/helpers/remoteConfig.js +165 -0
  34. package/dist/commonjs/helpers/searchQueryParser.d.ts +1 -1
  35. package/dist/commonjs/helpers/searchQueryParser.js +39 -291
  36. package/dist/commonjs/helpers/telemetry.d.ts +5 -0
  37. package/dist/commonjs/helpers/telemetry.js +339 -8
  38. package/dist/commonjs/index.d.ts +1 -0
  39. package/dist/commonjs/index.js +173 -29
  40. package/dist/commonjs/styles/AppFonts.d.ts +2 -0
  41. package/dist/commonjs/styles/AppFonts.js +1 -0
  42. package/dist/commonjs/styles/index.d.ts +22 -0
  43. package/dist/commonjs/styles/index.js +19 -0
  44. package/dist/commonjs/types/enums.d.ts +1 -0
  45. package/dist/commonjs/types/enums.js +1 -0
  46. package/dist/commonjs/types/interfaces.d.ts +12 -0
  47. package/dist/esm/components/AnimatedEntrance.js +3 -3
  48. package/dist/esm/components/ConsoleLogCard.js +141 -100
  49. package/dist/esm/components/Inspector/AnalyticsTab.js +1 -23
  50. package/dist/esm/components/Inspector/ConsoleTab.js +26 -39
  51. package/dist/esm/components/Inspector/CrashTab.js +20 -29
  52. package/dist/esm/components/Inspector/DeviceInfoTab.js +198 -98
  53. package/dist/esm/components/Inspector/FeedbackModal.d.ts +7 -0
  54. package/dist/esm/components/Inspector/FeedbackModal.js +515 -0
  55. package/dist/esm/components/Inspector/InspectorHeader.js +60 -8
  56. package/dist/esm/components/Inspector/MainScreen.js +101 -59
  57. package/dist/esm/components/Inspector/NetworkTab.js +27 -372
  58. package/dist/esm/components/Inspector/NpmStarPrompt.d.ts +3 -0
  59. package/dist/esm/components/Inspector/NpmStarPrompt.js +454 -0
  60. package/dist/esm/components/Inspector/PerformanceTab.js +40 -7
  61. package/dist/esm/components/Inspector/ReduxTab.js +4 -24
  62. package/dist/esm/components/Inspector/SettingsPanel.js +1038 -176
  63. package/dist/esm/components/Inspector/StorageTab.js +23 -28
  64. package/dist/esm/components/Inspector/TabBar.js +50 -15
  65. package/dist/esm/components/JsonViewer.js +14 -2
  66. package/dist/esm/components/LogCard.js +422 -221
  67. package/dist/esm/components/NetworkIcons.d.ts +5 -0
  68. package/dist/esm/components/NetworkIcons.js +26 -0
  69. package/dist/esm/constants/version.d.ts +1 -1
  70. package/dist/esm/constants/version.js +1 -1
  71. package/dist/esm/customHooks/analyticsLogger.js +1 -1
  72. package/dist/esm/customHooks/consoleLogger.js +34 -2
  73. package/dist/esm/customHooks/crashHandler.js +1 -1
  74. package/dist/esm/customHooks/networkLogger.js +184 -26
  75. package/dist/esm/helpers/index.d.ts +1 -0
  76. package/dist/esm/helpers/index.js +1 -0
  77. package/dist/esm/helpers/remoteConfig.d.ts +4 -0
  78. package/dist/esm/helpers/remoteConfig.js +160 -0
  79. package/dist/esm/helpers/searchQueryParser.d.ts +1 -1
  80. package/dist/esm/helpers/searchQueryParser.js +39 -291
  81. package/dist/esm/helpers/telemetry.d.ts +5 -0
  82. package/dist/esm/helpers/telemetry.js +332 -9
  83. package/dist/esm/index.d.ts +1 -0
  84. package/dist/esm/index.js +171 -29
  85. package/dist/esm/styles/AppFonts.d.ts +2 -0
  86. package/dist/esm/styles/AppFonts.js +1 -0
  87. package/dist/esm/styles/index.d.ts +22 -0
  88. package/dist/esm/styles/index.js +19 -0
  89. package/dist/esm/types/enums.d.ts +1 -0
  90. package/dist/esm/types/enums.js +1 -0
  91. package/dist/esm/types/interfaces.d.ts +12 -0
  92. package/package.json +1 -1
  93. package/src/components/AnimatedEntrance.tsx +3 -3
  94. package/src/components/ConsoleLogCard.tsx +154 -103
  95. package/src/components/Inspector/AnalyticsTab.tsx +0 -23
  96. package/src/components/Inspector/ConsoleTab.tsx +27 -41
  97. package/src/components/Inspector/CrashTab.tsx +19 -28
  98. package/src/components/Inspector/DeviceInfoTab.tsx +224 -102
  99. package/src/components/Inspector/FeedbackModal.tsx +626 -0
  100. package/src/components/Inspector/InspectorHeader.tsx +83 -5
  101. package/src/components/Inspector/MainScreen.tsx +61 -6
  102. package/src/components/Inspector/NetworkTab.tsx +70 -480
  103. package/src/components/Inspector/NpmStarPrompt.tsx +532 -0
  104. package/src/components/Inspector/PerformanceTab.tsx +44 -8
  105. package/src/components/Inspector/ReduxTab.tsx +9 -24
  106. package/src/components/Inspector/SettingsPanel.tsx +1162 -197
  107. package/src/components/Inspector/StorageTab.tsx +27 -30
  108. package/src/components/Inspector/TabBar.tsx +57 -20
  109. package/src/components/JsonViewer.tsx +15 -2
  110. package/src/components/LogCard.tsx +528 -339
  111. package/src/components/NetworkIcons.tsx +92 -0
  112. package/src/constants/version.ts +1 -1
  113. package/src/customHooks/analyticsLogger.ts +1 -1
  114. package/src/customHooks/consoleLogger.ts +36 -3
  115. package/src/customHooks/crashHandler.ts +1 -1
  116. package/src/customHooks/networkLogger.ts +214 -26
  117. package/src/helpers/index.ts +1 -0
  118. package/src/helpers/remoteConfig.ts +212 -0
  119. package/src/helpers/searchQueryParser.ts +42 -284
  120. package/src/helpers/telemetry.ts +381 -10
  121. package/src/index.tsx +374 -211
  122. package/src/styles/AppFonts.ts +2 -0
  123. package/src/styles/index.ts +20 -1
  124. package/src/types/enums.ts +1 -0
  125. package/src/types/interfaces.ts +12 -0
@@ -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;