-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
/
MakeSelectable.js
110 lines (93 loc) · 3.26 KB
/
MakeSelectable.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
100
101
102
103
104
105
106
107
108
109
110
import React, {Component, PropTypes} from 'react';
import {fade} from '../utils/colorManipulator';
import deprecated from '../utils/deprecatedPropType';
export const MakeSelectable = (Component) => {
return class extends Component {
static propTypes = {
children: PropTypes.node,
onChange: PropTypes.func,
selectedItemStyle: PropTypes.object,
value: PropTypes.any,
valueLink: deprecated(PropTypes.shape({
value: PropTypes.any,
requestChange: PropTypes.func,
}), 'This property is deprecated due to his low popularity. Use the value and onChange property.'),
};
static contextTypes = {
muiTheme: PropTypes.object.isRequired,
};
getValueLink(props) {
return props.valueLink || {
value: props.value,
requestChange: props.onChange,
};
}
extendChild(child, styles, selectedItemStyle) {
if (child && child.type && child.type.muiName === 'ListItem') {
const selected = this.isChildSelected(child, this.props);
let selectedChildrenStyles;
if (selected) {
selectedChildrenStyles = Object.assign({}, styles, selectedItemStyle);
}
const mergedChildrenStyles = Object.assign({}, child.props.style, selectedChildrenStyles);
this.keyIndex += 1;
return React.cloneElement(child, {
onTouchTap: (event) => {
this.handleItemTouchTap(event, child);
if (child.props.onTouchTap) {
child.props.onTouchTap(event);
}
},
key: this.keyIndex,
style: mergedChildrenStyles,
nestedItems: child.props.nestedItems.map((child) => this.extendChild(child, styles, selectedItemStyle)),
initiallyOpen: this.isInitiallyOpen(child),
});
} else {
return child;
}
}
isInitiallyOpen(child) {
if (child.props.initiallyOpen) {
return child.props.initiallyOpen;
}
return this.hasSelectedDescendant(false, child);
}
hasSelectedDescendant = (previousValue, child) => {
if (React.isValidElement(child) && child.props.nestedItems && child.props.nestedItems.length > 0) {
return child.props.nestedItems.reduce(this.hasSelectedDescendant, previousValue);
}
return previousValue || this.isChildSelected(child, this.props);
};
isChildSelected(child, props) {
return this.getValueLink(props).value === child.props.value;
}
handleItemTouchTap = (event, item) => {
const valueLink = this.getValueLink(this.props);
const itemValue = item.props.value;
if (itemValue !== valueLink.value) {
valueLink.requestChange(event, itemValue);
}
};
render() {
const {
children,
selectedItemStyle,
} = this.props;
this.keyIndex = 0;
const styles = {};
if (!selectedItemStyle) {
const textColor = this.context.muiTheme.baseTheme.palette.textColor;
styles.backgroundColor = fade(textColor, 0.2);
}
return (
<Component {...this.props} {...this.state}>
{React.Children.map(children, (child) => (
this.extendChild(child, styles, selectedItemStyle))
)}
</Component>
);
}
};
};
export default MakeSelectable;