UNPKG

5.29 kBJavaScriptView Raw
1import React, {PureComponent} from 'react';
2import PropTypes from 'prop-types';
3import classNames from 'classnames';
4
5import dataTests from '../global/data-tests';
6import Avatar, {Size as AvatarSize} from '../avatar/avatar';
7import Checkbox from '../checkbox/checkbox';
8import Icon from '../icon';
9
10import styles from './list.css';
11
12/**
13 * @constructor
14 * @extends {ReactComponent}
15 */
16
17const RING_UNIT = 8;
18const DEFAULT_PADDING = 16;
19
20export default class ListItem extends PureComponent {
21 static propTypes = {
22 scrolling: PropTypes.bool,
23 hover: PropTypes.bool,
24 details: PropTypes.string,
25 disabled: PropTypes.bool,
26 className: PropTypes.string,
27 tabIndex: PropTypes.number,
28 checkbox: PropTypes.bool,
29 description: PropTypes.oneOfType([
30 PropTypes.string,
31 PropTypes.element,
32 PropTypes.array
33 ]),
34 avatar: PropTypes.string,
35 glyph: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
36 icon: PropTypes.string,
37 iconSize: PropTypes.number,
38 rightNodes: PropTypes.oneOfType([
39 PropTypes.string,
40 PropTypes.element,
41 PropTypes.array
42 ]),
43 leftNodes: PropTypes.oneOfType([
44 PropTypes.string,
45 PropTypes.element,
46 PropTypes.array
47 ]),
48 label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
49 level: PropTypes.number,
50 rgItemType: PropTypes.number,
51 rightGlyph: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
52 compact: PropTypes.bool,
53 onClick: PropTypes.func,
54 onCheckboxChange: PropTypes.func,
55 onMouseOver: PropTypes.func,
56 onMouseUp: PropTypes.func,
57 'data-test': PropTypes.string
58 };
59
60 stopBubbling = e => e.stopPropagation();
61
62 render() {
63 /* eslint-disable no-unused-vars */
64 const {
65 scrolling,
66 className,
67 disabled,
68 checkbox,
69 avatar,
70 glyph,
71 icon,
72 rightGlyph,
73 description,
74 label,
75 details,
76 hover,
77 rgItemType,
78 level,
79 tabIndex,
80 compact,
81 onClick,
82 onCheckboxChange,
83 onMouseOver,
84 onMouseUp,
85 rightNodes,
86 leftNodes,
87 ...restProps
88 } = this.props;
89 /* eslint-enable */
90
91 const checkable = checkbox !== undefined;
92 const hasLeftNodes = leftNodes || glyph || avatar;
93 const showCheckbox = checkable && (checkbox || !hasLeftNodes || (hover && !disabled));
94
95 const classes = classNames(styles.item, className, {
96 [styles.action]: !disabled,
97 [styles.hover]: hover && !disabled,
98 [styles.compact]: compact,
99 [styles.scrolling]: scrolling
100 });
101
102 const detailsClasses = classNames({
103 [styles.details]: details,
104 [styles.padded]: icon !== undefined ||
105 checkbox !== undefined ||
106 glyph !== undefined
107 });
108
109 const style = {
110 paddingLeft: `${(+level || 0) * RING_UNIT + DEFAULT_PADDING}px`
111 };
112
113 const labelIsString = typeof label === 'string' || label instanceof String;
114 const dataTest = dataTests({
115 'ring-list-item': (restProps['data-test'] || '').indexOf('ring-list-item') === -1,
116 'ring-list-item-action': !disabled,
117 'ring-list-item-selected': checkbox
118 }, restProps['data-test']);
119
120 return (
121 <div
122 tabIndex={tabIndex}
123 onClick={onClick}
124 onMouseOver={onMouseOver}
125 onMouseUp={onMouseUp}
126 className={classes}
127 data-test={dataTest}
128 style={style}
129 >
130 <div className={styles.top} onMouseOut={this.stopBubbling}>
131 {!showCheckbox && (
132 <div className={styles.left}>
133 {leftNodes}
134 {glyph && (
135 <Icon
136 className={styles.glyph}
137 glyph={glyph}
138 size={this.props.iconSize}
139 />
140 )}
141 {avatar && (
142 <Avatar
143 className={styles.avatar}
144 url={avatar}
145 size={AvatarSize.Size20}
146 />
147 )}
148 </div>
149 )}
150 {showCheckbox && (
151 <div
152 onClick={this.stopBubbling}
153 className={classNames(styles.left, styles.checkboxContainer)}
154 >
155 <Checkbox
156 checked={checkbox}
157 onChange={onCheckboxChange}
158 />
159 </div>
160 )}
161
162 <span
163 className={styles.label}
164 title={labelIsString ? label : ''}
165 data-test="ring-list-item-label"
166 >{label}</span>
167
168 {description && (
169 <span
170 className={styles.description}
171 data-test="ring-list-item-description"
172 >{description}</span>
173 )}
174
175 <div className={styles.right}>
176 {rightGlyph && (
177 <Icon
178 className={styles.rightGlyph}
179 glyph={rightGlyph}
180 size={this.props.iconSize}
181 />
182 )}
183 {icon && (
184 <div
185 className={styles.icon}
186 style={{backgroundImage: `url("${icon}")`}}
187 />
188 )}
189 {rightNodes}
190 </div>
191 </div>
192
193 {details && <div className={detailsClasses}>{details}</div>}
194 </div>
195 );
196 }
197}