-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
ReportActionItemImages.tsx
110 lines (96 loc) · 5.28 KB
/
ReportActionItemImages.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* eslint-disable react/no-array-index-key */
import React from 'react';
import {View} from 'react-native';
import {Polygon, Svg} from 'react-native-svg';
import Text from '@components/Text';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import type {ThumbnailAndImageURI} from '@libs/ReceiptUtils';
import variables from '@styles/variables';
import ReportActionItemImage from './ReportActionItemImage';
type ReportActionItemImagesProps = {
/** array of image and thumbnail URIs */
images: ThumbnailAndImageURI[];
// We're not providing default values for size and total and disabling the ESLint rule
// because we want them to default to the length of images, but we can't set default props
// to be computed from another prop
/** max number of images to show in the row if different than images length */
size?: number;
/** total number of images if different than images length */
total?: number;
/** if the corresponding report action item is hovered */
isHovered?: boolean;
};
/**
* This component displays a row of images in a report action item like a card, such
* as report previews or money request previews which contain receipt images. The maximum of images
* shown in this row is dictated by the size prop, which, if not passed, is just the number of images.
* Otherwise, if size is passed and the number of images is over size, we show a small overlay on the
* last image of how many additional images there are. If passed, total prop can be used to change how this
* additional number when subtracted from size.
*/
function ReportActionItemImages({images, size, total, isHovered = false}: ReportActionItemImagesProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
// Calculate the number of images to be shown, limited by the value of 'size' (if defined)
// or the total number of images.
const numberOfShownImages = Math.min(size ?? images.length, images.length);
const shownImages = images.slice(0, numberOfShownImages);
const remaining = (total ?? images.length) - numberOfShownImages;
const MAX_REMAINING = 9;
// The height varies depending on the number of images we are displaying.
let heightStyle = {};
if (numberOfShownImages === 1) {
heightStyle = StyleUtils.getHeight(variables.reportActionImagesSingleImageHeight);
} else if (numberOfShownImages === 2) {
heightStyle = StyleUtils.getHeight(variables.reportActionImagesDoubleImageHeight);
} else if (numberOfShownImages > 2) {
heightStyle = StyleUtils.getHeight(variables.reportActionImagesMultipleImageHeight);
}
const hoverStyle = isHovered ? styles.reportPreviewBoxHoverBorder : undefined;
const triangleWidth = variables.reportActionItemImagesMoreCornerTriangleWidth;
return (
<View style={[styles.reportActionItemImages, hoverStyle, heightStyle]}>
{shownImages.map(({thumbnail, image, transaction, isLocalFile}, index) => {
const isLastImage = index === numberOfShownImages - 1;
// Show a border to separate multiple images. Shown to the right for each except the last.
const shouldShowBorder = shownImages.length > 1 && index < shownImages.length - 1;
const borderStyle = shouldShowBorder ? styles.reportActionItemImageBorder : {};
return (
<View
key={`${index}-${image as string}`}
style={[styles.reportActionItemImage, borderStyle, hoverStyle]}
>
<ReportActionItemImage
thumbnail={thumbnail}
image={image}
isLocalFile={isLocalFile}
transaction={transaction}
isSingleImage={numberOfShownImages === 1}
/>
{isLastImage && remaining > 0 && (
<View style={[styles.reportActionItemImagesMoreContainer]}>
<View style={[styles.reportActionItemImagesMore, isHovered ? styles.reportActionItemImagesMoreHovered : {}]} />
<Svg
height={triangleWidth}
width={triangleWidth}
style={styles.reportActionItemImagesMoreCornerTriangle}
>
<Polygon
points={`${triangleWidth},0 ${triangleWidth},${triangleWidth} 0,${triangleWidth}`}
fill={isHovered ? theme.border : theme.cardBG}
/>
</Svg>
<Text style={[styles.reportActionItemImagesMoreText, styles.textStrong]}>{remaining > MAX_REMAINING ? `${MAX_REMAINING}+` : `+${remaining}`}</Text>
</View>
)}
</View>
);
})}
</View>
);
}
ReportActionItemImages.displayName = 'ReportActionItemImages';
export default ReportActionItemImages;