main
js 101 lines 2.56 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import * as React from 'react';
11 import {memo} from 'react';
12 import {areEqual} from 'react-window';
13 import {getGradientColor} from './utils';
14
15 import styles from './SnapshotCommitListItem.css';
16
17 import type {ItemData} from './SnapshotCommitList';
18
19 type Props = {
20 data: ItemData,
21 index: number,
22 style: Object,
23 ...
24 };
25
26 function SnapshotCommitListItem({data: itemData, index, style}: Props) {
27 const {
28 filteredCommitIndices,
29 maxDuration,
30 selectedCommitIndex,
31 selectCommitIndex,
32 setHoveredCommitIndex,
33 startCommitDrag,
34 totalDurations,
35 } = itemData;
36
37 index = filteredCommitIndices[index];
38
39 const totalDuration = totalDurations[index];
40
41 // Use natural cbrt for bar height.
42 // This prevents one (or a few) outliers from squishing the majority of other commits.
43 // So rather than e.g. _█_ we get something more like e.g. ▄█_
44 const heightScale =
45 Math.min(
46 1,
47 Math.max(0, Math.cbrt(totalDuration) / Math.cbrt(maxDuration)),
48 ) || 0;
49
50 // Use a linear scale for color.
51 // This gives some visual contrast between cheaper and more expensive commits
52 // and somewhat compensates for the cbrt scale height.
53 const colorScale = Math.min(1, Math.max(0, totalDuration / maxDuration)) || 0;
54
55 const isSelected = selectedCommitIndex === index;
56
57 // Leave a 1px gap between snapshots
58 const width = parseFloat(style.width) - 1;
59
60 const handleMouseDown = ({buttons, target}: any) => {
61 if (buttons === 1) {
62 selectCommitIndex(index);
63 startCommitDrag({
64 commitIndex: index,
65 left: target.getBoundingClientRect().left,
66 sizeIncrement: parseFloat(style.width),
67 });
68 }
69 };
70
71 let backgroundColor;
72 if (!isSelected && totalDuration > 0) {
73 backgroundColor = getGradientColor(colorScale);
74 }
75
76 return (
77 <div
78 className={styles.Outer}
79 onMouseDown={handleMouseDown}
80 onMouseEnter={() => setHoveredCommitIndex(index)}
81 style={{
82 ...style,
83 width,
84 borderBottom: isSelected
85 ? '3px solid var(--color-tab-selected-border)'
86 : undefined,
87 }}>
88 <div
89 className={isSelected ? styles.InnerSelected : styles.Inner}
90 style={{
91 height: `${Math.round(heightScale * 100)}%`,
92 backgroundColor,
93 }}
94 />
95 </div>
96 );
97 }
98
99 export default memo(SnapshotCommitListItem, areEqual) as component(
100 ...props: Props
101 );