UNPKG

3.24 kBJavaScriptView Raw
1import React, { useMemo, useCallback } from 'react';
2import {
3 array,
4 func,
5 object,
6 oneOf,
7 oneOfType,
8 shape,
9 string
10} from 'prop-types';
11
12import fromRenderProp from '../util/fromRenderProp';
13import iterable from '../validators/iterable';
14import Items from './items';
15
16/**
17 * The **List** component maps a collection of data objects into an array of elements.
18 * It also manages the selection and focus of those elements.
19 *
20 * @typedef List
21 * @kind functional component
22 *
23 * @param {props} props React Component props
24 *
25 * @returns{React.Element} A React component that displays list data.
26 */
27const List = props => {
28 const {
29 classes,
30 getItemKey,
31 initialSelection,
32 items,
33 render,
34 renderItem,
35 onSelectionChange,
36 selectionModel,
37 ...restProps
38 } = props;
39
40 const customProps = {
41 classes,
42 getItemKey,
43 items,
44 onSelectionChange,
45 selectionModel
46 };
47
48 const handleSelectionChange = useCallback(
49 selection => {
50 if (onSelectionChange) {
51 onSelectionChange(selection);
52 }
53 },
54 [onSelectionChange]
55 );
56
57 const Root = useMemo(
58 () => fromRenderProp(render, Object.keys(customProps)),
59 [render, customProps]
60 );
61
62 return (
63 <Root className={classes.root} {...customProps} {...restProps}>
64 <Items
65 getItemKey={getItemKey}
66 initialSelection={initialSelection}
67 items={items}
68 renderItem={renderItem}
69 selectionModel={selectionModel}
70 onSelectionChange={handleSelectionChange}
71 />
72 </Root>
73 );
74};
75
76/**
77 * props for {@link List}
78 *
79 * @typedef props
80 *
81 * @property {Object} classes css classes prop for List
82 * @property {string} classes.root css classes for List root container
83 * @property {func} getItemKey item key value getter
84 * @property {array | object} initialSelection A single or list of objects that should start off selected
85 * @property {iterable} items An iterable that yields `[key, item]` pairs such as an ES2015 Map
86 * @property {func | string} render A render prop for the list element. A tagname string, such as `"div"`, is also valid.
87 * @property {func | string} renderItem A render prop for the list item elements. A tagname string, such as `"div"`, is also valid
88 * @property {func} onSelectionChange A callback that fires when the selection state changes
89 * @property {checkbox | radio} selectionModel A string corresponding to a selection model
90 */
91List.propTypes = {
92 classes: shape({
93 root: string
94 }),
95 getItemKey: func.isRequired,
96 initialSelection: oneOfType([array, object]),
97 items: iterable.isRequired,
98 render: oneOfType([func, string]).isRequired,
99 renderItem: oneOfType([func, string]),
100 onSelectionChange: func,
101 selectionModel: oneOf(['checkbox', 'radio'])
102};
103
104/**
105 * default props for {@link List}
106 *
107 * @typedef defaultProps
108 */
109List.defaultProps = {
110 classes: {},
111 getItemKey: ({ id }) => id,
112 items: [],
113 render: 'div',
114 renderItem: 'div',
115 selectionModel: 'radio'
116};
117
118export default List;