-
Notifications
You must be signed in to change notification settings - Fork 93
/
RatingAPILayer.jsx
152 lines (139 loc) · 4.02 KB
/
RatingAPILayer.jsx
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import React, { PropTypes } from 'react';
import Style from './utils/style';
import Rating from './Rating';
import noop from './utils/noop';
class RatingAPILayer extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
value: props.initialRating
};
this.handleClick = this.handleClick.bind(this);
this.handleHover = this.handleHover.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.initialRating
});
}
componentDidUpdate(prevProps, prevState) {
// If we have a new value trigger onChange callback
if (this.state.value !== prevState.value) {
this.props.onChange(this.state.value);
}
}
handleClick(value, e) {
const newValue = this.translateDisplayValueToValue(value);
// Avoid calling setState if not necessary. Micro optimisation.
if (this.state.value !== newValue) {
this.setState({
value: newValue
});
}
}
handleHover(displayValue) {
const value = displayValue === undefined
? displayValue
: this.translateDisplayValueToValue(displayValue);
this.props.onHover(value);
}
translateDisplayValueToValue(displayValue) {
const translatedValue = displayValue * this.props.step + this.props.start;
// minimum value cannot be equal to start, since it's exclusive
return translatedValue === this.props.start
? translatedValue + 1 / this.props.fractions
: translatedValue;
}
tranlateValueToDisplayValue(value) {
if (value === undefined) {
return 0;
}
return (value - this.props.start) / this.props.step;
}
render() {
const {
step,
emptySymbol,
fullSymbol,
placeholderSymbol,
readonly,
quiet,
fractions,
direction,
start,
stop
} = this.props;
function calculateTotalSymbols(start, stop, step) {
return Math.floor((stop - start) / step);
}
return (
<Rating
totalSymbols={calculateTotalSymbols(start, stop, step)}
value={this.tranlateValueToDisplayValue(this.state.value)}
placeholderValue={this.tranlateValueToDisplayValue(this.props.placeholderRating)}
readonly={readonly}
quiet={quiet}
fractions={fractions}
direction={direction}
emptySymbol={emptySymbol}
fullSymbol={fullSymbol}
placeholderSymbol={placeholderSymbol}
onClick={this.handleClick}
onHover={this.handleHover}
/>
);
}
}
RatingAPILayer.defaultProps = {
start: 0,
stop: 5,
step: 1,
readonly: false,
quiet: false,
fractions: 1,
direction: 'ltr',
onChange: noop,
onHover: noop,
emptySymbol: Style.empty,
fullSymbol: Style.full,
placeholderSymbol: Style.placeholder
};
// Define propTypes only in development.
RatingAPILayer.propTypes = typeof __DEV__ !== 'undefined' && __DEV__ && {
start: PropTypes.number,
stop: PropTypes.number,
step: PropTypes.number,
initialRating: PropTypes.number,
placeholderRating: PropTypes.number,
readonly: PropTypes.bool,
quiet: PropTypes.bool,
fractions: PropTypes.number,
direction: PropTypes.string,
emptySymbol: PropTypes.oneOfType([
// Array of class names and/or style objects.
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element])),
// Class names.
PropTypes.string,
// Style objects.
PropTypes.object
]),
fullSymbol: PropTypes.oneOfType([
// Array of class names and/or style objects.
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element])),
// Class names.
PropTypes.string,
// Style objects.
PropTypes.object
]),
placeholderSymbol: PropTypes.oneOfType([
// Array of class names and/or style objects.
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element])),
// Class names.
PropTypes.string,
// Style objects.
PropTypes.object
]),
onHover: PropTypes.func,
onChange: PropTypes.func
};
export default RatingAPILayer;