-
Notifications
You must be signed in to change notification settings - Fork 682
/
items.js
99 lines (79 loc) 路 2.4 KB
/
items.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { Component, Fragment, createElement } from 'react';
import PropTypes from 'prop-types';
import memoize from '../util/unaryMemoize';
import ListItem from './item';
const removeFocus = () => ({
hasFocus: false
});
const updateCursor = memoize(index => () => ({
cursor: index,
hasFocus: true
}));
const updateSelection = memoize(key => (prevState, props) => {
const { selectionModel } = props;
let selection;
if (selectionModel === 'radio') {
selection = new Set().add(key);
}
if (selectionModel === 'checkbox') {
selection = new Set(prevState.selection);
if (selection.has(key)) {
selection.delete(key);
} else {
selection.add(key);
}
}
return { selection };
});
class Items extends Component {
static propTypes = {
items: PropTypes.oneOfType([
PropTypes.instanceOf(Map),
PropTypes.arrayOf(PropTypes.array)
]).isRequired,
renderItem: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
selectionModel: PropTypes.oneOf(['checkbox', 'radio'])
};
static defaultProps = {
selectionModel: 'radio'
};
state = {
cursor: null,
hasFocus: false,
selection: new Set()
};
render() {
const { items, renderItem } = this.props;
const { cursor, hasFocus, selection } = this.state;
const children = Array.from(items, ([key, item], index) => (
<ListItem
key={key}
item={item}
render={renderItem}
hasFocus={hasFocus && cursor === index}
isSelected={selection.has(key)}
onBlur={this.handleBlur}
onClick={this.getClickHandler(key)}
onFocus={this.getFocusHandler(index)}
/>
));
return <Fragment>{children}</Fragment>;
}
syncSelection() {
const { selection } = this.state;
const { onSelectionChange } = this.props;
if (onSelectionChange) {
onSelectionChange(selection);
}
}
handleBlur = () => {
this.setState(removeFocus);
};
getClickHandler = memoize(key => () => {
this.setState(updateSelection(key), this.syncSelection);
});
getFocusHandler = memoize(index => () => {
this.setState(updateCursor(index));
});
}
export default Items;