diff --git a/.babelrc b/.babelrc index 0bc4e4b..ae42091 100755 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { - "presets": ["react", "es2015", "stage-0"], + "presets": ["es2015", "react", "stage-0"] } diff --git a/.github/preview.gif b/.github/preview.gif index 47709d7..1677091 100644 Binary files a/.github/preview.gif and b/.github/preview.gif differ diff --git a/README.md b/README.md index ee26818..b6c9dca 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # react-mobile-datepicker [![Travis][build-badge]][build] [![npm package][npm-badge]][npm] [![Coveralls][coveralls-badge]][coveralls] -一个移动端时间选择器react组件 ---------------------------------------- + +**a lightweight react date picker for mobile, Not more than 4k** + +react-mobile-datepicker provides a component that can set year, month and day by sliding up or down. + +
@@ -10,72 +14,93 @@ -安装 ------------- + +## Getting Started + +### Install + Using [npm](https://www.npmjs.com/): $ npm install react-mobile-datepicker --save +### Import what you need +The following guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc. -然后,使用模块加载工具流,支持common.js或ES2015模块,例如[webpack](https://github.com/webpack/webpack) ```js // Using an ES6 transpiler like Babel +import React from 'react'; +import ReactDOM from 'react-dom'; import DatePicker from 'react-mobile-datepicker'; -import 'react-mobile-datepicker/dist/mobile-datepicker.css'; // Make sure to import the default stylesheet - -// Not using an ES6 transpiler -var DatePicker = require('react-mobile-datepicker'); -require('react-mobile-datepicker/dist/mobile-datepicker.css'); ``` -使用 ------------- -### 例子 -```js -import React, { Component } from 'react'; -import { render } from 'react-dom'; -import DatePicker from 'mobile-datepicker'; -import 'react-mobile-datepicker/dist/mobile-datepicker.css'; // only needs to be imported once - -// Render the Calendar -var today = new Date(); -var minDate = Number(new Date()) - (24*60*60*1000) * 7; // One week before today +### Usage Example - -render( - { console.log(time); }} />, - document.getElementById('root') -); +```js +class App extends React.Component { + state = { + time: new Date(), + isOpen: false, + } + + handleClick = () => { + this.setState({ isOpen: true }); + } + + handleSelect = (time) => { + this.setState({ time, isOpen: false }); + } + + render() { + return ( +
+ + select time + +

+ {convertDate(this.state.time, 'YYYY-MM-DD')} +

