@messenger-box/platform-mobile 10.0.3-alpha.7 → 10.0.3-alpha.72

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 (98) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/lib/compute.js +2 -3
  3. package/lib/compute.js.map +1 -1
  4. package/lib/index.js.map +1 -1
  5. package/lib/queries/inboxQueries.js +65 -0
  6. package/lib/queries/inboxQueries.js.map +1 -0
  7. package/lib/routes.json +2 -3
  8. package/lib/screens/inbox/DialogMessages.js +1 -1
  9. package/lib/screens/inbox/DialogMessages.js.map +1 -1
  10. package/lib/screens/inbox/DialogThreadMessages.js +4 -8
  11. package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
  12. package/lib/screens/inbox/DialogThreads.js +57 -12
  13. package/lib/screens/inbox/DialogThreads.js.map +1 -1
  14. package/lib/screens/inbox/Inbox.js +1 -1
  15. package/lib/screens/inbox/Inbox.js.map +1 -1
  16. package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
  17. package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
  18. package/lib/screens/inbox/components/CachedImage/index.js +168 -46
  19. package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
  20. package/lib/screens/inbox/components/DialogItem.js +169 -0
  21. package/lib/screens/inbox/components/DialogItem.js.map +1 -0
  22. package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
  23. package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
  24. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +147 -31
  25. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
  26. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +6 -1
  27. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
  28. package/lib/screens/inbox/components/SubscriptionHandler.js +24 -0
  29. package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
  30. package/lib/screens/inbox/components/ThreadsViewItem.js +66 -55
  31. package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
  32. package/lib/screens/inbox/config/config.js +2 -2
  33. package/lib/screens/inbox/config/config.js.map +1 -1
  34. package/lib/screens/inbox/containers/ConversationView.js +1111 -434
  35. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  36. package/lib/screens/inbox/containers/Dialogs.js +193 -80
  37. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  38. package/lib/screens/inbox/containers/ThreadConversationView.js +725 -216
  39. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  40. package/lib/screens/inbox/containers/ThreadsView.js +83 -50
  41. package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
  42. package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
  43. package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
  44. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
  45. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
  46. package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
  47. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
  48. package/package.json +4 -4
  49. package/src/compute.ts +5 -6
  50. package/src/index.ts +2 -0
  51. package/src/navigation/InboxNavigation.tsx +3 -3
  52. package/src/queries/inboxQueries.ts +299 -0
  53. package/src/queries/index.d.ts +2 -0
  54. package/src/queries/index.ts +1 -0
  55. package/src/screens/inbox/DialogMessages.tsx +1 -1
  56. package/src/screens/inbox/DialogThreadMessages.tsx +7 -14
  57. package/src/screens/inbox/DialogThreads.tsx +55 -61
  58. package/src/screens/inbox/Inbox.tsx +1 -1
  59. package/src/screens/inbox/components/Actionsheet.tsx +30 -0
  60. package/src/screens/inbox/components/CachedImage/consts.ts +4 -3
  61. package/src/screens/inbox/components/CachedImage/index.tsx +232 -61
  62. package/src/screens/inbox/components/DialogItem.tsx +306 -0
  63. package/src/screens/inbox/components/DialogsHeader.tsx +6 -13
  64. package/src/screens/inbox/components/DialogsListItem.tsx +262 -198
  65. package/src/screens/inbox/components/ExpandableInput.tsx +460 -0
  66. package/src/screens/inbox/components/ExpandableInputActionSheet.tsx +518 -0
  67. package/src/screens/inbox/components/GiftedChatInboxComponent.tsx +411 -0
  68. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +337 -194
  69. package/src/screens/inbox/components/SlackInput.tsx +23 -0
  70. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
  71. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +1 -1
  72. package/src/screens/inbox/components/SmartLoader.tsx +61 -0
  73. package/src/screens/inbox/components/SubscriptionHandler.tsx +41 -0
  74. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +53 -55
  75. package/src/screens/inbox/components/ThreadsViewItem.tsx +178 -285
  76. package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +145 -0
  77. package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +159 -0
  78. package/src/screens/inbox/config/config.ts +2 -2
  79. package/src/screens/inbox/containers/ConversationView.tsx +1843 -702
  80. package/src/screens/inbox/containers/ConversationView.tsx.bk +1467 -0
  81. package/src/screens/inbox/containers/Dialogs.tsx +402 -204
  82. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +4 -4
  83. package/src/screens/inbox/containers/ThreadConversationView.tsx +1350 -319
  84. package/src/screens/inbox/containers/ThreadsView.tsx +105 -193
  85. package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +20 -0
  86. package/src/screens/inbox/containers/workflow/conversation-xstate.ts +313 -0
  87. package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +196 -0
  88. package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +401 -0
  89. package/src/screens/inbox/hooks/useInboxMessages.ts +34 -0
  90. package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +136 -0
  91. package/src/screens/inbox/index.ts +37 -0
  92. package/src/screens/inbox/machines/threadsMachine.ts +147 -0
  93. package/src/screens/inbox/workflow/dialog-threads-xstate.ts +163 -0
  94. package/tsconfig.json +11 -54
  95. package/lib/screens/inbox/components/DialogsListItem.js +0 -171
  96. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  97. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -171
  98. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
