1 | 'use strict';
|
2 |
|
3 | exports.__esModule = true;
|
4 |
|
5 | var _extends2 = require('babel-runtime/helpers/extends');
|
6 |
|
7 | var _extends3 = _interopRequireDefault(_extends2);
|
8 |
|
9 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
10 |
|
11 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
12 |
|
13 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
14 |
|
15 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
16 |
|
17 | var _inherits2 = require('babel-runtime/helpers/inherits');
|
18 |
|
19 | var _inherits3 = _interopRequireDefault(_inherits2);
|
20 |
|
21 | var _class, _temp;
|
22 |
|
23 | var _react = require('react');
|
24 |
|
25 | var _react2 = _interopRequireDefault(_react);
|
26 |
|
27 | var _propTypes = require('prop-types');
|
28 |
|
29 | var _propTypes2 = _interopRequireDefault(_propTypes);
|
30 |
|
31 | var _classnames = require('classnames');
|
32 |
|
33 | var _classnames2 = _interopRequireDefault(_classnames);
|
34 |
|
35 | var _reactLifecyclesCompat = require('react-lifecycles-compat');
|
36 |
|
37 | var _icon = require('../icon');
|
38 |
|
39 | var _icon2 = _interopRequireDefault(_icon);
|
40 |
|
41 | var _util = require('../util');
|
42 |
|
43 | var _zhCn = require('../locale/zh-cn');
|
44 |
|
45 | var _zhCn2 = _interopRequireDefault(_zhCn);
|
46 |
|
47 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
48 |
|
49 | var noop = _util.func.noop,
|
50 | bindCtx = _util.func.bindCtx;
|
51 | var ENTER = _util.KEYCODE.ENTER,
|
52 | LEFT = _util.KEYCODE.LEFT,
|
53 | UP = _util.KEYCODE.UP,
|
54 | RIGHT = _util.KEYCODE.RIGHT,
|
55 | DOWN = _util.KEYCODE.DOWN;
|
56 |
|
57 | var supportKeys = [ENTER, LEFT, UP, RIGHT, DOWN];
|
58 |
|
59 |
|
60 | var ICON_SIZE_MAP = {
|
61 | small: 'xs',
|
62 | medium: 'small',
|
63 | large: 'medium'
|
64 | };
|
65 |
|
66 |
|
67 | var Rating = (_temp = _class = function (_Component) {
|
68 | (0, _inherits3.default)(Rating, _Component);
|
69 |
|
70 | Rating.currentValue = function currentValue(min, max, hoverValue, stateValue) {
|
71 | var value = hoverValue ? hoverValue : stateValue;
|
72 |
|
73 | value = value >= max ? max : value;
|
74 | value = value <= min ? min : value;
|
75 |
|
76 | return value || 0;
|
77 | };
|
78 |
|
79 | function Rating(props) {
|
80 | (0, _classCallCheck3.default)(this, Rating);
|
81 |
|
82 | var _this = (0, _possibleConstructorReturn3.default)(this, _Component.call(this, props));
|
83 |
|
84 | _this.saveRef = function (ref, i) {
|
85 | _this['refs-rating-icon-' + i] = ref;
|
86 | };
|
87 |
|
88 | _this.state = {
|
89 | value: 'value' in props ? props.value : props.defaultValue,
|
90 | hoverValue: 0,
|
91 | cleanedValue: null,
|
92 | iconSpace: 0,
|
93 | iconSize: 0,
|
94 | clicked: false
|
95 | };
|
96 | _this.timer = null;
|
97 |
|
98 | bindCtx(_this, ['handleClick', 'handleHover', 'handleLeave', 'onKeyDown']);
|
99 | return _this;
|
100 | }
|
101 |
|
102 | Rating.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
|
103 | var state = {};
|
104 | if ('value' in nextProps) {
|
105 | state.value = nextProps.value || 0;
|
106 | }
|
107 |
|
108 | if ('disabled' in nextProps || 'readOnly' in nextProps || 'isPreview' in nextProps || 'renderPreview' in nextProps) {
|
109 | state.disabled = nextProps.disabled || nextProps.readOnly || nextProps.isPreview && !('renderPreview' in nextProps);
|
110 | }
|
111 |
|
112 | return state;
|
113 | };
|
114 |
|
115 | Rating.prototype.componentDidMount = function componentDidMount() {
|
116 | this.getRenderResult();
|
117 | };
|
118 |
|
119 | Rating.prototype.componentWillUnmount = function componentWillUnmount() {
|
120 | this.clearTimer();
|
121 | };
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | Rating.prototype.clearTimer = function clearTimer() {
|
127 | if (this.timer) {
|
128 | clearTimeout(this.timer);
|
129 | this.timer = null;
|
130 | }
|
131 | };
|
132 |
|
133 | Rating.prototype.getRenderResult = function getRenderResult() {
|
134 | var count = this.props.count;
|
135 | var _state = this.state,
|
136 | iconSpace = _state.iconSpace,
|
137 | iconSize = _state.iconSize;
|
138 |
|
139 | var icon = this['refs-rating-icon-0'];
|
140 |
|
141 | if (icon && this.underlayNode) {
|
142 | var newIconSize = icon.offsetWidth;
|
143 | var newIconSpace = (this.underlayNode.offsetWidth - count * newIconSize) / (count + 1);
|
144 |
|
145 | if (newIconSize !== iconSize || newIconSpace !== iconSpace) {
|
146 | this.setState({
|
147 | iconSpace: newIconSpace,
|
148 | iconSize: newIconSize
|
149 | });
|
150 | }
|
151 | }
|
152 | };
|
153 |
|
154 | Rating.prototype.getValue = function getValue(e) {
|
155 |
|
156 | this.getRenderResult();
|
157 |
|
158 | var _props = this.props,
|
159 | allowHalf = _props.allowHalf,
|
160 | count = _props.count,
|
161 | rtl = _props.rtl;
|
162 | var _state2 = this.state,
|
163 | iconSpace = _state2.iconSpace,
|
164 | iconSize = _state2.iconSize;
|
165 |
|
166 |
|
167 | var pos = e.pageX - this.underlayNode.getBoundingClientRect().left;
|
168 | var fullNum = Math.floor(pos / (iconSpace + iconSize));
|
169 | var surplusNum = (pos - fullNum * (iconSpace + iconSize) - iconSpace) / iconSize;
|
170 | var value = Number(fullNum) + Number(surplusNum.toFixed(1));
|
171 | if (value >= count) {
|
172 | value = count;
|
173 | } else if (allowHalf) {
|
174 | var floorValue = Math.floor(value);
|
175 | if (rtl) {
|
176 | value = value - 0.5 >= floorValue ? floorValue + 1.5 : floorValue + 1;
|
177 | } else {
|
178 | value = value - 0.5 >= floorValue ? floorValue + 1 : floorValue + 0.5;
|
179 | }
|
180 | } else {
|
181 | value = Math.floor(value) + 1;
|
182 | }
|
183 |
|
184 | return rtl ? count - value + 1 : value;
|
185 | };
|
186 |
|
187 | Rating.prototype.handleHover = function handleHover(e) {
|
188 | var _this2 = this;
|
189 |
|
190 | if (this.state.disabled) {
|
191 | return;
|
192 | }
|
193 |
|
194 | var value = this.getValue(e);
|
195 | var onHoverChange = this.props.onHoverChange;
|
196 | var cleanedValue = this.state.cleanedValue;
|
197 |
|
198 | if (cleanedValue !== value) {
|
199 | this.clearTimer();
|
200 |
|
201 | this.timer = setTimeout(function () {
|
202 | _this2.setState({ hoverValue: value, cleanedValue: null }, function () {
|
203 | onHoverChange(value);
|
204 | });
|
205 | }, 0);
|
206 | }
|
207 | };
|
208 |
|
209 | Rating.prototype.handleLeave = function handleLeave() {
|
210 | var onHoverChange = this.props.onHoverChange;
|
211 |
|
212 | if (this.state.disabled) {
|
213 | return;
|
214 | }
|
215 |
|
216 | this.clearTimer();
|
217 |
|
218 | this.setState({
|
219 | hoverValue: 0,
|
220 | cleanedValue: null
|
221 | });
|
222 | onHoverChange(undefined);
|
223 | };
|
224 |
|
225 | Rating.prototype.onKeyDown = function onKeyDown(e) {
|
226 | if (this.state.disabled) {
|
227 | return;
|
228 | }
|
229 |
|
230 | var _props2 = this.props,
|
231 | onKeyDown = _props2.onKeyDown,
|
232 | count = _props2.count;
|
233 | var disabled = this.state.disabled;
|
234 |
|
235 | if (disabled || supportKeys.indexOf(e.keyCode) < 0) {
|
236 | return !onKeyDown || onKeyDown(e);
|
237 | }
|
238 |
|
239 | var _state3 = this.state,
|
240 | hoverValue = _state3.hoverValue,
|
241 | value = _state3.value;
|
242 |
|
243 | var changingValue = hoverValue;
|
244 | if (changingValue === 0) {
|
245 | changingValue = value;
|
246 | }
|
247 |
|
248 | switch (e.keyCode) {
|
249 | case DOWN:
|
250 | case RIGHT:
|
251 | if (changingValue < count) {
|
252 | changingValue += 1;
|
253 | } else {
|
254 | changingValue = 1;
|
255 | }
|
256 | this.handleChecked(changingValue);
|
257 | break;
|
258 | case UP:
|
259 | case LEFT:
|
260 | if (changingValue > 1) {
|
261 | changingValue -= 1;
|
262 | } else {
|
263 | changingValue = count;
|
264 | }
|
265 | this.handleChecked(changingValue);
|
266 | break;
|
267 | case ENTER:
|
268 | this.props.onChange(changingValue);
|
269 | this.setState({
|
270 | value: changingValue,
|
271 | hoverValue: changingValue
|
272 | });
|
273 | break;
|
274 | }
|
275 | return !onKeyDown || onKeyDown(e);
|
276 | };
|
277 |
|
278 | Rating.prototype.handleChecked = function handleChecked(index) {
|
279 | if (this.state.disabled) {
|
280 | return;
|
281 | }
|
282 |
|
283 | this.setState({ hoverValue: index });
|
284 | };
|
285 |
|
286 | Rating.prototype.handleClick = function handleClick(e) {
|
287 | var _this3 = this;
|
288 |
|
289 | if (this.state.disabled) {
|
290 | return;
|
291 | }
|
292 | var allowClear = this.props.allowClear;
|
293 | var value = this.state.value;
|
294 |
|
295 | var newValue = this.getValue(e);
|
296 | var isReset = false;
|
297 | if (allowClear) {
|
298 | isReset = newValue === value;
|
299 | }
|
300 | this.handleLeave();
|
301 | if (newValue < 0) {
|
302 | return;
|
303 | }
|
304 |
|
305 | if (!('value' in this.props)) {
|
306 | this.setState({ value: isReset ? 0 : newValue, clicked: true });
|
307 | }
|
308 |
|
309 | this.props.onChange(isReset ? 0 : newValue);
|
310 | setTimeout(function () {
|
311 | _this3.setState({ clicked: false });
|
312 | }, 100);
|
313 | this.setState({
|
314 | cleanedValue: isReset ? newValue : null
|
315 | });
|
316 | };
|
317 |
|
318 | Rating.prototype.getOverlayWidth = function getOverlayWidth() {
|
319 | var _state4 = this.state,
|
320 | hoverValue = _state4.hoverValue,
|
321 | iconSpace = _state4.iconSpace,
|
322 | iconSize = _state4.iconSize;
|
323 |
|
324 |
|
325 | if (!iconSpace || !iconSize) {
|
326 | return 'auto';
|
327 | }
|
328 |
|
329 | var value = Rating.currentValue(0, this.props.count, hoverValue, this.state.value);
|
330 |
|
331 | var floorValue = Math.floor(value);
|
332 |
|
333 | return iconSize * value + (floorValue + 1) * iconSpace;
|
334 | };
|
335 |
|
336 | Rating.prototype.getInfoLeft = function getInfoLeft() {
|
337 | var _state5 = this.state,
|
338 | value = _state5.value,
|
339 | hoverValue = _state5.hoverValue,
|
340 | iconSpace = _state5.iconSpace,
|
341 | iconSize = _state5.iconSize;
|
342 |
|
343 | var infoValue = hoverValue || value;
|
344 | var ceilValue = Math.ceil(infoValue);
|
345 |
|
346 | return iconSize * (ceilValue - 1) + ceilValue * iconSpace;
|
347 | };
|
348 |
|
349 | Rating.prototype.render = function render() {
|
350 | var _classNames,
|
351 | _classNames2,
|
352 | _classNames3,
|
353 | _this4 = this;
|
354 |
|
355 | var _props3 = this.props,
|
356 | id = _props3.id,
|
357 | prefix = _props3.prefix,
|
358 | className = _props3.className,
|
359 | showGrade = _props3.showGrade,
|
360 | count = _props3.count,
|
361 | size = _props3.size,
|
362 | iconType = _props3.iconType,
|
363 | strokeMode = _props3.strokeMode,
|
364 | readAs = _props3.readAs,
|
365 | rtl = _props3.rtl,
|
366 | isPreview = _props3.isPreview,
|
367 | renderPreview = _props3.renderPreview,
|
368 | locale = _props3.locale;
|
369 | var disabled = this.state.disabled;
|
370 |
|
371 | var others = _util.obj.pickOthers(Rating.propTypes, this.props);
|
372 | var _state6 = this.state,
|
373 | hoverValue = _state6.hoverValue,
|
374 | clicked = _state6.clicked;
|
375 |
|
376 | var underlay = [],
|
377 | overlay = [];
|
378 |
|
379 | var enableA11y = !!id;
|
380 |
|
381 |
|
382 | var value = Rating.currentValue(0, count, hoverValue, this.state.value);
|
383 |
|
384 |
|
385 | var sizeMap = ICON_SIZE_MAP[size];
|
386 |
|
387 | var _loop = function _loop(i) {
|
388 | var _classNames4;
|
389 |
|
390 | var isCurrent = Math.ceil(value - 1) === i;
|
391 | var iconCls = (0, _classnames2.default)((_classNames4 = {
|
392 | hover: hoverValue > 0 && isCurrent,
|
393 | clicked: clicked && isCurrent
|
394 | }, _classNames4[prefix + 'rating-symbol-icon'] = !iconType, _classNames4));
|
395 | var iconNode = iconType ? _react2.default.createElement(_icon2.default, { type: iconType, size: sizeMap, className: iconCls }) : _react2.default.createElement(_icon2.default, { type: 'favorites-filling', size: sizeMap, className: iconCls });
|
396 |
|
397 | var saveRefs = function saveRefs(ref) {
|
398 | _this4.saveRef(ref, i);
|
399 | };
|
400 |
|
401 | underlay.push(_react2.default.createElement(
|
402 | 'span',
|
403 | { ref: saveRefs, key: 'underlay-' + i, className: prefix + 'rating-icon' },
|
404 | iconNode
|
405 | ));
|
406 | if (enableA11y) {
|
407 | overlay.push(_react2.default.createElement('input', {
|
408 | id: id + '-' + prefix + 'star' + (i + 1),
|
409 | key: 'input-' + i,
|
410 | className: prefix + 'sr-only',
|
411 | 'aria-checked': i + 1 === parseInt(hoverValue),
|
412 | checked: i + 1 === parseInt(hoverValue),
|
413 | onChange: _this4.handleChecked.bind(_this4, i + 1),
|
414 | type: 'radio',
|
415 | name: 'rating'
|
416 | }));
|
417 | }
|
418 |
|
419 | overlay.push(_react2.default.createElement(
|
420 | 'label',
|
421 | {
|
422 | key: 'overlay-' + i,
|
423 | htmlFor: enableA11y ? id + '-' + prefix + 'star' + (i + 1) : null,
|
424 | className: prefix + 'rating-icon'
|
425 | },
|
426 | iconNode,
|
427 | enableA11y ? _react2.default.createElement(
|
428 | 'span',
|
429 | { className: prefix + 'sr-only' },
|
430 | readAs(i + 1)
|
431 | ) : null
|
432 | ));
|
433 | };
|
434 |
|
435 | for (var i = 0; i < count; i++) {
|
436 | _loop(i);
|
437 | }
|
438 |
|
439 | var ratingCls = (0, _classnames2.default)([prefix + 'rating', prefix + 'rating-' + size], (_classNames = {}, _classNames[prefix + 'rating-grade-low'] = value <= count * 0.4, _classNames[prefix + 'rating-grade-high'] = value > count * 0.4, _classNames[prefix + 'rating-stroke-mode'] = strokeMode, _classNames.hover = hoverValue > 0, _classNames), className);
|
440 |
|
441 | var baseCls = (0, _classnames2.default)(prefix + 'rating-base', (_classNames2 = {}, _classNames2[prefix + 'rating-base-disabled'] = disabled, _classNames2));
|
442 |
|
443 | var previewCls = (0, _classnames2.default)((_classNames3 = {}, _classNames3[prefix + 'form-preview'] = true, _classNames3[className] = !!className, _classNames3));
|
444 |
|
445 | var overlayStyle = {
|
446 | width: this.getOverlayWidth()
|
447 | };
|
448 | var infoStyle = {
|
449 | left: this.getInfoLeft(),
|
450 | display: hoverValue ? 'block' : 'none'
|
451 | };
|
452 |
|
453 | var finalProps = disabled ? {} : {
|
454 | onClick: this.handleClick,
|
455 | onMouseOver: this.handleHover,
|
456 | onMouseMove: this.handleHover,
|
457 | onMouseLeave: this.handleLeave
|
458 | };
|
459 |
|
460 | if (rtl) {
|
461 | others.dir = 'rtl';
|
462 | }
|
463 |
|
464 | if (isPreview && 'renderPreview' in this.props) {
|
465 | return _react2.default.createElement(
|
466 | 'div',
|
467 | (0, _extends3.default)({ id: id }, others, { className: previewCls }),
|
468 | renderPreview(value, this.props)
|
469 | );
|
470 | }
|
471 |
|
472 | return _react2.default.createElement(
|
473 | 'div',
|
474 | (0, _extends3.default)({
|
475 | id: id
|
476 | }, others, {
|
477 | className: ratingCls,
|
478 | onKeyDown: this.onKeyDown,
|
479 | tabIndex: '0',
|
480 | role: 'group',
|
481 | 'aria-label': locale.description
|
482 | }),
|
483 | _react2.default.createElement(
|
484 | 'div',
|
485 | (0, _extends3.default)({ className: baseCls }, finalProps),
|
486 | _react2.default.createElement(
|
487 | 'div',
|
488 | { className: prefix + 'rating-underlay', ref: function ref(n) {
|
489 | return _this4.underlayNode = n;
|
490 | }, 'aria-hidden': true },
|
491 | underlay
|
492 | ),
|
493 | _react2.default.createElement(
|
494 | 'div',
|
495 | { className: prefix + 'rating-overlay', style: overlayStyle, onClick: function onClick(e) {
|
496 | return e.preventDefault();
|
497 | } },
|
498 | overlay
|
499 | )
|
500 | ),
|
501 | showGrade ? _react2.default.createElement(
|
502 | 'div',
|
503 | { className: prefix + 'rating-info', style: infoStyle },
|
504 | readAs(value)
|
505 | ) : null
|
506 | );
|
507 | };
|
508 |
|
509 | return Rating;
|
510 | }(_react.Component), _class.propTypes = {
|
511 | prefix: _propTypes2.default.string,
|
512 | |
513 |
|
514 |
|
515 | defaultValue: _propTypes2.default.number,
|
516 | |
517 |
|
518 |
|
519 | value: _propTypes2.default.number,
|
520 | |
521 |
|
522 |
|
523 | count: _propTypes2.default.number,
|
524 | |
525 |
|
526 |
|
527 | showGrade: _propTypes2.default.bool,
|
528 | |
529 |
|
530 |
|
531 | size: _propTypes2.default.oneOf(['small', 'medium', 'large']),
|
532 | |
533 |
|
534 |
|
535 | allowHalf: _propTypes2.default.bool,
|
536 | |
537 |
|
538 |
|
539 | allowClear: _propTypes2.default.bool,
|
540 | |
541 |
|
542 |
|
543 |
|
544 | onChange: _propTypes2.default.func,
|
545 | |
546 |
|
547 |
|
548 |
|
549 | onHoverChange: _propTypes2.default.func,
|
550 | |
551 |
|
552 |
|
553 | disabled: _propTypes2.default.bool,
|
554 | |
555 |
|
556 |
|
557 | readAs: _propTypes2.default.func,
|
558 |
|
559 | iconType: _propTypes2.default.string,
|
560 |
|
561 | strokeMode: _propTypes2.default.bool,
|
562 | className: _propTypes2.default.string,
|
563 | id: _propTypes2.default.string,
|
564 | rtl: _propTypes2.default.bool,
|
565 | |
566 |
|
567 |
|
568 | locale: _propTypes2.default.object,
|
569 | |
570 |
|
571 |
|
572 | isPreview: _propTypes2.default.bool,
|
573 | |
574 |
|
575 |
|
576 |
|
577 | renderPreview: _propTypes2.default.func,
|
578 | |
579 |
|
580 |
|
581 | readOnly: _propTypes2.default.bool
|
582 | }, _class.defaultProps = {
|
583 | prefix: 'next-',
|
584 | size: 'medium',
|
585 | disabled: false,
|
586 | readOnly: false,
|
587 | isPreview: false,
|
588 | count: 5,
|
589 | showGrade: false,
|
590 | defaultValue: 0,
|
591 | readAs: function readAs(val) {
|
592 | return val;
|
593 | },
|
594 | allowHalf: false,
|
595 | allowClear: false,
|
596 | onChange: noop,
|
597 | onHoverChange: noop,
|
598 | locale: _zhCn2.default.Rating
|
599 | }, _temp);
|
600 | Rating.displayName = 'Rating';
|
601 | exports.default = (0, _reactLifecyclesCompat.polyfill)(Rating);
|
602 | module.exports = exports['default']; |
\ | No newline at end of file |