+ + +
+ ); + } +} + + +ReactDOM.render(, document.getElementById('react-box')); ``` -Prop Types ------------- +## PropTypes | Property | Type | Default | Description | |:------------- |:------------- |:-------------- |:---------- | -| btnColor | String | #fff | 完成按钮颜色 | -| dateColor | String | #fff | 日期文字颜色 | -| layerBackground | String | #ffa70b | 背景颜色 | -| date | Date | new Date() | 初始日期 | -| minDate | Date | 前一周 | 最小日期 | -| maxDate | Date | new Date() | 最大日期 | -| onSelect | Function | () => {} | 点击完成后的回调函数, Date对象作为参数 | - -Changelog -------------- - -v1.0.3 - Thu, 23 Jun 2016 13:22:13 GMT --------------------------------------- - -- [5a93fe9](../../commit/5a93fe9) [changed] 更新了READEME - +| btnColor | String | #fff | done button color | +| dateColor | String | #fff | date of text color | +| layerBackground | String | #ffa70b | background color | +| date | Date | new Date() | date value | +| minDate | Date | new Date(1970, 0, 1) | minimum date | +| maxDate | Date | new Date(2050, 0, 1) | maximum date | +| onSelect | Function | () => {} | the callback function after click button of done, Date object as a parameter | + +## Changelog +* [Changelog](CHANGELOG.md) + +## How to Contribute + +Anyone and everyone is welcome to contribute to this project. The best way to +start is by checking our [open issues](https://github.com/lanjingling0510/react-mobile-datepicker/issues), +[submit a new issues](https://github.com/lanjingling0510/react-mobile-datepicker/issues/new?labels=bug) or +[feature request](https://github.com/lanjingling0510/react-mobile-datepicker/issues/new?labels=enhancement), +participate in discussions, upvote or downvote the issues you like or dislike. diff --git a/dist/mobile-datepicker.css b/dist/mobile-datepicker.css deleted file mode 100644 index 29b362e..0000000 --- a/dist/mobile-datepicker.css +++ /dev/null @@ -1 +0,0 @@ -.datepicker{position:absolute;left:0;bottom:0;width:100%;z-index:1;border-top:2px solid #d7d4d4;height:244px;font-size:12px}.datepicker .datepicker-navbar{background:hsla(30,7%,95%,.3);padding:.5em .8em;text-align:right}.datepicker .datepicker-finish-btn{font:1.2em/17px 微软雅黑}.datepicker .datepicker-content{display:-webkit-box;display:-ms-flexbox;display:flex;position:absolute;top:39px;bottom:0;left:0;right:0;margin:0 .5em .5em}.datepicker .datepicker-viewport{padding-top:84px;-webkit-box-flex:1;-ms-flex:1;flex:1;background-image:-webkit-linear-gradient(top,hsla(0,0%,100%,.2) 20%,hsla(0,0%,100%,.7) 50%,hsla(0,0%,100%,.2));background-image:linear-gradient(180deg,hsla(0,0%,100%,.2) 20%,hsla(0,0%,100%,.7) 50%,hsla(0,0%,100%,.2));margin:0 .5em}.datepicker .datepicker-scroll{-webkit-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-perspective:800px;perspective:800px;position:relative;list-style-type:none;height:33px;z-index:-1}.datepicker .datepicker-scroll>li{text-align:center;position:absolute;top:0;left:0;font-size:1.5em;width:100%;line-height:35px} \ No newline at end of file diff --git a/dist/mobile-datepicker.js b/dist/mobile-datepicker.js deleted file mode 100644 index 07c05f5..0000000 --- a/dist/mobile-datepicker.js +++ /dev/null @@ -1,704 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("react")); - else if(typeof define === 'function' && define.amd) - define(["react"], factory); - else if(typeof exports === 'object') - exports["DatePicker"] = factory(require("react")); - else - root["DatePicker"] = factory(root["react"]); -})(this, function(__WEBPACK_EXTERNAL_MODULE_3__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = "/"; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - __webpack_require__(1); - - var _DatePicker = __webpack_require__(2); - - var _DatePicker2 = _interopRequireDefault(_DatePicker); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - exports.default = _DatePicker2.default; - -/***/ }, -/* 1 */ -/***/ function(module, exports) { - - // removed by extract-text-webpack-plugin - -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _DatePickerItem = __webpack_require__(4); - - var _DatePickerItem2 = _interopRequireDefault(_DatePickerItem); - - var _time = __webpack_require__(5); - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * @module DatePicker组件 - */ - - /** - * Class DatePicker组件类 - * @extends Component - */ - - var DatePicker = function (_Component) { - _inherits(DatePicker, _Component); - - function DatePicker(props) { - _classCallCheck(this, DatePicker); - - // 容器转过的角度 - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(DatePicker).call(this, props)); - - _this.state = { - date: _this._productDate(props.date), - minDate: _this._productDate(props.minDate), - maxDate: _this._productDate(props.maxDate) - }; - - _this.handleFinishBtnClick = _this.handleFinishBtnClick.bind(_this); - _this.handleDateSelect = _this.handleDateSelect.bind(_this); - return _this; - } - - _createClass(DatePicker, [{ - key: 'componentWillReceiveProps', - value: function componentWillReceiveProps(nextProps) { - this.setState({ - date: this._productDate(nextProps.date), - minDate: this._productDate(nextProps.minDate), - maxDate: this._productDate(nextProps.maxDate) - }); - } - }, { - key: 'shouldComponentUpdate', - value: function shouldComponentUpdate(nextProps, nextState) { - return nextState.date.timestamp !== this.state.date.timestamp || nextProps.date !== this.props.date || nextProps.minDate !== this.props.minDate || nextProps.maxDate !== this.props.maxDate; - } - }, { - key: '_productDate', - value: function _productDate(date) { - var nDate = (0, _time.nextDate)(date, 0); - return { - value: nDate, - timestamp: nDate.getTime(), - Year: (0, _time.getTime)(nDate, 'Year'), - Month: (0, _time.getTime)(nDate, 'Month'), - Date: (0, _time.getTime)(nDate, 'Date') - }; - } - - /** - * 点击完成按钮事件 - * @return {undefined} - */ - - }, { - key: 'handleFinishBtnClick', - value: function handleFinishBtnClick() { - this.props.onSelect(this.state.date.value); - } - - /** - * 选择下一个日期 - * @return {undefined} - */ - - }, { - key: 'handleDateSelect', - value: function handleDateSelect(date) { - this.setState({ date: this._productDate(date) }); - } - - /** - * render函数 - * @return {Object} JSX对象 - */ - - }, { - key: 'render', - value: function render() { - var _props = this.props; - var layerBackground = _props.layerBackground; - var btnColor = _props.btnColor; - var touchLen = _props.touchLen; - var dateColor = _props.dateColor; - var _state = this.state; - var date = _state.date; - var minDate = _state.minDate; - var maxDate = _state.maxDate; - - var datePickerStyle = { - backgroundColor: layerBackground - }; - - return _react2.default.createElement( - 'div', - { - className: 'datepicker', - style: datePickerStyle }, - _react2.default.createElement( - 'p', - { className: 'datepicker-navbar' }, - _react2.default.createElement( - 'span', - { - style: { color: btnColor }, - className: 'datepicker-finish-btn', - onClick: this.handleFinishBtnClick }, - '完成' - ) - ), - _react2.default.createElement( - 'div', - { className: 'datepicker-content' }, - _react2.default.createElement(_DatePickerItem2.default, { - date: date, - typeName: 'Year', - minDate: minDate, - maxDate: maxDate, - touchLen: touchLen, - dateColor: dateColor, - onSelect: this.handleDateSelect }), - _react2.default.createElement(_DatePickerItem2.default, { - date: date, - typeName: 'Month', - minDate: minDate, - maxDate: maxDate, - touchLen: touchLen, - dateColor: dateColor, - onSelect: this.handleDateSelect }), - _react2.default.createElement(_DatePickerItem2.default, { - date: date, - typeName: 'Date', - minDate: minDate, - maxDate: maxDate, - touchLen: touchLen, - dateColor: dateColor, - onSelect: this.handleDateSelect }) - ) - ); - } - }]); - - return DatePicker; - }(_react.Component); - - DatePicker.propTypes = { - touchLen: _react.PropTypes.number, - btnColor: _react.PropTypes.string, - dateColor: _react.PropTypes.string, - layerBackground: _react.PropTypes.string, - date: _react.PropTypes.object, - minDate: _react.PropTypes.object, - maxDate: _react.PropTypes.object, - onSelect: _react.PropTypes.func - }; - - DatePicker.defaultProps = { - touchLen: 40, - dateColor: '#fff', - btnColor: '#fff', - layerBackground: '#ffa70b', - date: new Date(), - minDate: new Date(1970, 0, 1), - maxDate: new Date(2050, 0, 1), - onSelect: function onSelect() {} - }; - - exports.default = DatePicker; - -/***/ }, -/* 3 */ -/***/ function(module, exports) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_3__; - -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - - var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - - var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - - var _react = __webpack_require__(3); - - var _react2 = _interopRequireDefault(_react); - - var _time = __webpack_require__(5); - - var TimeUtil = _interopRequireWildcard(_time); - - var _transition = __webpack_require__(6); - - function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - - function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - - function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - - function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - /** - * @module Date组件 - */ - - - /** - * Class Date组件类 - * @extends Component - */ - - var DatePickerItem = function (_Component) { - _inherits(DatePickerItem, _Component); - - function DatePickerItem(props) { - _classCallCheck(this, DatePickerItem); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(DatePickerItem).call(this, props)); - - _this.animating = false; // 判断是否在transition过渡动画之中 - _this.touchY = 0; // 保存touchstart的pageY - _this.angle = 0; // 容器转过的角度 - _this.renderDatepickerItem = _this.renderDatepickerItem.bind(_this); - _this.handleContentTouch = _this.handleContentTouch.bind(_this); - _this.handleContentTransitionEnd = _this.handleContentTransitionEnd.bind(_this); - _this.state = { - angle: 0 - }; - return _this; - } - - _createClass(DatePickerItem, [{ - key: 'componentWillMount', - value: function componentWillMount() { - var _this2 = this; - - var dates = Array.apply(undefined, _toConsumableArray(Array(5))).map(function (value, index) { - var date = TimeUtil['next' + _this2.props.typeName](_this2.props.date.value, index - 2); - return _extends({}, TimeUtil.getTime(date, _this2.props.typeName), { - angle: (2 - index) * 22.5 - }); - }); - this.setState({ dates: dates }); - } - }, { - key: 'componentWillReceiveProps', - value: function componentWillReceiveProps(nextProps) { - // 更新同级的组件日期视图 - var scroll = this.refs.scroll; - var angle = this.angle; - var typeName = this.props.typeName; - var nowVal = this.props.date[typeName].value; - var nextVal = nextProps.date[typeName].value; - var nowstamp = this.props.date.timestamp; - var nextstamp = nextProps.date.timestamp; - - var direction = void 0; - if (nextVal > nowVal && nextstamp > nowstamp || nextVal < nowVal && nextstamp > nowstamp) direction = 1;else if (nextVal > nowVal && nextstamp < nowstamp || nextVal < nowVal && nextstamp < nowstamp) direction = -1; - if (direction) { - this._moveTo(scroll, angle + direction * 22.5); - } - } - - /** - * 根据角度返回透明度(0-1之间) - * @param {number} angle 角度 - * @return - */ - - }, { - key: '_setOpacity', - value: function _setOpacity(angle) { - return angle > 0 ? ((40 - angle) / 40 * 100 | 0) / 100 : ((40 + angle) / 40 * 100 | 0) / 100; - } - - /** - * 清除对象的transition样式 - * @param {Dom} obj 指定的对象 - * @return {undefined} - */ - - }, { - key: '_clearTransition', - value: function _clearTransition(obj) { - obj.style[_transition.TRANSITION] = ''; // eslint-disable-line - } - - /** - * 滑动到下一日期 - * @param {number} direction 滑动方向 - * @return {undefined} - */ - - }, { - key: '_moveToNext', - value: function _moveToNext(direction) { - var _props = this.props; - var typeName = _props.typeName; - var date = _props.date; - var maxDate = _props.maxDate; - var minDate = _props.minDate; - - var nextDate = TimeUtil['next' + typeName](date.value, direction); - var canMove = direction === 1 ? nextDate.getTime() <= maxDate.timestamp : nextDate.getTime() >= minDate.timestamp; - if (canMove) { - this.props.onSelect(nextDate); - } else { - this._moveTo(this.refs.scroll, this.angle); - } - } - - /** - * 添加滑动动画 - * @param {DOM} obj DOM对象 - * @param {number} angle 角度 - * @return {undefined} - */ - - }, { - key: '_moveTo', - value: function _moveTo(obj, angle) { - this.animating = true; - obj.style[_transition.TRANSITION] = 'all .2s ease-out'; // eslint-disable-line - this.setState({ - angle: angle - }); - } - - /** - * 滑动日期选择器事件 - * @param {Object} event 事件对象 - * @return {undefined} - */ - - }, { - key: 'handleContentTouch', - value: function handleContentTouch(event) { - event.preventDefault(); - if (this.animating) return; - if (event.type === 'touchstart') { - this.touchY = event.targetTouches[0].pageY; - this.angle = this.state.angle; - } else if (event.type === 'touchmove') { - var touchY = event.targetTouches[0].pageY; - var dir = touchY - this.touchY; - var angle = this.angle - parseInt(22.5 * dir / 180, 10); - this.setState({ angle: angle }); - } else if (event.type === 'touchend') { - var _touchY = event.changedTouches[0].pageY; - var _dir = _touchY - this.touchY; - var direction = _dir > 0 ? -1 : 1; - if (direction === 1 && this.props.touchLen < -_dir || direction === -1 && this.props.touchLen < _dir) { - this._moveToNext(direction); - } else { - this._moveTo(this.refs.scroll, this.angle); - } - } - } - - /** - * transition过渡完成事件 - * @return {undefined} - */ - - }, { - key: 'handleContentTransitionEnd', - value: function handleContentTransitionEnd() { - var _this3 = this; - - var date = this.props.date; - var newDates = Array.apply(undefined, _toConsumableArray(Array(5))).map(function (value, index) { - var now = TimeUtil['next' + _this3.props.typeName](date.value, index - 2); - return _extends({}, TimeUtil.getTime(now, _this3.props.typeName), { - angle: (2 - index) * 22.5 - }); - }); - - this.animating = false; - this._clearTransition(this.refs.scroll); - this.setState({ - dates: newDates, - angle: 0 - }); - } - - /** - * 渲染一个日期DOM对象 - * @param {Object} date date数据 - * @return {Object} JSX对象 - */ - - }, { - key: 'renderDatepickerItem', - value: function renderDatepickerItem(date, index) { - var _itemStyle; - - var itemStyle = (_itemStyle = {}, _defineProperty(_itemStyle, _transition.TRANSFORM, 'rotateX(' + date.angle + 'deg) translate3d(0,0,100px)'), _defineProperty(_itemStyle, 'opacity', this._setOpacity(date.angle + this.state.angle)), _defineProperty(_itemStyle, 'color', this.props.dateColor), _itemStyle); - return _react2.default.createElement( - 'li', - { - key: index, - style: itemStyle }, - date.value, - date.suffix - ); - } - }, { - key: 'render', - value: function render() { - var scrollStyle = _defineProperty({}, _transition.TRANSFORM, 'rotateX(' + this.state.angle + 'deg)'); - - return _react2.default.createElement( - 'div', - { - className: 'datepicker-viewport', - onTouchStart: this.handleContentTouch, - onTouchMove: this.handleContentTouch, - onTouchEnd: this.handleContentTouch, - onTransitionEnd: this.handleContentTransitionEnd }, - _react2.default.createElement( - 'ul', - { - ref: 'scroll', - className: 'datepicker-scroll', - style: scrollStyle }, - this.state.dates.map(this.renderDatepickerItem) - ) - ); - } - }]); - - return DatePickerItem; - }(_react.Component); - - DatePickerItem.propTypes = { - date: _react.PropTypes.object.isRequired, - minDate: _react.PropTypes.object.isRequired, - maxDate: _react.PropTypes.object.isRequired, - typeName: _react.PropTypes.string.isRequired, - touchLen: _react.PropTypes.number, - dateColor: _react.PropTypes.string, - onSelect: _react.PropTypes.func - }; - - DatePickerItem.defaultProps = { - dateColor: '#fff', - touchLen: 40, - onSelect: function onSelect() {} - }; - - exports.default = DatePickerItem; - -/***/ }, -/* 5 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - exports.nextYear = nextYear; - exports.nextMonth = nextMonth; - exports.nextDate = nextDate; - exports.getTime = getTime; - /** - * @module time工具 - */ - - function convertDate(date, formate) { - var year = date.getFullYear(); - var month = date.getMonth() + 1; - var day = date.getDate(); - var hour = date.getHours(); - var minute = date.getMinutes(); - var second = date.getSeconds(); - - return formate.replace(/Y+/, year).replace(/M+/, month).replace(/D+/, day).replace(/h+/, hour).replace(/m+/, minute).replace(/s+/, second); - } - - function throwIfInvalidDate(date) { - if (Object.prototype.toString.call(date, null) !== '[object Date]') { - throw new Error('参数类型不对'); - } - } - - /** - * 获取相对日期的偏移日期 - * @param {Date} 日期 - * @return {number} 相对的天数 - */ - function nextYear(now) { - var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; - - throwIfInvalidDate(now); - var date = new Date(now.getFullYear() + index, now.getMonth(), now.getDate()); - return date; - } - - function nextMonth(now) { - var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; - - throwIfInvalidDate(now); - var date = new Date(now.getFullYear(), now.getMonth() + index, now.getDate()); - return date; - } - - function nextDate(now) { - var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; - - throwIfInvalidDate(now); - var date = new Date(now.getFullYear(), now.getMonth(), now.getDate() + index); - return date; - } - - /** - * 获取指定日期年,月或日 - * @param {Date} 日期 - * @return {String} 格式化日期名称 - */ - function getTime(date, type) { - throwIfInvalidDate(date); - var units = { - Year: ['YYYY', '年'], - Month: ['MM', '月'], - Date: ['DD', '日'] - }; - - if (!units[type]) throw new Error('类型不对'); - - var result = { - value: parseInt(convertDate(date, units[type][0]), 10), - suffix: units[type][1] - }; - return result; - } - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - 'use strict'; - - Object.defineProperty(exports, "__esModule", { - value: true - }); - var TRANSITION = null; - var TRANSITIONEND = null; - var TRANSITION_CSS = null; - if (typeof document.body.style.transition === 'string') { - exports.TRANSITION = TRANSITION = 'transition'; - exports.TRANSITIONEND = TRANSITIONEND = 'transitionend'; - exports.TRANSITION_CSS = TRANSITION_CSS = 'transition'; - } else if (typeof document.body.style.webkitTransition === 'string') { - exports.TRANSITION = TRANSITION = 'WebkitTransition'; - exports.TRANSITION_CSS = TRANSITION_CSS = '-webkit-transition'; - exports.TRANSITIONEND = TRANSITIONEND = 'webkitTransitionEnd'; - } - - var TRANSFORM = null; - var TRANSFORM_CSS = null; - if (typeof document.body.style.transform === 'string') { - exports.TRANSFORM = TRANSFORM = 'transform'; - exports.TRANSFORM_CSS = TRANSFORM_CSS = 'transform'; - } else if (typeof document.body.style.webkitTransform === 'string') { - exports.TRANSFORM = TRANSFORM = 'WebkitTransform'; - exports.TRANSFORM_CSS = TRANSFORM_CSS = '-webkit-transform'; - } - - exports.TRANSITION = TRANSITION; - exports.TRANSITIONEND = TRANSITIONEND; - exports.TRANSITION_CSS = TRANSITION_CSS; - exports.TRANSFORM = TRANSFORM; - exports.TRANSFORM_CSS = TRANSFORM_CSS; - -/***/ } -/******/ ]) -}); -; \ No newline at end of file diff --git a/dist/mobile-datepicker.min.css b/dist/mobile-datepicker.min.css deleted file mode 100644 index 29b362e..0000000 --- a/dist/mobile-datepicker.min.css +++ /dev/null @@ -1 +0,0 @@ -.datepicker{position:absolute;left:0;bottom:0;width:100%;z-index:1;border-top:2px solid #d7d4d4;height:244px;font-size:12px}.datepicker .datepicker-navbar{background:hsla(30,7%,95%,.3);padding:.5em .8em;text-align:right}.datepicker .datepicker-finish-btn{font:1.2em/17px 微软雅黑}.datepicker .datepicker-content{display:-webkit-box;display:-ms-flexbox;display:flex;position:absolute;top:39px;bottom:0;left:0;right:0;margin:0 .5em .5em}.datepicker .datepicker-viewport{padding-top:84px;-webkit-box-flex:1;-ms-flex:1;flex:1;background-image:-webkit-linear-gradient(top,hsla(0,0%,100%,.2) 20%,hsla(0,0%,100%,.7) 50%,hsla(0,0%,100%,.2));background-image:linear-gradient(180deg,hsla(0,0%,100%,.2) 20%,hsla(0,0%,100%,.7) 50%,hsla(0,0%,100%,.2));margin:0 .5em}.datepicker .datepicker-scroll{-webkit-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-perspective:800px;perspective:800px;position:relative;list-style-type:none;height:33px;z-index:-1}.datepicker .datepicker-scroll>li{text-align:center;position:absolute;top:0;left:0;font-size:1.5em;width:100%;line-height:35px} \ No newline at end of file diff --git a/dist/mobile-datepicker.min.js b/dist/mobile-datepicker.min.js deleted file mode 100644 index e498e87..0000000 --- a/dist/mobile-datepicker.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.DatePicker=t(require("react")):e.DatePicker=t(e.react)}(this,function(e){return function(e){function t(a){if(n[a])return n[a].exports;var r=n[a]={exports:{},id:a,loaded:!1};return e[a].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/",t(0)}([function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0}),n(1);var r=n(2),o=a(r);t["default"]=o["default"]},function(e,t){},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;nr&&s>i||oi?l=1:(o>r&&s0?((40-e)/40*100|0)/100:((40+e)/40*100|0)/100}},{key:"_clearTransition",value:function(e){e.style[y.TRANSITION]=""}},{key:"_moveToNext",value:function(e){var t=this.props,n=t.typeName,a=t.date,r=t.maxDate,o=t.minDate,i=m["next"+n](a.value,e),s=1===e?i.getTime()<=r.timestamp:i.getTime()>=o.timestamp;s?this.props.onSelect(i):this._moveTo(this.refs.scroll,this.angle)}},{key:"_moveTo",value:function(e,t){this.animating=!0,e.style[y.TRANSITION]="all .2s ease-out",this.setState({angle:t})}},{key:"handleContentTouch",value:function(e){if(e.preventDefault(),!this.animating)if("touchstart"===e.type)this.touchY=e.targetTouches[0].pageY,this.angle=this.state.angle;else if("touchmove"===e.type){var t=e.targetTouches[0].pageY,n=t-this.touchY,a=this.angle-parseInt(22.5*n/180,10);this.setState({angle:a})}else if("touchend"===e.type){var r=e.changedTouches[0].pageY,o=r-this.touchY,i=o>0?-1:1;1===i&&this.props.touchLen<-o||i===-1&&this.props.touchLenli {\n text-align: center;\n position: absolute;\n top: 0;\n left: 0;\n font-size: 1.5em;\n width: 100%;\n line-height: 35px;\n}\n", undefined); + +/** + * @module time工具 + */ + +function convertDate(date, formate) { + var year = date.getFullYear(); + var month = date.getMonth() + 1; + var day = date.getDate(); + var hour = date.getHours(); + var minute = date.getMinutes(); + var second = date.getSeconds(); + + return formate.replace(/Y+/, year).replace(/M+/, month).replace(/D+/, day).replace(/h+/, hour).replace(/m+/, minute).replace(/s+/, second); +} + +function throwIfInvalidDate(date) { + if (Object.prototype.toString.call(date, null) !== '[object Date]') { + throw new Error('参数类型不对'); + } +} + +/** + * 获取相对日期的偏移日期 + * @param {Date} 日期 + * @return {number} 相对的天数 + */ +function nextYear(now) { + var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; + + throwIfInvalidDate(now); + var date = new Date(now.getFullYear() + index, now.getMonth(), now.getDate()); + return date; +} + +function nextMonth(now) { + var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; + + throwIfInvalidDate(now); + var date = new Date(now.getFullYear(), now.getMonth() + index, now.getDate()); + return date; +} + +function nextDate(now) { + var index = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1]; + + throwIfInvalidDate(now); + var date = new Date(now.getFullYear(), now.getMonth(), now.getDate() + index); + return date; +} + +/** + * 获取指定日期年,月或日 + * @param {Date} 日期 + * @return {String} 格式化日期名称 + */ +function getTime(date, type) { + throwIfInvalidDate(date); + var units = { + Year: ['YYYY', '年'], + Month: ['MM', '月'], + Date: ['DD', '日'] + }; + + if (!units[type]) throw new Error('类型不对'); + + var result = { + value: parseInt(convertDate(date, units[type][0]), 10), + suffix: units[type][1] + }; + return result; +} + +var TimeUtil = Object.freeze({ + convertDate: convertDate, + nextYear: nextYear, + nextMonth: nextMonth, + nextDate: nextDate, + getTime: getTime +}); + +var TRANSITION = null; +var TRANSITIONEND = null; +var TRANSITION_CSS = null; +if (typeof document.body.style.transition === 'string') { + TRANSITION = 'transition'; + TRANSITIONEND = 'transitionend'; + TRANSITION_CSS = 'transition'; +} else if (typeof document.body.style.webkitTransition === 'string') { + TRANSITION = 'WebkitTransition'; + TRANSITION_CSS = '-webkit-transition'; + TRANSITIONEND = 'webkitTransitionEnd'; +} + +var TRANSFORM = null; +var TRANSFORM_CSS = null; +if (typeof document.body.style.transform === 'string') { + TRANSFORM = 'transform'; + TRANSFORM_CSS = 'transform'; +} else if (typeof document.body.style.webkitTransform === 'string') { + TRANSFORM = 'WebkitTransform'; + TRANSFORM_CSS = '-webkit-transform'; +} + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; +}; + +var inherits = function (subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; +}; + +var objectWithoutProperties = function (obj, keys) { + var target = {}; + + for (var i in obj) { + if (keys.indexOf(i) >= 0) continue; + if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; + target[i] = obj[i]; + } + + return target; +}; + +var possibleConstructorReturn = function (self, call) { + if (!self) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return call && (typeof call === "object" || typeof call === "function") ? call : self; +}; + +/** + * @module Date组件 + */ +/** + * Class Date组件类 + * @extends Component + */ + +var DatePickerItem = function (_Component) { + inherits(DatePickerItem, _Component); + + function DatePickerItem(props) { + classCallCheck(this, DatePickerItem); + + var _this = possibleConstructorReturn(this, _Component.call(this, props)); + + _this.animating = false; // 判断是否在transition过渡动画之中 + _this.touchY = 0; // 保存touchstart的pageY + _this.angle = 0; // 容器转过的角度 + _this.renderDatepickerItem = _this.renderDatepickerItem.bind(_this); + _this.handleContentTouch = _this.handleContentTouch.bind(_this); + _this.handleContentTransitionEnd = _this.handleContentTransitionEnd.bind(_this); + _this.state = { + angle: 0 + }; + return _this; + } + + DatePickerItem.prototype.componentWillMount = function componentWillMount() { + var _this2 = this; + + var dates = Array.apply(undefined, Array(5)).map(function (value, index) { + var date = TimeUtil['next' + _this2.props.typeName](_this2.props.date.value, index - 2); + return _extends({}, getTime(date, _this2.props.typeName), { + angle: (2 - index) * 22.5 + }); + }); + this.setState({ dates: dates }); + }; + + DatePickerItem.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { + // 更新同级的组件日期视图 + var scroll = this.refs.scroll; + var angle = this.angle; + var typeName = this.props.typeName; + var nowVal = this.props.date[typeName].value; + var nextVal = nextProps.date[typeName].value; + var nowstamp = this.props.date.timestamp; + var nextstamp = nextProps.date.timestamp; + + var direction = void 0; + if (nextVal > nowVal && nextstamp > nowstamp || nextVal < nowVal && nextstamp > nowstamp) direction = 1;else if (nextVal > nowVal && nextstamp < nowstamp || nextVal < nowVal && nextstamp < nowstamp) direction = -1; + if (direction) { + this._moveTo(scroll, angle + direction * 22.5); + } + }; + + /** + * 根据角度返回透明度(0-1之间) + * @param {number} angle 角度 + * @return + */ + + + DatePickerItem.prototype._setOpacity = function _setOpacity(angle) { + return angle > 0 ? ((40 - angle) / 40 * 100 | 0) / 100 : ((40 + angle) / 40 * 100 | 0) / 100; + }; + + /** + * 清除对象的transition样式 + * @param {Dom} obj 指定的对象 + * @return {undefined} + */ + + + DatePickerItem.prototype._clearTransition = function _clearTransition(obj) { + obj.style[TRANSITION] = ''; // eslint-disable-line + }; + + /** + * 滑动到下一日期 + * @param {number} direction 滑动方向 + * @return {undefined} + */ + + + DatePickerItem.prototype._moveToNext = function _moveToNext(direction) { + var _props = this.props; + var typeName = _props.typeName; + var date = _props.date; + var maxDate = _props.maxDate; + var minDate = _props.minDate; + + var nextDate = TimeUtil['next' + typeName](date.value, direction); + var canMove = direction === 1 ? nextDate.getTime() <= maxDate.timestamp : nextDate.getTime() >= minDate.timestamp; + if (canMove) { + this.props.onSelect(nextDate); + } else { + this._moveTo(this.refs.scroll, this.angle); + } + }; + + /** + * 添加滑动动画 + * @param {DOM} obj DOM对象 + * @param {number} angle 角度 + * @return {undefined} + */ + + + DatePickerItem.prototype._moveTo = function _moveTo(obj, angle) { + this.animating = true; + obj.style[TRANSITION] = 'all .2s ease-out'; // eslint-disable-line + this.setState({ + angle: angle + }); + }; + + /** + * 滑动日期选择器事件 + * @param {Object} event 事件对象 + * @return {undefined} + */ + + + DatePickerItem.prototype.handleContentTouch = function handleContentTouch(event) { + event.preventDefault(); + if (this.animating) return; + if (event.type === 'touchstart') { + this.touchY = event.targetTouches[0].pageY; + this.angle = this.state.angle; + } else if (event.type === 'touchmove') { + var touchY = event.targetTouches[0].pageY; + var dir = touchY - this.touchY; + var angle = this.angle - parseInt(22.5 * dir / 180, 10); + this.setState({ angle: angle }); + } else if (event.type === 'touchend') { + var _touchY = event.changedTouches[0].pageY; + var _dir = _touchY - this.touchY; + var direction = _dir > 0 ? -1 : 1; + if (direction === 1 && this.props.touchLen < -_dir || direction === -1 && this.props.touchLen < _dir) { + this._moveToNext(direction); + } else { + this._moveTo(this.refs.scroll, this.angle); + } + } + }; + + /** + * transition过渡完成事件 + * @return {undefined} + */ + + + DatePickerItem.prototype.handleContentTransitionEnd = function handleContentTransitionEnd() { + var _this3 = this; + + var date = this.props.date; + var newDates = Array.apply(undefined, Array(5)).map(function (value, index) { + var now = TimeUtil['next' + _this3.props.typeName](date.value, index - 2); + return _extends({}, getTime(now, _this3.props.typeName), { + angle: (2 - index) * 22.5 + }); + }); + + this.animating = false; + this._clearTransition(this.refs.scroll); + this.setState({ + dates: newDates, + angle: 0 + }); + }; + + /** + * 渲染一个日期DOM对象 + * @param {Object} date date数据 + * @return {Object} JSX对象 + */ + + + DatePickerItem.prototype.renderDatepickerItem = function renderDatepickerItem(date, index) { + var _itemStyle; + + var itemStyle = (_itemStyle = {}, _itemStyle[TRANSFORM] = 'rotateX(' + date.angle + 'deg) translate3d(0,0,100px)', _itemStyle.opacity = this._setOpacity(date.angle + this.state.angle), _itemStyle.color = this.props.dateColor, _itemStyle); + return React__default.createElement( + 'li', + { + key: index, + style: itemStyle }, + date.value, + date.suffix + ); + }; + + DatePickerItem.prototype.render = function render() { + var _scrollStyle; + + var scrollStyle = (_scrollStyle = {}, _scrollStyle[TRANSFORM] = 'rotateX(' + this.state.angle + 'deg)', _scrollStyle); + + return React__default.createElement( + 'div', + { + className: 'datepicker-viewport', + onTouchStart: this.handleContentTouch, + onTouchMove: this.handleContentTouch, + onTouchEnd: this.handleContentTouch, + onTransitionEnd: this.handleContentTransitionEnd }, + React__default.createElement( + 'ul', + { + ref: 'scroll', + className: 'datepicker-scroll', + style: scrollStyle }, + this.state.dates.map(this.renderDatepickerItem) + ) + ); + }; + + return DatePickerItem; +}(React.Component); + +DatePickerItem.propTypes = { + date: React.PropTypes.object, + minDate: React.PropTypes.object, + maxDate: React.PropTypes.object, + typeName: React.PropTypes.string, + touchLen: React.PropTypes.number, + dateColor: React.PropTypes.string, + onSelect: React.PropTypes.func +}; + +/** + * @module DatePicker组件 + */ + +/** + * Class DatePicker组件类 + * @extends Component + */ + +var DatePicker = function (_Component) { + inherits(DatePicker, _Component); + + function DatePicker(props) { + classCallCheck(this, DatePicker); + // 容器转过的角度 + + var _this = possibleConstructorReturn(this, _Component.call(this, props)); + + _this.state = { + date: _this._productDate(props.date), + minDate: _this._productDate(props.minDate), + maxDate: _this._productDate(props.maxDate) + }; + + _this.handleFinishBtnClick = _this.handleFinishBtnClick.bind(_this); + _this.handleDateSelect = _this.handleDateSelect.bind(_this); + return _this; + } + + DatePicker.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { + this.setState({ + date: this._productDate(nextProps.date), + minDate: this._productDate(nextProps.minDate), + maxDate: this._productDate(nextProps.maxDate) + }); + }; + + DatePicker.prototype._productDate = function _productDate(date) { + var nDate = nextDate(date, 0); + return { + value: nDate, + timestamp: nDate.getTime(), + Year: getTime(nDate, 'Year'), + Month: getTime(nDate, 'Month'), + Date: getTime(nDate, 'Date') + }; + }; + + /** + * 点击完成按钮事件 + * @return {undefined} + */ + + + DatePicker.prototype.handleFinishBtnClick = function handleFinishBtnClick() { + this.props.onSelect(this.state.date.value); + }; + + /** + * 选择下一个日期 + * @return {undefined} + */ + + + DatePicker.prototype.handleDateSelect = function handleDateSelect(date) { + this.setState({ date: this._productDate(date) }); + }; + + /** + * render函数 + * @return {Object} JSX对象 + */ + + + DatePicker.prototype.render = function render() { + var _props = this.props; + var layerBackground = _props.layerBackground; + var btnColor = _props.btnColor; + var touchLen = _props.touchLen; + var dateColor = _props.dateColor; + var _state = this.state; + var date = _state.date; + var minDate = _state.minDate; + var maxDate = _state.maxDate; + + var datePickerStyle = { + backgroundColor: layerBackground + }; + + return React__default.createElement( + 'div', + { + className: 'datepicker', + style: datePickerStyle }, + React__default.createElement( + 'p', + { className: 'datepicker-navbar' }, + React__default.createElement( + 'span', + { + style: { color: btnColor }, + className: 'datepicker-finish-btn', + onClick: this.handleFinishBtnClick }, + '完成' + ) + ), + React__default.createElement( + 'div', + { className: 'datepicker-content' }, + React__default.createElement(DatePickerItem, { + date: date, + typeName: 'Year', + minDate: minDate, + maxDate: maxDate, + touchLen: touchLen, + dateColor: dateColor, + onSelect: this.handleDateSelect }), + React__default.createElement(DatePickerItem, { + date: date, + typeName: 'Month', + minDate: minDate, + maxDate: maxDate, + touchLen: touchLen, + dateColor: dateColor, + onSelect: this.handleDateSelect }), + React__default.createElement(DatePickerItem, { + date: date, + typeName: 'Date', + minDate: minDate, + maxDate: maxDate, + touchLen: touchLen, + dateColor: dateColor, + onSelect: this.handleDateSelect }) + ) + ); + }; + + return DatePicker; +}(React.Component); + +DatePicker.propTypes = { + touchLen: React.PropTypes.number, + btnColor: React.PropTypes.string, + dateColor: React.PropTypes.string, + layerBackground: React.PropTypes.string, + date: React.PropTypes.object, + minDate: React.PropTypes.object, + maxDate: React.PropTypes.object, + onSelect: React.PropTypes.func +}; + +var renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer; + +var Modal = function (_Component) { + inherits(Modal, _Component); + + function Modal() { + classCallCheck(this, Modal); + return possibleConstructorReturn(this, _Component.apply(this, arguments)); + } + + Modal.prototype.componentDidMount = function componentDidMount() { + this._div = document.createElement('div'); + this._div.classList.add('Modal-Portal'); + document.body.appendChild(this._div); + this.renderPortal(this.props); + }; + + Modal.prototype.componentWillReceiveProps = function componentWillReceiveProps(newProps) { + this.renderPortal(newProps); + }; + + Modal.prototype.componentWillUnmount = function componentWillUnmount() { + ReactDOM.unmountComponentAtNode(this._div); + this._div.parentNode.removeChild(this._div); + }; + + Modal.prototype.renderPortal = function renderPortal(props) { + var portal = React__default.cloneElement(this.props.children, _extends({}, props, { key: 'portal' }), null); + + this.portal = renderSubtreeIntoContainer(this, portal, this._div); + }; + + Modal.prototype.render = function render() { + return React__default.createElement('noscript', null); + }; + + return Modal; +}(React.Component); + +Modal.propTypes = { + children: React.PropTypes.node, + isOpen: React.PropTypes.bool +}; +Modal.defaultProps = { + isOpen: false +}; + +function EnhanceDatePicker(_ref) { + var isOpen = _ref.isOpen; + var props = objectWithoutProperties(_ref, ['isOpen']); + + return React__default.createElement( + 'div', + { + style: { display: isOpen ? '' : 'none' }, + className: 'datepicker-modal' }, + React__default.createElement(DatePicker, props) + ); +} + +function ModalDatePicker(props) { + return React__default.createElement( + Modal, + props, + React__default.createElement(EnhanceDatePicker, null) + ); +} + +ModalDatePicker.propTypes = { + isOpen: React.PropTypes.bool, + touchLen: React.PropTypes.number, + btnColor: React.PropTypes.string, + dateColor: React.PropTypes.string, + layerBackground: React.PropTypes.string, + date: React.PropTypes.object, + minDate: React.PropTypes.object, + maxDate: React.PropTypes.object, + onSelect: React.PropTypes.func +}; + +ModalDatePicker.defaultProps = { + touchLen: 40, + dateColor: '#fff', + btnColor: '#fff', + layerBackground: '#ffa70b', + isOpen: false, + date: new Date(), + minDate: new Date(1970, 0, 1), + maxDate: new Date(2050, 0, 1), + onSelect: function () {} +}; + +return ModalDatePicker; + +}))); +//# sourceMappingURL=react-mobile-datepicker.js.map diff --git a/dist/react-mobile-datepicker.js.map b/dist/react-mobile-datepicker.js.map new file mode 100644 index 0000000..9fe2cfd --- /dev/null +++ b/dist/react-mobile-datepicker.js.map @@ -0,0 +1 @@ +{"version":3,"file":null,"sources":["../lib/time.js","../lib/transition.js","../lib/DatePickerItem.js","../lib/DatePicker.js","../lib/Modal.js","../lib/index.js"],"sourcesContent":["/**\n * @module time工具\n */\n\nexport function convertDate(date, formate) {\n const year = date.getFullYear();\n const month = date.getMonth() + 1;\n const day = date.getDate();\n const hour = date.getHours();\n const minute = date.getMinutes();\n const second = date.getSeconds();\n\n return formate\n .replace(/Y+/, year)\n .replace(/M+/, month)\n .replace(/D+/, day)\n .replace(/h+/, hour)\n .replace(/m+/, minute)\n .replace(/s+/, second);\n}\n\nfunction throwIfInvalidDate(date) {\n if (Object.prototype.toString.call(date, null) !== '[object Date]') {\n throw new Error('参数类型不对');\n }\n}\n\n\n/**\n * 获取相对日期的偏移日期\n * @param {Date} 日期\n * @return {number} 相对的天数\n */\nexport function nextYear(now, index = 0) {\n throwIfInvalidDate(now);\n const date = new Date(now.getFullYear() + index, now.getMonth(), now.getDate());\n return date;\n}\n\nexport function nextMonth(now, index = 0) {\n throwIfInvalidDate(now);\n const date = new Date(now.getFullYear(), now.getMonth() + index, now.getDate());\n return date;\n}\n\nexport function nextDate(now, index = 0) {\n throwIfInvalidDate(now);\n const date = new Date(now.getFullYear(), now.getMonth(), now.getDate() + index);\n return date;\n}\n\n\n/**\n * 获取指定日期年,月或日\n * @param {Date} 日期\n * @return {String} 格式化日期名称\n */\nexport function getTime(date, type) {\n throwIfInvalidDate(date);\n const units = {\n Year: ['YYYY', '年'],\n Month: ['MM', '月'],\n Date: ['DD', '日'],\n };\n\n if (!units[type]) throw new Error('类型不对');\n\n const result = {\n value: parseInt(convertDate(date, units[type][0]), 10),\n suffix: units[type][1],\n };\n return result;\n}\n","let TRANSITION = null;\nlet TRANSITIONEND = null;\nlet TRANSITION_CSS = null;\nif (typeof document.body.style.transition === 'string') {\n TRANSITION = 'transition';\n TRANSITIONEND = 'transitionend';\n TRANSITION_CSS = 'transition';\n} else if (typeof document.body.style.webkitTransition === 'string') {\n TRANSITION = 'WebkitTransition';\n TRANSITION_CSS = '-webkit-transition';\n TRANSITIONEND = 'webkitTransitionEnd';\n}\n\nlet TRANSFORM = null;\nlet TRANSFORM_CSS = null;\nif (typeof document.body.style.transform === 'string') {\n TRANSFORM = 'transform';\n TRANSFORM_CSS = 'transform';\n} else if (typeof document.body.style.webkitTransform === 'string') {\n TRANSFORM = 'WebkitTransform';\n TRANSFORM_CSS = '-webkit-transform';\n}\n\nexport {\n TRANSITION,\n TRANSITIONEND,\n TRANSITION_CSS,\n TRANSFORM,\n TRANSFORM_CSS,\n};\n","\n/**\n * @module Date组件\n */\nimport React, { Component, PropTypes } from 'react';\nimport * as TimeUtil from './time.js';\nimport {\n TRANSITION,\n TRANSFORM,\n} from './transition';\n\n/**\n * Class Date组件类\n * @extends Component\n */\nclass DatePickerItem extends Component {\n constructor(props) {\n super(props);\n this.animating = false; // 判断是否在transition过渡动画之中\n this.touchY = 0; // 保存touchstart的pageY\n this.angle = 0; // 容器转过的角度\n this.renderDatepickerItem = this.renderDatepickerItem.bind(this);\n this.handleContentTouch = this.handleContentTouch.bind(this);\n this.handleContentTransitionEnd = this.handleContentTransitionEnd.bind(this);\n this.state = {\n angle: 0,\n };\n }\n\n componentWillMount() {\n const dates = Array(...Array(5)).map((value, index) => {\n const date = TimeUtil[`next${this.props.typeName}`](this.props.date.value, index - 2);\n return {\n ...TimeUtil.getTime(date, this.props.typeName),\n angle: (2 - index) * 22.5,\n };\n });\n this.setState({ dates });\n }\n\n componentWillReceiveProps(nextProps) {\n // 更新同级的组件日期视图\n const scroll = this.refs.scroll;\n const angle = this.angle;\n const typeName = this.props.typeName;\n const nowVal = this.props.date[typeName].value;\n const nextVal = nextProps.date[typeName].value;\n const nowstamp = this.props.date.timestamp;\n const nextstamp = nextProps.date.timestamp;\n\n let direction;\n if ((nextVal > nowVal && nextstamp > nowstamp) ||\n (nextVal < nowVal && nextstamp > nowstamp)) direction = 1;\n else if ((nextVal > nowVal && nextstamp < nowstamp) ||\n (nextVal < nowVal && nextstamp < nowstamp)) direction = -1;\n if (direction) {\n this._moveTo(scroll, angle + direction * 22.5);\n }\n }\n\n /**\n * 根据角度返回透明度(0-1之间)\n * @param {number} angle 角度\n * @return\n */\n _setOpacity(angle) {\n return angle > 0\n ? ((40 - angle) / 40 * 100 | 0) / 100\n : ((40 + angle) / 40 * 100 | 0) / 100;\n }\n\n /**\n * 清除对象的transition样式\n * @param {Dom} obj 指定的对象\n * @return {undefined}\n */\n _clearTransition(obj) {\n obj.style[TRANSITION] = ''; // eslint-disable-line\n }\n\n /**\n * 滑动到下一日期\n * @param {number} direction 滑动方向\n * @return {undefined}\n */\n _moveToNext(direction) {\n const { typeName, date, maxDate, minDate } = this.props;\n const nextDate = TimeUtil[`next${typeName}`](date.value, direction);\n const canMove = (direction === 1) ?\n (nextDate.getTime() <= maxDate.timestamp) :\n (nextDate.getTime() >= minDate.timestamp);\n if (canMove) {\n this.props.onSelect(nextDate);\n } else {\n this._moveTo(this.refs.scroll, this.angle);\n }\n }\n\n /**\n * 添加滑动动画\n * @param {DOM} obj DOM对象\n * @param {number} angle 角度\n * @return {undefined}\n */\n _moveTo(obj, angle) {\n this.animating = true;\n obj.style[TRANSITION] = `all .2s ease-out`; // eslint-disable-line\n this.setState({\n angle,\n });\n }\n\n\n /**\n * 滑动日期选择器事件\n * @param {Object} event 事件对象\n * @return {undefined}\n */\n handleContentTouch(event) {\n event.preventDefault();\n if (this.animating) return;\n if (event.type === 'touchstart') {\n this.touchY = event.targetTouches[0].pageY;\n this.angle = this.state.angle;\n } else if (event.type === 'touchmove') {\n const touchY = event.targetTouches[0].pageY;\n const dir = touchY - this.touchY;\n const angle = this.angle - parseInt(22.5 * dir / 180, 10);\n this.setState({ angle });\n } else if (event.type === 'touchend') {\n const touchY = event.changedTouches[0].pageY;\n const dir = touchY - this.touchY;\n const direction = dir > 0 ? -1 : 1;\n if ((direction === 1 && this.props.touchLen < -dir) ||\n (direction === -1 && this.props.touchLen < dir)) {\n this._moveToNext(direction);\n } else {\n this._moveTo(this.refs.scroll, this.angle);\n }\n }\n }\n\n /**\n * transition过渡完成事件\n * @return {undefined}\n */\n handleContentTransitionEnd() {\n const date = this.props.date;\n const newDates = Array(...Array(5)).map((value, index) => {\n const now = TimeUtil[`next${this.props.typeName}`](date.value, index - 2);\n return {\n ...TimeUtil.getTime(now, this.props.typeName),\n angle: (2 - index) * 22.5,\n };\n });\n\n this.animating = false;\n this._clearTransition(this.refs.scroll);\n this.setState({\n dates: newDates,\n angle: 0,\n });\n }\n\n /**\n * 渲染一个日期DOM对象\n * @param {Object} date date数据\n * @return {Object} JSX对象\n */\n renderDatepickerItem(date, index) {\n const itemStyle = {\n [TRANSFORM]: `rotateX(${date.angle}deg) translate3d(0,0,100px)`,\n opacity: this._setOpacity(date.angle + this.state.angle),\n color: this.props.dateColor,\n };\n return (\n \n {date.value}{date.suffix}\n \n );\n }\n\n render() {\n const scrollStyle = {\n [TRANSFORM]: `rotateX(${this.state.angle}deg)`,\n };\n\n return (\n \n \n {this.state.dates.map(this.renderDatepickerItem)}\n \n
\n );\n }\n}\n\nDatePickerItem.propTypes = {\n date: PropTypes.object,\n minDate: PropTypes.object,\n maxDate: PropTypes.object,\n typeName: PropTypes.string,\n touchLen: PropTypes.number,\n dateColor: PropTypes.string,\n onSelect: PropTypes.func,\n};\n\nexport default DatePickerItem;\n","/**\n * @module DatePicker组件\n */\n\nimport React, { Component, PropTypes } from 'react';\nimport DatePickerItem from './DatePickerItem.js';\nimport { nextDate, getTime } from './time.js';\n\n/**\n * Class DatePicker组件类\n * @extends Component\n */\nclass DatePicker extends Component {\n constructor(props) {\n super(props); // 容器转过的角度\n this.state = {\n date: this._productDate(props.date),\n minDate: this._productDate(props.minDate),\n maxDate: this._productDate(props.maxDate),\n };\n\n this.handleFinishBtnClick = this.handleFinishBtnClick.bind(this);\n this.handleDateSelect = this.handleDateSelect.bind(this);\n }\n\n componentWillReceiveProps(nextProps) {\n this.setState({\n date: this._productDate(nextProps.date),\n minDate: this._productDate(nextProps.minDate),\n maxDate: this._productDate(nextProps.maxDate),\n });\n }\n\n _productDate(date) {\n const nDate = nextDate(date, 0);\n return {\n value: nDate,\n timestamp: nDate.getTime(),\n Year: getTime(nDate, 'Year'),\n Month: getTime(nDate, 'Month'),\n Date: getTime(nDate, 'Date'),\n };\n }\n\n /**\n * 点击完成按钮事件\n * @return {undefined}\n */\n handleFinishBtnClick() {\n this.props.onSelect(this.state.date.value);\n }\n\n /**\n * 选择下一个日期\n * @return {undefined}\n */\n handleDateSelect(date) {\n this.setState({ date: this._productDate(date) });\n }\n\n /**\n * render函数\n * @return {Object} JSX对象\n */\n render() {\n const { layerBackground, btnColor, touchLen, dateColor } = this.props;\n const { date, minDate, maxDate } = this.state;\n const datePickerStyle = {\n backgroundColor: layerBackground,\n };\n\n return (\n \n

\n 完成\n

\n
\n \n \n \n
\n \n );\n }\n }\n\nDatePicker.propTypes = {\n touchLen: PropTypes.number,\n btnColor: PropTypes.string,\n dateColor: PropTypes.string,\n layerBackground: PropTypes.string,\n date: PropTypes.object,\n minDate: PropTypes.object,\n maxDate: PropTypes.object,\n onSelect: PropTypes.func,\n};\n\n\nexport default DatePicker;\n","import React, { Component, PropTypes } from 'react';\nimport ReactDOM from 'react-dom';\nconst renderSubtreeIntoContainer = ReactDOM.unstable_renderSubtreeIntoContainer;\n\n\nclass Modal extends Component {\n static propTypes = {\n children: PropTypes.node,\n isOpen: PropTypes.bool,\n }\n\n static defaultProps = {\n isOpen: false,\n }\n\n componentDidMount() {\n this._div = document.createElement('div');\n this._div.classList.add('Modal-Portal');\n document.body.appendChild(this._div);\n this.renderPortal(this.props);\n }\n\n componentWillReceiveProps(newProps) {\n this.renderPortal(newProps);\n }\n\n componentWillUnmount() {\n ReactDOM.unmountComponentAtNode(this._div);\n this._div.parentNode.removeChild(this._div);\n }\n\n renderPortal(props) {\n const portal =\n React.cloneElement(this.props.children, { ...props, key: 'portal' }, null);\n\n this.portal =\n renderSubtreeIntoContainer(this, portal, this._div);\n }\n\n render() {\n return (