UNPKG

modo-mobile

Version:

A mobile UI toolkit, based on React

357 lines (335 loc) 13.9 kB
import _defineProperty from 'babel-runtime/helpers/defineProperty'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _createClass from 'babel-runtime/helpers/createClass'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; import * as React from 'react'; import classNames from 'classnames'; var PickerColumn = function (_React$Component) { _inherits(PickerColumn, _React$Component); function PickerColumn(props) { _classCallCheck(this, PickerColumn); var _this = _possibleConstructorReturn(this, (PickerColumn.__proto__ || Object.getPrototypeOf(PickerColumn)).call(this, props)); _this.scrollHanders = function () { var scrollY = -1; var lastY = 0; var startY = 0; var scrollDisabled = false; var isMoving = false; var setTransform = function setTransform(nodeStyle, value) { nodeStyle.transform = value; nodeStyle.webkitTransform = value; }; var setTransition = function setTransition(nodeStyle, value) { nodeStyle.transition = value; nodeStyle.webkitTransition = value; }; var scrollTo = function scrollTo(_x, y) { var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.3; if (scrollY !== y) { scrollY = y; setTransition(_this.listRef.style, 'cubic-bezier(0,0,0.2,1.15) ' + time + 's'); setTransform(_this.listRef.style, 'translate3d(0,' + -y + 'px,0)'); setTimeout(function () { _this.scrollingComplete(); if (_this.listRef) { setTransition(_this.listRef.style, ''); } }, +time * 1000); } }; var Velocity = function () { var minInterval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30; var maxInterval = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; var _time = 0; var _y = 0; var _velocity = 0; var recorder = { record: function record(y) { var now = +new Date(); _velocity = (y - _y) / (now - _time); if (now - _time >= minInterval) { _velocity = now - _time <= maxInterval ? _velocity : 0; _y = y; _time = now; } }, getVelocity: function getVelocity(y) { if (y !== _y) { recorder.record(y); } return _velocity; } }; return recorder; }(); var onFinish = function onFinish() { isMoving = false; var targetY = scrollY; var height = (_this.props.data.length - 1) * _this.itemHeight; var time = 0.3; var velocity = Velocity.getVelocity(targetY) * 4; if (velocity) { targetY = velocity * 40 + targetY; time = Math.abs(velocity) * 0.1; } if (targetY % _this.itemHeight !== 0) { targetY = Math.round(targetY / _this.itemHeight) * _this.itemHeight; } if (targetY < 0) { targetY = 0; } else if (targetY > height) { targetY = height; } scrollTo(0, targetY, time < 0.3 ? 0.3 : time); _this.onScrollChange(); }; var onStart = function onStart(y) { if (scrollDisabled) { return; } isMoving = true; startY = y; lastY = scrollY; }; var onMove = function onMove(y) { if (scrollDisabled || !isMoving) { return; } scrollY = lastY - y + startY; Velocity.record(scrollY); _this.onScrollChange(); setTransform(_this.listRef.style, 'translate3d(0,' + -scrollY + 'px,0)'); }; return { touchstart: function touchstart(evt) { return onStart(evt.touches[0].screenY); }, mousedown: function mousedown(evt) { return onStart(evt.screenY); }, touchmove: function touchmove(evt) { evt.preventDefault(); onMove(evt.touches[0].screenY); }, mousemove: function mousemove(evt) { evt.preventDefault(); onMove(evt.screenY); }, touchend: function touchend() { return onFinish(); }, touchcancel: function touchcancel() { return onFinish(); }, mouseup: function mouseup() { return onFinish(); }, getValue: function getValue() { return scrollY; }, scrollTo: scrollTo, setDisabled: function setDisabled() { var disabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; scrollDisabled = disabled; } }; }(); _this.onSelect = function (value, itemHeight, scrollTo) { var data = _this.props.data; for (var i = 0, len = data.length; i < len; i++) { if (data[i].value === value) { _this.selectByIndex(i, itemHeight, scrollTo); return; } } _this.selectByIndex(0, itemHeight, scrollTo); }; _this.scrollTo = function (top) { _this.scrollHanders.scrollTo(0, top); }; _this.scrollToWithoutAnimation = function (top) { _this.scrollHanders.scrollTo(0, top, 0); }; _this.onScrollChange = function () { var top = _this.scrollHanders.getValue(); if (top >= 0) { var _data = _this.props.data; var index = _this.computeChildIndex(top, _this.itemHeight, _data.length); if (_this.scrollValue !== index) { _this.scrollValue = index; var item = _data[index]; if (item && _this.props.onScrollChange) { _this.props.onScrollChange(item.value); } else if (!item && console.warn) { console.warn('child not found', item, index); } } } }; _this.computeChildIndex = function (top, itemHeight, childrenLength) { var index = Math.round(top / itemHeight); return Math.min(index, childrenLength - 1); }; _this.scrollingComplete = function () { var top = _this.scrollHanders.getValue(); if (top >= 0) { var _data2 = _this.props.data; var index = _this.computeChildIndex(top, _this.itemHeight, _data2.length); var item = _data2[index]; if (item) { _this.fireValueChange(item.value); } else if (console.warn) { console.warn('child not found', item, index); } } }; _this.fireValueChange = function (value) { if (value !== _this.state.value) { if (!('value' in _this.props)) { _this.setState({ value: value }); } if (_this.props.onValueChange) { _this.props.onValueChange(value); } } }; var valueState = void 0; var _this$props = _this.props, value = _this$props.value, defaultValue = _this$props.defaultValue, data = _this$props.data; if (value !== undefined) { valueState = value; } else if (defaultValue !== undefined) { valueState = defaultValue; } else { valueState = data && data[0] && data[0].value; } _this.state = { value: valueState }; return _this; } _createClass(PickerColumn, [{ key: 'componentDidMount', value: function componentDidMount() { var _this2 = this; var listRef = this.listRef, indicatorRef = this.indicatorRef, maskRef = this.maskRef, rootRef = this.rootRef; var rootHeight = rootRef.getBoundingClientRect().height; var itemHeight = this.itemHeight = indicatorRef.getBoundingClientRect().height; var num = Math.floor(rootHeight / itemHeight); if (num % 2 === 0) { num--; } num--; num /= 2; listRef.style.padding = itemHeight * num + 'px 0'; indicatorRef.style.top = itemHeight * num + 'px'; maskRef.style.backgroundSize = '100% ' + itemHeight * num + 'px'; // this.scrollHanders.setDisabled(this.props.disabled); this.onSelect(this.state.value, this.itemHeight, this.scrollTo); Object.keys(this.scrollHanders).forEach(function (key) { if (key.indexOf('touch') === 0 || key.indexOf('mouse') === 0) { rootRef.addEventListener(key, _this2.scrollHanders[key], false); } }); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { var _this3 = this; Object.keys(this.scrollHanders).forEach(function (key) { if (key.indexOf('touch') === 0 || key.indexOf('mouse') === 0) { _this3.rootRef.removeEventListener(key, _this3.scrollHanders[key]); } }); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var _this4 = this; if ('value' in nextProps) { if (this.state.value !== nextProps.value) { this.setState({ value: nextProps.value }, function () { _this4.onSelect(nextProps.value, _this4.itemHeight, _this4.scrollTo); }); } } // this.scrollHanders.setDisabled(nextProps.disabled); } }, { key: 'shouldComponentUpdate', value: function shouldComponentUpdate(_nextProps, nextState) { return this.state.value !== nextState.value; } }, { key: 'componentDidUpdate', value: function componentDidUpdate() { this.onSelect(this.state.selectedValue, this.itemHeight, this.scrollToWithoutAnimation); } }, { key: 'selectByIndex', value: function selectByIndex(index, itemHeight, zscrollTo) { var data = this.props.data; if (index < 0 || index >= data.length || !itemHeight) { return; } zscrollTo(index * itemHeight); } }, { key: 'getValue', value: function getValue() { if ('value' in this.props) { return this.props.value; } var data = this.props.data; return data && data[0] && data[0].value; } }, { key: 'render', value: function render() { var _this5 = this; var _props = this.props, prefixCls = _props.prefixCls, data = _props.data; var value = this.state.value; var items = data.map(function (item) { var itemCls = classNames(prefixCls + '-item', _defineProperty({}, prefixCls + '-item-selected', item.value === value)); return React.createElement( 'div', { className: itemCls, key: item.value }, item.label ); }); return React.createElement( 'div', { className: '' + prefixCls, ref: function ref(el) { return _this5.rootRef = el; } }, React.createElement('div', { className: prefixCls + '-mask', ref: function ref(el) { return _this5.maskRef = el; } }), React.createElement('div', { className: prefixCls + '-indicator', ref: function ref(el) { return _this5.indicatorRef = el; } }), React.createElement( 'div', { className: prefixCls + '-list', ref: function ref(el) { return _this5.listRef = el; } }, items ) ); } }]); return PickerColumn; }(React.Component); export default PickerColumn;