UNPKG

2.58 kBJavaScriptView Raw
1import React, { useCallback, useMemo } from 'react';
2import { any, bool, func, number, oneOfType, shape, string } from 'prop-types';
3
4import fromRenderProp from '../util/fromRenderProp';
5
6/**
7 * The **Item** Component is reponsible for rendering each item in list
8 *
9 * @typedef Item
10 * @kind functional component
11 *
12 * @param {props} props
13 *
14 * @returns{React.Element} A React component for rendering each item in list.
15 */
16const Item = props => {
17 const {
18 classes,
19 hasFocus,
20 isSelected,
21 item,
22 itemIndex,
23 render,
24 setFocus,
25 uniqueId: key,
26 updateSelectedKeys,
27 ...restProps
28 } = props;
29
30 const children = typeof item === 'string' ? item : null;
31
32 const onClick = useCallback(() => updateSelectedKeys(key), [
33 key,
34 updateSelectedKeys
35 ]);
36 const onFocus = useCallback(() => setFocus(key), [key, setFocus]);
37
38 const customProps = {
39 classes,
40 hasFocus,
41 isSelected,
42 item,
43 itemIndex,
44 onClick,
45 onFocus
46 };
47
48 const Root = useMemo(
49 () => fromRenderProp(render, Object.keys(customProps)),
50 [render, customProps]
51 );
52
53 return (
54 <Root className={classes.root} {...customProps} {...restProps}>
55 {children}
56 </Root>
57 );
58};
59
60/**
61 * props for {@link Item}
62 *
63 * @typedef props
64 *
65 * @property {Object} classes css classes prop for Item
66 * @property {string} classes.root css classes for Item root container
67 * @property {bool} hasFocus Does the item have focus
68 * @property {bool} isSelected Is the item currently selected
69 * @property {any} item item data
70 * @property {number} itemIndex index of item
71 * @property {func | string} render A render prop for the list item. A tagname string, such as `"div"`, is also valid
72 * @property {func} setFocus A callback for setting focus
73 * @property {number | string} uniqueId unique Id given for the item
74 * @property {func} updateSelectedKeys A callback for updating selected items
75 */
76Item.propTypes = {
77 classes: shape({
78 root: string
79 }),
80 hasFocus: bool,
81 isSelected: bool,
82 item: any.isRequired,
83 itemIndex: number.isRequired,
84 render: oneOfType([func, string]).isRequired,
85 setFocus: func,
86 uniqueId: oneOfType([number, string]).isRequired,
87 updateSelectedKeys: func.isRequired
88};
89
90/**
91 * default props for {@link Item}
92 *
93 * @typedef @defaultProps
94 */
95Item.defaultProps = {
96 classes: {},
97 hasFocus: false,
98 isSelected: false,
99 render: 'div'
100};
101
102export default Item;