Mirror of https://github.com/roostorg/osprey
github.com/roostorg/osprey
1import * as React from 'react';
2import classNames from 'classnames';
3import { chunk } from 'lodash';
4
5import Text, { TextSizes } from '../../uikit/Text';
6import BrandDot from '../../uikit/icons/BrandDot';
7
8import styles from './PropertyTable.module.css';
9
10export type Entries = Record<string, string>;
11type Entry = [string, string];
12
13interface PropertyTableProps {
14 className?: string;
15 entries: Entries[];
16 columns?: number;
17 renderKey?: (entry: Entry) => React.ReactNode;
18 renderValue?: (entry: Entry) => React.ReactNode;
19 shouldHighlightCell?: (entry: Entry) => boolean;
20 shouldWrapText?: boolean;
21}
22
23const PropertyTable = ({
24 className,
25 entries,
26 columns = 3,
27 renderKey,
28 renderValue,
29 shouldHighlightCell,
30 shouldWrapText = false,
31}: PropertyTableProps) => {
32 const entriesAsTuples = entries.map((entry) => Object.entries(entry));
33 let currentRowIndex = 0;
34
35 const renderRow = (entryTuple: Entry[], index: number) => {
36 return (
37 <div key={index} className={(index + 1) % 2 === 0 ? styles.darkRow : styles.row}>
38 {entryTuple.map((entry) => {
39 const [key, value] = entry;
40 const highlightCell = shouldHighlightCell?.(entry);
41
42 return (
43 <div className={classNames(styles.keyValuePair, { [styles.highlightedCell]: highlightCell })} key={key}>
44 <Text className={styles.key} size={TextSizes.SMALL}>
45 {renderKey != null ? renderKey(entry) : key}
46 {highlightCell ? <BrandDot className={styles.highlightDot} /> : null}
47 </Text>
48 <div
49 title={shouldWrapText ? undefined : value}
50 className={shouldWrapText ? styles.value_wrapped : styles.value}
51 >
52 {renderValue != null ? renderValue(entry) : value}
53 </div>
54 </div>
55 );
56 })}
57 </div>
58 );
59 };
60
61 const renderBlock = (entryBlock: Entry[]) => {
62 return chunk(entryBlock, columns).map((block) => {
63 const row = renderRow(block, currentRowIndex);
64 currentRowIndex++;
65 return row;
66 });
67 };
68
69 return <div className={classNames(styles.propertyTable, className)}>{entriesAsTuples.map(renderBlock)}</div>;
70};
71
72export default PropertyTable;