@@ -0,0 +1,518 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import {
3
+ View,
4
+ TouchableOpacity,
5
+ Animated,
6
+ Keyboard,
7
+ Dimensions,
8
+ StyleSheet,
9
+ PanResponder,
10
+ Text,
11
+ TouchableWithoutFeedback,
12
+ Modal,
13
+ Image,
14
+ TextInput,
15
+ KeyboardAvoidingView,
16
+ Platform,
17
+ ScrollView,
18
+ ActivityIndicator,
19
+ } from 'react-native';
20
+ import { HStack } from '@admin-layout/gluestack-ui-mobile';
21
+ import { MaterialIcons, Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
22
+ import colors from 'tailwindcss/colors';
23
+
24
+ const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('window');
25
+ const MAX_HEIGHT = SCREEN_HEIGHT * 0.5; // Half screen height instead of 80%
26
+ const BASE_MIN_HEIGHT = 150; // Default compact height without images
27
+ const IMAGE_PREVIEW_HEIGHT = 90; // Height needed for image preview section including margins
28
+ const HANDLE_HEIGHT = 30;
29
+
30
+ interface ExpandableInputActionSheetProps {
31
+ isVisible: boolean;
32
+ onClose: () => void;
33
+ onSend: () => void;
34
+ onSelectImages: () => void;
35
+ text: string;
36
+ onChangeText: (text: string) => void;
37
+ textInputRef: React.RefObject<any>;
38
+ isSendDisabled: boolean;
39
+ selectedImages: Array<any>;
40
+ onRemoveImage: (index: number) => void;
41
+ loading?: boolean;
42
+ }
43
+
44
+ const ExpandableInputActionSheet = ({
45
+ isVisible,
46
+ onClose,
47
+ onSend,
48
+ onSelectImages,
49
+ text,
50
+ onChangeText,
51
+ textInputRef,
52
+ isSendDisabled,
53
+ selectedImages,
54
+ onRemoveImage,
55
+ loading = false,
56
+ }: ExpandableInputActionSheetProps) => {
57
+ const translateY = useRef(new Animated.Value(MAX_HEIGHT)).current;
58
+ const [isExpanded, setIsExpanded] = useState(false);
59
+ const [isDragging, setIsDragging] = useState(false);
60
+ const inputRef = useRef<TextInput>(null);
61
+
62
+ // Calculate height based on whether we have images
63
+ const getMinHeight = () => {
64
+ return selectedImages.length > 0 ? BASE_MIN_HEIGHT + IMAGE_PREVIEW_HEIGHT : BASE_MIN_HEIGHT;
65
+ };
66
+
67
+ const [sheetHeight, setSheetHeight] = useState(getMinHeight());
68
+
69
+ // Update height when images array changes
70
+ useEffect(() => {
71
+ if (!isExpanded) {
72
+ setSheetHeight(getMinHeight());
73
+ }
74
+ }, [selectedImages.length, isExpanded]);
75
+
76
+ // Add a function to handle text input changes
77
+ const handleTextChange = (newText) => {
78
+ // Update the parent component's state
79
+ onChangeText(newText);
80
+ };
81
+
82
+ // Close animation
83
+ const closeSheet = () => {
84
+ // Ensure any text changes are properly passed to the parent component
85
+ // This ensures the parent component has the latest text state
86
+ if (inputRef.current) {
87
+ inputRef.current.blur();
88
+ }
89
+
90
+ Keyboard.dismiss();
91
+ Animated.timing(translateY, {
92
+ toValue: MAX_HEIGHT,
93
+ duration: 300,
94
+ useNativeDriver: true,
95
+ }).start(() => {
96
+ // Ensure onClose is called after animation completes
97
+ onClose();
98
+ setIsExpanded(false);
99
+ });
100
+ };
101
+
102
+ // Expand the sheet to max height
103
+ const expandSheet = () => {
104
+ setIsExpanded(true);
105
+ setSheetHeight(MAX_HEIGHT);
106
+ };
107
+
108
+ // Collapse the sheet to min height
109
+ const collapseSheet = () => {
110
+ setIsExpanded(false);
111
+ setSheetHeight(getMinHeight());
112
+ };
113
+
114
+ // Toggle expansion when handle is clicked
115
+ const toggleExpansion = () => {
116
+ if (isExpanded) {
117
+ collapseSheet();
118
+ } else {
119
+ expandSheet();
120
+ }
121
+ };
122
+
123
+ // Open animation
124
+ useEffect(() => {
125
+ if (isVisible) {
126
+ // Set initial height based on images
127
+ setSheetHeight(getMinHeight());
128
+ setIsExpanded(false);
129
+
130
+ Animated.timing(translateY, {
131
+ toValue: 0,
132
+ duration: 300,
133
+ useNativeDriver: true,
134
+ }).start(() => {
135
+ // Focus the text input after a small delay to ensure the sheet is visible
136
+ setTimeout(() => {
137
+ if (inputRef.current) {
138
+ inputRef.current.focus();
139
+ }
140
+ }, 100);
141
+ });
142
+ }
143
+ }, [isVisible, translateY, selectedImages.length]);
144
+
145
+ // Handle keyboard showing/hiding
146
+ useEffect(() => {
147
+ const keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', (e) => {
148
+ // Keep height as is when keyboard shows
149
+ if (!isExpanded) {
150
+ setSheetHeight(getMinHeight());
151
+ }
152
+ });
153
+
154
+ const keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', () => {
155
+ if (!isDragging && !isExpanded) {
156
+ setSheetHeight(getMinHeight());
157
+ }
158
+ });
159
+
160
+ return () => {
161
+ keyboardWillShowListener.remove();
162
+ keyboardWillHideListener.remove();
163
+ };
164
+ }, [isDragging, isExpanded, selectedImages.length]);
165
+
166
+ // Create pan responder for drag gestures
167
+ const panResponder = useRef(
168
+ PanResponder.create({
169
+ onStartShouldSetPanResponder: () => true,
170
+ onMoveShouldSetPanResponder: (_, gestureState) => {
171
+ return Math.abs(gestureState.dy) > 5;
172
+ },
173
+ onPanResponderGrant: () => {
174
+ setIsDragging(true);
175
+ translateY.setOffset(-1 * translateY['_value']);
176
+ },
177
+ onPanResponderMove: (_, gestureState) => {
178
+ // Allow dragging down to close or up to expand
179
+ if (gestureState.dy > 0) {
180
+ // Dragging down
181
+ translateY.setValue(gestureState.dy);
182
+ } else if (gestureState.dy < 0 && !isExpanded) {
183
+ // Dragging up (only if not already expanded)
184
+ // Calculate what percentage of full expansion this drag represents
185
+ const expansionPercentage = Math.min(1, Math.abs(gestureState.dy) / 200);
186
+ // Calculate new height based on drag distance
187
+ const additionalHeight = (MAX_HEIGHT - getMinHeight()) * expansionPercentage;
188
+ const newHeight = getMinHeight() + additionalHeight;
189
+ setSheetHeight(newHeight);
190
+ }
191
+ },
192
+ onPanResponderRelease: (_, gestureState) => {
193
+ translateY.flattenOffset();
194
+ setIsDragging(false);
195
+
196
+ // If dragged down significantly, close the sheet
197
+ if (gestureState.dy > 50) {
198
+ closeSheet();
199
+ } else if (gestureState.dy < -50 && !isExpanded) {
200
+ // If dragged up significantly, expand to full height
201
+ expandSheet();
202
+ } else {
203
+ // Otherwise, snap back to current position
204
+ Animated.spring(translateY, {
205
+ toValue: 0,
206
+ useNativeDriver: true,
207
+ tension: 50,
208
+ friction: 7,
209
+ }).start();
210
+
211
+ // If not expanding or closing, restore height to previous state
212
+ if (gestureState.dy > 0 && gestureState.dy <= 50) {
213
+ // Small downward drag, keep current state
214
+ if (isExpanded) {
215
+ setSheetHeight(MAX_HEIGHT);
216
+ } else {
217
+ setSheetHeight(getMinHeight());
218
+ }
219
+ }
220
+ }
221
+ },
222
+ }),
223
+ ).current;
224
+
225
+ return (
226
+ <Modal
227
+ visible={isVisible}
228
+ transparent={true}
229
+ animationType="none"
230
+ onRequestClose={closeSheet}
231
+ statusBarTranslucent={true}
232
+ >
233
+ <KeyboardAvoidingView
234
+ style={styles.container}
235
+ behavior={Platform.OS === 'ios' ? 'padding' : undefined}
236
+ keyboardVerticalOffset={Platform.OS === 'ios' ? 10 : 0}
237
+ >
238
+ <TouchableWithoutFeedback onPress={closeSheet}>
239
+ <View style={styles.backdrop} />
240
+ </TouchableWithoutFeedback>
241
+
242
+ <Animated.View
243
+ style={[
244
+ styles.sheetContainer,
245
+ {
246
+ transform: [{ translateY }],
247
+ height: sheetHeight,
248
+ },
249
+ ]}
250
+ >
251
+ {/* Drag handle with click to expand */}
252
+ <TouchableOpacity style={styles.handleContainer} onPress={toggleExpansion} activeOpacity={0.7}>
253
+ <View style={styles.handle} {...panResponder.panHandlers} />
254
+ </TouchableOpacity>
255
+
256
+ {/* Main content */}
257
+ <View style={styles.sheetContent}>
258
+ {/* Input area at top - always visible */}
259
+ <View style={styles.inputContainer}>
260
+ <TextInput
261
+ ref={inputRef}
262
+ value={text}
263
+ onChangeText={handleTextChange}
264
+ style={[styles.textInput, isExpanded && styles.textInputExpanded]}
265
+ placeholder="Jot something down"
266
+ placeholderTextColor="#888"
267
+ multiline
268
+ numberOfLines={isExpanded ? 5 : 2}
269
+ autoCapitalize="sentences"
270
+ autoCorrect={true}
271
+ blurOnSubmit={false}
272
+ textAlignVertical="top"
273
+ />
274
+ </View>
275
+
276
+ {/* Image preview section - immediately below input, always visible */}
277
+ {selectedImages.length > 0 && (
278
+ <View style={styles.imagePreviewWrapper}>
279
+ <ScrollView
280
+ horizontal
281
+ showsHorizontalScrollIndicator={false}
282
+ style={styles.imagePreviewContainer}
283
+ contentContainerStyle={styles.imagePreviewContent}
284
+ >
285
+ {selectedImages.map((img, index) => (
286
+ <View key={`image-preview-${index}`} style={styles.imagePreview}>
287
+ <View style={styles.imageBox}>
288
+ {img.uri || img.url ? (
289
+ <Image
290
+ source={{ uri: img.uri || img.url }}
291
+ style={{ width: '100%', height: '100%' }}
292
+ resizeMode="cover"
293
+ />
294
+ ) : (
295
+ <View
296
+ style={{
297
+ width: '100%',
298
+ height: '100%',
299
+ backgroundColor: colors.gray[200],
300
+ }}
301
+ />
302
+ )}
303
+ </View>
304
+ <TouchableOpacity
305
+ onPress={() => onRemoveImage(index)}
306
+ style={styles.removeImageButton}
307
+ >
308
+ <Ionicons name="close" size={16} color="white" />
309
+ </TouchableOpacity>
310
+ </View>
311
+ ))}
312
+ </ScrollView>
313
+ </View>
314
+ )}
315
+
316
+ {/* Extra content area - only in expanded mode */}
317
+ {isExpanded && (
318
+ <ScrollView style={styles.extraContentArea} showsVerticalScrollIndicator={false}>
319
+ {/* This area only appears when expanded */}
320
+ <View style={styles.expandedContentPlaceholder} />
321
+ </ScrollView>
322
+ )}
323
+
324
+ {/* Bottom controls always at bottom */}
325
+ <HStack style={styles.controlsContainer}>
326
+ <View style={styles.leftControls}>
327
+ <TouchableOpacity onPress={onSelectImages} style={styles.actionButton}>
328
+ <MaterialIcons name="add" size={24} color="#888" />
329
+ </TouchableOpacity>
330
+ </View>
331
+
332
+ <TouchableOpacity
333
+ onPress={() => {
334
+ // Make sure input is focused and synchronized before sending
335
+ if (inputRef.current) {
336
+ // Force a blur to commit any pending text changes
337
+ inputRef.current.blur();
338
+ // Short timeout to ensure state is updated
339
+ setTimeout(() => {
340
+ onSend();
341
+ }, 50);
342
+ } else {
343
+ onSend();
344
+ }
345
+ }}
346
+ disabled={isSendDisabled || loading}
347
+ style={styles.sendIconContainer}
348
+ >
349
+ <View style={{ padding: 4 }}>
350
+ {loading ? (
351
+ <View
352
+ style={{
353
+ width: 32,
354
+ height: 32,
355
+ alignItems: 'center',
356
+ justifyContent: 'center',
357
+ }}
358
+ >
359
+ <ActivityIndicator size="small" color={colors.blue[400]} />
360
+ </View>
361
+ ) : (
362
+ <MaterialCommunityIcons
363
+ name="send-circle"
364
+ size={32}
365
+ color={isSendDisabled ? colors.gray[400] : colors.blue[500]}
366
+ />
367
+ )}
368
+ </View>
369
+ </TouchableOpacity>
370
+ </HStack>
371
+ </View>
372
+ </Animated.View>
373
+ </KeyboardAvoidingView>
374
+ </Modal>
375
+ );
376
+ };
377
+
378
+ const styles = StyleSheet.create({
379
+ container: {
380
+ flex: 1,
381
+ justifyContent: 'flex-end',
382
+ },
383
+ backdrop: {
384
+ position: 'absolute',
385
+ top: 0,
386
+ left: 0,
387
+ right: 0,
388
+ bottom: 0,
389
+ backgroundColor: 'rgba(0,0,0,0.5)',
390
+ },
391
+ sheetContainer: {
392
+ backgroundColor: 'white',
393
+ borderTopLeftRadius: 20,
394
+ borderTopRightRadius: 20,
395
+ overflow: 'hidden',
396
+ paddingBottom: 15,
397
+ elevation: 5, // For Android
398
+ shadowColor: '#000', // For iOS
399
+ shadowOffset: { width: 0, height: -3 },
400
+ shadowOpacity: 0.2,
401
+ shadowRadius: 5,
402
+ width: SCREEN_WIDTH,
403
+ },
404
+ handleContainer: {
405
+ height: HANDLE_HEIGHT,
406
+ width: '100%',
407
+ alignItems: 'center',
408
+ justifyContent: 'center',
409
+ },
410
+ handle: {
411
+ width: 40,
412
+ height: 5,
413
+ borderRadius: 3,
414
+ backgroundColor: '#ddd',
415
+ },
416
+ sheetContent: {
417
+ flex: 1,
418
+ paddingHorizontal: 15,
419
+ paddingTop: 0,
420
+ flexDirection: 'column',
421
+ justifyContent: 'space-between',
422
+ },
423
+ inputContainer: {
424
+ backgroundColor: '#fff',
425
+ borderRadius: 12,
426
+ padding: 12,
427
+ marginTop: 5,
428
+ // marginBottom: 10,
429
+ },
430
+ textInput: {
431
+ backgroundColor: 'transparent',
432
+ borderWidth: 0,
433
+ fontSize: 16,
434
+ color: '#444',
435
+ paddingVertical: 0,
436
+ paddingHorizontal: 0,
437
+ minHeight: 40,
438
+ },
439
+ textInputExpanded: {
440
+ minHeight: 80,
441
+ maxHeight: 200,
442
+ },
443
+ imagePreviewWrapper: {
444
+ marginBottom: 10,
445
+ },
446
+ imagePreviewContainer: {
447
+ height: 65,
448
+ },
449
+ imagePreviewContent: {
450
+ alignItems: 'center',
451
+ paddingRight: 5,
452
+ },
453
+ extraContentArea: {
454
+ flex: 1,
455
+ marginBottom: 10,
456
+ },
457
+ expandedContentPlaceholder: {
458
+ height: 20,
459
+ },
460
+ controlsContainer: {
461
+ height: 45,
462
+ alignItems: 'center',
463
+ justifyContent: 'space-between',
464
+ paddingHorizontal: 0,
465
+ flexDirection: 'row',
466
+ // borderTopWidth: 1,
467
+ // borderTopColor: colors.gray[200],
468
+ // paddingTop: 5,
469
+ paddingBottom: 10,
470
+ },
471
+ leftControls: {
472
+ flexDirection: 'row',
473
+ alignItems: 'center',
474
+ },
475
+ actionButton: {
476
+ width: 40,
477
+ height: 40,
478
+ borderRadius: 20,
479
+ alignItems: 'center',
480
+ justifyContent: 'center',
481
+ marginRight: 8,
482
+ // padding: 6,
483
+ },
484
+ imagePreview: {
485
+ width: 60,
486
+ height: 60,
487
+ marginRight: 8,
488
+ position: 'relative',
489
+ },
490
+ imageBox: {
491
+ width: '100%',
492
+ height: '100%',
493
+ borderRadius: 8,
494
+ overflow: 'hidden',
495
+ backgroundColor: colors.gray[200],
496
+ },
497
+ removeImageButton: {
498
+ position: 'absolute',
499
+ top: -5,
500
+ right: -5,
501
+ backgroundColor: 'rgba(0,0,0,0.6)',
502
+ borderRadius: 12,
503
+ width: 20,
504
+ height: 20,
505
+ alignItems: 'center',
506
+ justifyContent: 'center',
507
+ zIndex: 10,
508
+ },
509
+ sendIconContainer: {
510
+ width: 48,
511
+ height: 48,
512
+ alignItems: 'center',
513
+ justifyContent: 'center',
514
+ // padding: 6,
515
+ },
516
+ });
517
+
518
+ export default ExpandableInputActionSheet;