From 61d569f392aa77c4910966b95f97ee100703138e Mon Sep 17 00:00:00 2001
From: rainie <463103063@qq.com>
Date: Thu, 5 Jan 2017 15:05:27 +0800
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=20[feature]=20Support=20server=20r?=
=?UTF-8?q?endering=20(https://github.com/lanjingling0510/react-mobile-dat?=
=?UTF-8?q?epicker/issues/4)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.eslintrc | 2 +
.gitignore | 1 +
dist/react-mobile-datepicker.js | 764 ------------------------
dist/react-mobile-datepicker.js.map | 1 -
dist/react-mobile-datepicker.min.js | 2 -
dist/react-mobile-datepicker.min.js.map | 1 -
lib/DatePickerItem.js | 21 +-
lib/prefix.js | 54 ++
lib/transition.js | 30 -
test/functional/DatePicker_spec.js | 11 +
test/functional/prefix.spec.js | 66 ++
11 files changed, 144 insertions(+), 809 deletions(-)
delete mode 100644 dist/react-mobile-datepicker.js
delete mode 100644 dist/react-mobile-datepicker.js.map
delete mode 100644 dist/react-mobile-datepicker.min.js
delete mode 100644 dist/react-mobile-datepicker.min.js.map
create mode 100644 lib/prefix.js
delete mode 100644 lib/transition.js
create mode 100644 test/functional/prefix.spec.js
diff --git a/.eslintrc b/.eslintrc
index 7c6e49a..8917d59 100755
--- a/.eslintrc
+++ b/.eslintrc
@@ -5,7 +5,9 @@
"camelcase": 0,
"indent": [2, 4, {"SwitchCase": 1}],
"no-use-before-define": 0,
+ "no-restricted-syntax": ["error", "WithStatement"],
"space-before-function-paren": [2, {"anonymous": "always", "named": "never"}],
+ "no-param-reassign": 0,
"func-names": 0,
"new-cap": 0,
"no-underscore-dangle": 0,
diff --git a/.gitignore b/.gitignore
index 0243923..126fe4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ node_modules/
examples/__build__/
.nyc_output/
coverage/
+dist
diff --git a/dist/react-mobile-datepicker.js b/dist/react-mobile-datepicker.js
deleted file mode 100644
index 23640f6..0000000
--- a/dist/react-mobile-datepicker.js
+++ /dev/null
@@ -1,764 +0,0 @@
-(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react'), require('react-dom')) :
- typeof define === 'function' && define.amd ? define(['react', 'react-dom'], factory) :
- (global.reactMobileDatePicker = factory(global.React,global.ReactDOM));
-}(this, (function (React,ReactDOM) { 'use strict';
-
-function __$styleInject(css, returnValue) {
- if (typeof document === 'undefined') {
- return returnValue;
- }
- css = css || '';
- var head = document.head || document.getElementsByTagName('head')[0];
- var style = document.createElement('style');
- style.type = 'text/css';
- if (style.styleSheet){
- style.styleSheet.cssText = css;
- } else {
- style.appendChild(document.createTextNode(css));
- }
- head.appendChild(style);
- return returnValue;
-}
-var React__default = 'default' in React ? React['default'] : React;
-ReactDOM = 'default' in ReactDOM ? ReactDOM['default'] : ReactDOM;
-
-__$styleInject(".datepicker-modal {\n position: fixed;\n right: 0;\n bottom: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0,0,0,.6);\n z-index: 999;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n}\n\n.datepicker {\n position: absolute;\n left: 0;\n bottom: 0;\n width: 100%;\n z-index: 1;\n height: 266px;\n font-size: 16px;\n text-align: center;\n font-family: arial,verdana,sans-serif;\n box-sizing: content-box;\n -webkit-font-smoothing: antialiased;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.datepicker .datepicker-header {\n padding: 0 .5em;\n min-height: 2em;\n line-height: 2em;\n font-size: 1.125em;\n display: none;\n}\n\n.datepicker .datepicker-navbar {\n padding: 0 .5em .5em .5em;\n overflow: hidden;\n}\n\n.datepicker .datepicker-navbar-btn {\n height: 2.5em;\n line-height: 2.5em;\n float: right;\n padding: 0 1em;\n cursor: pointer;\n}\n\n.datepicker .datepicker-content {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n padding: .5em .25em;\n}\n\n.datepicker .datepicker-col-1 {\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n margin: 0 .25em;\n}\n\n.datepicker .datepicker-viewport {\n height: 200px;\n position: relative;\n overflow: hidden\n}\n\n.datepicker .datepicker-viewport::after {\n content: '';\n position: absolute;\n z-index: 2;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n pointer-events: none;\n}\n\n.datepicker .datepicker-wheel {\n position: absolute;\n height: 40px;\n top: 50%;\n margin-top: -20px;\n width: 100%;\n}\n\n.datepicker .datepicker-scroll {\n list-style-type: none\n}\n\n.datepicker .datepicker-scroll>li {\n height: 40px;\n line-height: 40px;\n font-size: 1.375em;\n cursor: pointer;\n}\n\n.datepicker {\n\n /* default */\n\n /* dark */\n\n /* ios */\n\n\n /* android */\n\n /* android-dark */\n}\n\n.datepicker.default {\n background-color: #f7f7f7;\n}\n\n.datepicker.default .datepicker-wheel {\n border-top: 1px solid #4eccc4;\n border-bottom: 1px solid #4eccc4;\n}\n\n.datepicker.default .datepicker-scroll li {\n color: rgb(59, 59, 59);\n}\n\n.datepicker.default .datepicker-scroll li.disabled {\n color: rgb(191, 191, 191);\n}\n\n.datepicker.default .datepicker-navbar-btn {\n color: #4eccc4;\n}\n\n.datepicker.dark {\n background-color: #263238;\n}\n\n.datepicker.dark .datepicker-wheel {\n border-top: 1px solid #50ccc4;\n border-bottom: 1px solid #50ccc4;\n}\n\n.datepicker.dark .datepicker-scroll li {\n color: rgb(201, 203, 204);\n}\n\n.datepicker.dark .datepicker-scroll li.disabled {\n color: rgb(87, 96, 100);\n}\n\n.datepicker.dark .datepicker-navbar-btn {\n color: #50ccc4;\n}\n\n.datepicker.ios {\n background-color: #f7f7f7;\n}\n\n.datepicker.ios .datepicker-col-1 {\n margin: 0;\n}\n\n.datepicker.ios .datepicker-viewport {}\n\n.datepicker.ios .datepicker-viewport::after {\n background: -webkit-linear-gradient(#f7f7f7,rgba(245,245,245,0)52%,rgba(245,245,245,0)48%,#f7f7f7);\n background: linear-gradient(#f7f7f7,rgba(245,245,245,0)52%,rgba(245,245,245,0)48%,#f7f7f7);\n}\n\n.datepicker.ios .datepicker-wheel {\n border-top: 1px solid #dbdbdb;\n border-bottom: 1px solid #dbdbdb;\n}\n\n.datepicker.ios .datepicker-scroll li {\n color: rgb(59, 59, 59);\n}\n\n.datepicker.ios .datepicker-scroll li.disabled {\n color: rgb(191, 191, 191);\n}\n\n.datepicker.ios .datepicker-navbar {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n padding: 0;\n border-bottom: 1px solid #acacac;\n}\n\n.datepicker.ios .datepicker-navbar-btn {\n color: #007aff;\n}\n\n.datepicker.ios .datepicker-navbar-btn:nth-child(2) {\n float: left;\n}\n\n.datepicker.ios .datepicker-content {\n padding-top: 48px;\n}\n\n.datepicker.android, .datepicker.android-dark {\n height: 294px;\n background-color: #f5f5f5;\n}\n\n.datepicker.android .datepicker-header, .datepicker.android-dark .datepicker-header {\n color: #31b6e7;\n border-bottom: 2px solid #31b6e7;\n display: block;\n}\n\n.datepicker.android .datepicker-col-1, .datepicker.android-dark .datepicker-col-1 {\n margin: 0 .625em;\n}\n\n.datepicker.android .datepicker-viewport, .datepicker.android-dark .datepicker-viewport {}\n\n.datepicker.android .datepicker-viewport::after, .datepicker.android-dark .datepicker-viewport::after {\n background-image: -webkit-linear-gradient(#f5f5f5,rgba(245,245,245,0)52%,rgba(245,245,245,0)48%,#f5f5f5);\n background-image: linear-gradient(#f5f5f5,rgba(245,245,245,0)52%,rgba(245,245,245,0)48%,#f5f5f5);\n}\n\n.datepicker.android .datepicker-wheel, .datepicker.android-dark .datepicker-wheel {\n border-top: 2px solid #31b6e7;\n border-bottom: 2px solid #31b6e7;\n}\n\n.datepicker.android .datepicker-scroll li, .datepicker.android-dark .datepicker-scroll li {\n font-size: 1.125em;\n color: rgb(56, 56, 56);\n}\n\n.datepicker.android .datepicker-scroll li.disabled, .datepicker.android-dark .datepicker-scroll li.disabled {\n color: rgb(188, 188, 188);\n}\n\n.datepicker.android .datepicker-navbar, .datepicker.android-dark .datepicker-navbar {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n border-top: 1px solid #d9d4d4;\n padding: 0;\n}\n\n.datepicker.android .datepicker-navbar-btn, .datepicker.android-dark .datepicker-navbar-btn {\n padding: 0;\n color: #000;\n -webkit-box-flex: 1;\n -ms-flex: 1;\n flex: 1;\n}\n\n.datepicker.android .datepicker-navbar-btn:nth-child(2), .datepicker.android-dark .datepicker-navbar-btn:nth-child(2) {\n border-left: 1px solid #d9d4d4;\n}\n\n.datepicker.android-dark {\n background-color: #292829;\n}\n\n.datepicker.android-dark .datepicker-viewport {}\n\n.datepicker.android-dark .datepicker-viewport::after {\n background-image: -webkit-linear-gradient(#282828,rgba(40,40,40,0)52%,rgba(40,40,40,0)48%,#282828);\n background-image: linear-gradient(#282828,rgba(40,40,40,0)52%,rgba(40,40,40,0)48%,#282828);\n}\n\n.datepicker.android-dark .datepicker-scroll li {\n color: rgb(199, 199, 199);\n}\n\n.datepicker.android-dark .datepicker-scroll li.disabled {\n color: rgb(88, 88, 88);\n}\n\n.datepicker.android-dark .datepicker-navbar {\n border-color: #424542;\n}\n\n.datepicker.android-dark .datepicker-navbar-btn {\n color: #fff;\n}\n\n.datepicker.android-dark .datepicker-navbar-btn:nth-child(2) {\n border-color: #424542;\n}\n", undefined);
-
-/**
- * @module time工具
- */
-
-function throwIfInvalidDate(date) {
- if (Object.prototype.toString.call(date, null) !== '[object Date]') {
- throw new Error('参数类型不对');
- }
-}
-
-function daysInMonth(year, month) {
- return new Date(year, month + 1, 0).getDate();
-}
-
-/**
- * 对Date的扩展,将 Date 转化为指定格式的String
- * @param {Date} 日期
- * @return {String} 字符串格式
- */
-function convertDate(date, format) {
- var str = format;
- var o = {
- 'M+': date.getMonth() + 1,
- 'D+': date.getDate(),
- 'h+': date.getHours(),
- 'm+': date.getMinutes(),
- 's+': date.getSeconds()
- };
- if (/(Y+)/.test(format)) {
- str = str.replace(RegExp.$1, date.getFullYear().toString().substr(4 - RegExp.$1.length));
- }
-
- for (var k in o) {
- // eslint-disable-line
- if (new RegExp('(' + k + ')').test(format)) {
- str = str.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(o[k].toString().length));
- }
- }
-
- return str;
-}
-
-/**
- * 获取相对日期的偏移日期
- * @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 year = now.getFullYear();
- var month = now.getMonth() + index;
- var dayOfMonth = Math.min(now.getDate(), daysInMonth(year, month));
- var date = new Date(year, month, dayOfMonth);
- 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;
-}
-
-var TimeUtil = Object.freeze({
- convertDate: convertDate,
- nextYear: nextYear,
- nextMonth: nextMonth,
- nextDate: nextDate
-});
-
-function shallowEqual(prev, next) {
- if (prev === next) return true;
- var prevKeys = Object.keys(prev);
- var nextKeys = Object.keys(next);
-
- if (prevKeys !== nextKeys) return false;
-
- return prevKeys.every(function (key) {
- return prevKeys.hasOwnProperty(key) && prevKeys[key] === nextKeys[key];
- });
-}
-
-function PureRender(Component) {
- Component.prototype.shouldComponentUpdate = function (nextProps, nextState) {
- return PureRender.shouldComponentUpdate(nextProps, nextState, this.props, this.state);
- };
-}
-
-PureRender.shouldComponentUpdate = function (nextProps, nextState, preProps, preState) {
- return !shallowEqual(preProps, nextProps) || !shallowEqual(preState, nextState);
-};
-
-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组件
- */
-var DATE_HEIGHT = 40; // 每个日期的高度
-var DATE_LENGTH = 10; // 日期的个数
-var MIDDLE_INDEX = Math.floor(DATE_LENGTH / 2); // 日期数组中间值的索引
-var MIDDLE_Y = -DATE_HEIGHT * MIDDLE_INDEX; // translateY值
-
-/**
- * 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.translateY = 0; // 容器偏移的距离
- _this.currentIndex = MIDDLE_INDEX; // 滑动中当前日期的索引
-
- _this.state = {
- translateY: MIDDLE_Y,
- marginTop: (_this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT
- };
-
- _this.renderDatepickerItem = _this.renderDatepickerItem.bind(_this);
- _this.handleContentTouch = _this.handleContentTouch.bind(_this);
- _this.handleContentMouseDown = _this.handleContentMouseDown.bind(_this);
- _this.handleContentMouseMove = _this.handleContentMouseMove.bind(_this);
- _this.handleContentMouseUp = _this.handleContentMouseUp.bind(_this);
- return _this;
- }
-
- DatePickerItem.prototype.componentWillMount = function componentWillMount() {
- this._iniDates(this.props.value);
- };
-
- DatePickerItem.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
- if (nextProps.value.getTime() === this.props.value.getTime()) {
- return;
- }
- this._iniDates(nextProps.value);
- this.currentIndex = MIDDLE_INDEX;
- this.setState({
- translateY: MIDDLE_Y,
- marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT
- });
- };
-
- /**
- * Optimization component, Prevents unnecessary rendering
- * Only value or state change should re-rendering
- *
- * @param {Object} nextProps next props
- * @param {Object} nextState next state
- * @return {Boolean} Whether re-rendering
- */
-
-
- DatePickerItem.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
- return nextProps.value.getTime() !== this.props.value.getTime() || !shallowEqual(nextState, this.state);
- };
-
- DatePickerItem.prototype._iniDates = function _iniDates(date) {
- var typeName = this.props.typeName;
-
- var dates = Array.apply(undefined, Array(DATE_LENGTH)).map(function (value, index) {
- return TimeUtil['next' + typeName](date, index - MIDDLE_INDEX);
- });
- this.setState({ dates: dates });
- };
-
- DatePickerItem.prototype._updateDates = function _updateDates(direction) {
- var typeName = this.props.typeName;
- var dates = this.state.dates;
-
- if (direction === 1) {
- this.currentIndex++;
- this.setState({
- dates: [].concat(dates.slice(1), [TimeUtil['next' + typeName](dates[dates.length - 1], 1)]),
- marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT
- });
- } else {
- this.currentIndex--;
- this.setState({
- dates: [TimeUtil['next' + typeName](dates[0], -1)].concat(dates.slice(0, dates.length - 1)),
- marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT
- });
- }
- };
-
- DatePickerItem.prototype._checkIsUpdateDates = function _checkIsUpdateDates(direction, translateY) {
- return direction === 1 ? this.currentIndex * DATE_HEIGHT + DATE_HEIGHT / 2 < -translateY : this.currentIndex * DATE_HEIGHT - DATE_HEIGHT / 2 > -translateY;
- };
-
- /**
- * 清除对象的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 date = this.state.dates[MIDDLE_INDEX];
- var _props = this.props;
- var max = _props.max;
- var min = _props.min;
-
- if (direction === -1 && date.getTime() < min.getTime()) {
- this._updateDates(1);
- } else if (direction === 1 && date.getTime() > max.getTime()) {
- this._updateDates(-1);
- }
-
- this._moveTo(this.refs.scroll, this.currentIndex);
- };
-
- /**
- * 添加滑动动画
- * @param {DOM} obj DOM对象
- * @param {number} angle 角度
- * @return {undefined}
- */
-
-
- DatePickerItem.prototype._moveTo = function _moveTo(obj, currentIndex) {
- var _this2 = this;
-
- this.animating = true;
- obj.style[TRANSITION] = TRANSFORM_CSS + ' .2s ease-out'; // eslint-disable-line
- this.setState({
- translateY: -currentIndex * DATE_HEIGHT
- });
- setTimeout(function () {
- _this2.animating = false;
- _this2.props.onSelect(_this2.state.dates[MIDDLE_INDEX]);
- _this2._clearTransition(_this2.refs.scroll);
- }, 200);
- };
-
- DatePickerItem.prototype.handleStart = function handleStart(event) {
- this.touchY = event.pageY || event.targetTouches[0].pageY;
- this.translateY = this.state.translateY;
- };
-
- DatePickerItem.prototype.handleMove = function handleMove(event) {
- var touchY = event.pageY || event.targetTouches[0].pageY;
- var dir = touchY - this.touchY;
- var translateY = this.translateY + dir;
- var direction = dir > 0 ? -1 : 1;
-
- // 日期最小值,最大值限制
- var date = this.state.dates[MIDDLE_INDEX];
- var _props2 = this.props;
- var max = _props2.max;
- var min = _props2.min;
-
- if (date.getTime() < min.getTime() || date.getTime() > max.getTime()) {
- return;
- }
-
- // 检测是否更新日期列表
- if (this._checkIsUpdateDates(direction, translateY)) {
- this._updateDates(direction);
- }
-
- this.setState({ translateY: translateY });
- };
-
- DatePickerItem.prototype.handleEnd = function handleEnd(event) {
- var touchY = event.pageY || event.changedTouches[0].pageY;
- var dir = touchY - this.touchY;
- var direction = dir > 0 ? -1 : 1;
- this._moveToNext(direction);
- };
-
- /**
- * 滑动日期选择器触屏事件
- * @param {Object} event 事件对象
- * @return {undefined}
- */
-
-
- DatePickerItem.prototype.handleContentTouch = function handleContentTouch(event) {
- event.preventDefault();
- if (this.animating) return;
- if (event.type === 'touchstart') {
- this.handleStart(event);
- } else if (event.type === 'touchmove') {
- this.handleMove(event);
- } else if (event.type === 'touchend') {
- this.handleEnd(event);
- }
- };
-
- /**
- * 滑动日期选择器鼠标事件
- * @param {Object} event 事件对象
- * @return {undefined}
- */
-
-
- DatePickerItem.prototype.handleContentMouseDown = function handleContentMouseDown(event) {
- if (this.animating) return;
- this.handleStart(event);
- document.addEventListener('mousemove', this.handleContentMouseMove);
- document.addEventListener('mouseup', this.handleContentMouseUp);
- };
-
- DatePickerItem.prototype.handleContentMouseMove = function handleContentMouseMove(event) {
- if (this.animating) return;
- this.handleMove(event);
- };
-
- DatePickerItem.prototype.handleContentMouseUp = function handleContentMouseUp(event) {
- if (this.animating) return;
- this.handleEnd(event);
- document.removeEventListener('mousemove', this.handleContentMouseMove);
- document.removeEventListener('mouseup', this.handleContentMouseUp);
- };
-
- /**
- * 渲染一个日期DOM对象
- * @param {Object} date date数据
- * @return {Object} JSX对象
- */
-
-
- DatePickerItem.prototype.renderDatepickerItem = function renderDatepickerItem(date, index) {
- var className = date < this.props.min || date > this.props.max ? 'disabled' : '';
-
- return React__default.createElement(
- 'li',
- {
- key: index,
- className: className },
- convertDate(date, this.props.format)
- );
- };
-
- DatePickerItem.prototype.render = function render() {
- var _scrollStyle;
-
- var scrollStyle = (_scrollStyle = {}, _scrollStyle[TRANSFORM] = 'translateY(' + this.state.translateY + 'px)', _scrollStyle.marginTop = this.state.marginTop, _scrollStyle);
-
- return React__default.createElement(
- 'div',
- { className: 'datepicker-col-1' },
- React__default.createElement(
- 'div',
- {
- className: 'datepicker-viewport',
- onTouchStart: this.handleContentTouch,
- onTouchMove: this.handleContentTouch,
- onTouchEnd: this.handleContentTouch,
- onMouseDown: this.handleContentMouseDown },
- React__default.createElement(
- 'div',
- { className: 'datepicker-wheel' },
- React__default.createElement(
- 'ul',
- {
- ref: 'scroll',
- className: 'datepicker-scroll',
- style: scrollStyle },
- this.state.dates.map(this.renderDatepickerItem)
- )
- )
- )
- );
- };
-
- return DatePickerItem;
-}(React.Component);
-
-DatePickerItem.propTypes = {
- value: React.PropTypes.object,
- min: React.PropTypes.object,
- max: React.PropTypes.object,
- format: React.PropTypes.string,
- typeName: React.PropTypes.string,
- onSelect: React.PropTypes.func
-};
-
-/**
- * @module DatePicker Component
- */
-
-/**
- * Class DatePicker Component Class
- * @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 = {
- value: nextDate(_this.props.value)
- };
-
- _this.handleFinishBtnClick = _this.handleFinishBtnClick.bind(_this);
- _this.handleDateSelect = _this.handleDateSelect.bind(_this);
- return _this;
- }
-
- DatePicker.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
- // update value of state
- var date = nextDate(nextProps.value);
- if (date.getTime() !== this.state.value.getTime()) {
- this.setState({ value: date });
- }
- };
-
- /**
- * Optimization component, Prevents unnecessary rendering
- * Only props or state change or value before re-rendering
- *
- * @param {Object} nextProps next props
- * @param {Object} nextState next state
- * @return {Boolean} Whether re-rendering
- */
-
-
- DatePicker.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps, nextState) {
- var date = nextDate(nextState.value);
- return date.getTime() !== this.state.value.getTime() || PureRender.shouldComponentUpdate(nextProps, nextState, this.props, this.state);
- };
-
- /**
- * 点击完成按钮事件
- * @return {undefined}
- */
-
-
- DatePicker.prototype.handleFinishBtnClick = function handleFinishBtnClick() {
- this.props.onSelect(this.state.value);
- };
-
- /**
- * 选择下一个日期
- * @return {undefined}
- */
-
-
- DatePicker.prototype.handleDateSelect = function handleDateSelect(value) {
- this.setState({ value: value });
- };
-
- /**
- * render函数
- * @return {Object} JSX对象
- */
-
-
- DatePicker.prototype.render = function render() {
- var _props = this.props;
- var min = _props.min;
- var max = _props.max;
- var theme = _props.theme;
- var dateFormat = _props.dateFormat;
-
- var value = this.state.value;
- var themeClassName = ['default', 'dark', 'ios', 'android', 'android-dark'].indexOf(theme) === -1 ? 'default' : theme;
-
- return React__default.createElement(
- 'div',
- {
- className: 'datepicker ' + themeClassName },
- React__default.createElement(
- 'div',
- { className: 'datepicker-header' },
- convertDate(value, 'YYYY/MM/DD')
- ),
- React__default.createElement(
- 'div',
- { className: 'datepicker-content' },
- React__default.createElement(DatePickerItem, {
- value: value,
- min: min,
- max: max,
- typeName: 'Year',
- format: dateFormat[0],
- onSelect: this.handleDateSelect }),
- React__default.createElement(DatePickerItem, {
- value: value,
- min: min,
- max: max,
- typeName: 'Month',
- format: dateFormat[1],
- onSelect: this.handleDateSelect }),
- React__default.createElement(DatePickerItem, {
- value: value,
- min: min,
- max: max,
- typeName: 'Date',
- format: dateFormat[2],
- onSelect: this.handleDateSelect })
- ),
- React__default.createElement(
- 'div',
- { className: 'datepicker-navbar' },
- React__default.createElement(
- 'a',
- {
- className: 'datepicker-navbar-btn',
- onClick: this.handleFinishBtnClick },
- '完成'
- ),
- React__default.createElement(
- 'a',
- {
- className: 'datepicker-navbar-btn',
- onClick: this.props.onCancel },
- '取消'
- )
- )
- );
- };
-
- return DatePicker;
-}(React.Component);
-
-DatePicker.propTypes = {
- theme: React.PropTypes.string,
- value: React.PropTypes.object,
- min: React.PropTypes.object,
- max: React.PropTypes.object,
- dateFormat: React.PropTypes.array,
- onSelect: React.PropTypes.func,
- onCancel: 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']);
-
- function onModalClose(event) {
- if (event.target === event.currentTarget) {
- props.onCancel();
- }
- }
-
- return React__default.createElement(
- 'div',
- {
- style: { display: isOpen ? '' : 'none' },
- onClick: onModalClose,
- 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,
- theme: React.PropTypes.string,
- value: React.PropTypes.object,
- min: React.PropTypes.object,
- max: React.PropTypes.object,
- dateFormat: React.PropTypes.array,
- onSelect: React.PropTypes.func,
- onCancel: React.PropTypes.func
-};
-
-ModalDatePicker.defaultProps = {
- isOpen: false,
- theme: 'default',
- value: new Date(),
- min: new Date(1970, 0, 1),
- max: new Date(2050, 0, 1),
- dateFormat: ['YYYY', 'M', 'D'],
- onSelect: function () {},
- onCancel: 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
deleted file mode 100644
index 66b0ad2..0000000
--- a/dist/react-mobile-datepicker.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":null,"sources":["../lib/time.js","../lib/pureRender.js","../lib/transition.js","../lib/DatePickerItem.js","../lib/DatePicker.js","../lib/Modal.js","../lib/index.js"],"sourcesContent":["/**\n * @module time工具\n */\n\n\nfunction throwIfInvalidDate(date) {\n if (Object.prototype.toString.call(date, null) !== '[object Date]') {\n throw new Error('参数类型不对');\n }\n}\n\nfunction daysInMonth(year, month) {\n return new Date(year, month + 1, 0).getDate();\n}\n\n/**\n * 对Date的扩展,将 Date 转化为指定格式的String\n * @param {Date} 日期\n * @return {String} 字符串格式\n */\nexport function convertDate(date, format) {\n let str = format;\n const o = {\n 'M+': date.getMonth() + 1,\n 'D+': date.getDate(),\n 'h+': date.getHours(),\n 'm+': date.getMinutes(),\n 's+': date.getSeconds(),\n };\n if (/(Y+)/.test(format)) {\n str = str.replace(RegExp.$1,\n (date.getFullYear().toString()).substr(4 - RegExp.$1.length));\n }\n\n for (const k in o) { // eslint-disable-line\n if (new RegExp(`(${k})`).test(format)) {\n str = str.replace(RegExp.$1,\n (RegExp.$1.length === 1) ?\n o[k] : (`00${o[k]}`.substr((o[k].toString()).length)));\n }\n }\n\n return str;\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 year = now.getFullYear();\n const month = now.getMonth() + index;\n const dayOfMonth = Math.min(now.getDate(), daysInMonth(year, month));\n const date = new Date(year, month, dayOfMonth);\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","export function shallowEqual(prev, next) {\n if (prev === next) return true;\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n\n if (prevKeys !== nextKeys) return false;\n\n return prevKeys.every((key) => {\n return prevKeys.hasOwnProperty(key) && prevKeys[key] === nextKeys[key];\n });\n}\n\nfunction PureRender(Component) {\n Component.prototype.shouldComponentUpdate = function(nextProps, nextState) {\n return PureRender.shouldComponentUpdate(nextProps, nextState, this.props, this.state);\n };\n}\n\nPureRender.shouldComponentUpdate = function (nextProps, nextState, preProps, preState) {\n return !shallowEqual(preProps, nextProps) || !shallowEqual(preState, nextState);\n};\n\nexport default PureRender;\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 { shallowEqual } from './pureRender.js';\n\nimport {\n TRANSITION,\n TRANSFORM,\n TRANSFORM_CSS,\n} from './transition';\n\nconst DATE_HEIGHT = 40; // 每个日期的高度\nconst DATE_LENGTH = 10; // 日期的个数\nconst MIDDLE_INDEX = Math.floor(DATE_LENGTH / 2); // 日期数组中间值的索引\nconst MIDDLE_Y = - DATE_HEIGHT * MIDDLE_INDEX; // translateY值\n\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.translateY = 0; // 容器偏移的距离\n this.currentIndex = MIDDLE_INDEX; // 滑动中当前日期的索引\n\n this.state = {\n translateY: MIDDLE_Y,\n marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,\n };\n\n this.renderDatepickerItem = this.renderDatepickerItem.bind(this);\n this.handleContentTouch = this.handleContentTouch.bind(this);\n this.handleContentMouseDown = this.handleContentMouseDown.bind(this);\n this.handleContentMouseMove = this.handleContentMouseMove.bind(this);\n this.handleContentMouseUp = this.handleContentMouseUp.bind(this);\n }\n\n componentWillMount() {\n this._iniDates(this.props.value);\n }\n\n\n componentWillReceiveProps(nextProps) {\n if (nextProps.value.getTime() === this.props.value.getTime()) {\n return;\n }\n this._iniDates(nextProps.value);\n this.currentIndex = MIDDLE_INDEX;\n this.setState({\n translateY: MIDDLE_Y,\n marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,\n });\n }\n\n /**\n * Optimization component, Prevents unnecessary rendering\n * Only value or state change should re-rendering\n *\n * @param {Object} nextProps next props\n * @param {Object} nextState next state\n * @return {Boolean} Whether re-rendering\n */\n shouldComponentUpdate(nextProps, nextState) {\n return nextProps.value.getTime() !== this.props.value.getTime() ||\n !shallowEqual(nextState, this.state);\n }\n\n _iniDates(date) {\n const { typeName } = this.props;\n const dates = Array(...Array(DATE_LENGTH))\n .map((value, index) =>\n TimeUtil[`next${typeName}`](date, index - MIDDLE_INDEX));\n this.setState({ dates });\n }\n\n _updateDates(direction) {\n const { typeName } = this.props;\n const { dates } = this.state;\n if (direction === 1) {\n this.currentIndex ++;\n this.setState({\n dates: [\n ...dates.slice(1),\n TimeUtil[`next${typeName}`](dates[dates.length - 1], 1),\n ],\n marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,\n });\n } else {\n this.currentIndex --;\n this.setState({\n dates: [\n TimeUtil[`next${typeName}`](dates[0], -1),\n ...dates.slice(0, dates.length - 1),\n ],\n marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,\n });\n }\n }\n\n _checkIsUpdateDates(direction, translateY) {\n return direction === 1 ?\n this.currentIndex * DATE_HEIGHT + DATE_HEIGHT / 2 < -translateY :\n this.currentIndex * DATE_HEIGHT - DATE_HEIGHT / 2 > -translateY;\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 date = this.state.dates[MIDDLE_INDEX];\n const { max, min } = this.props;\n if (direction === -1 && date.getTime() < min.getTime()) {\n this._updateDates(1);\n } else if (direction === 1 && date.getTime() > max.getTime()) {\n this._updateDates(-1);\n }\n\n this._moveTo(this.refs.scroll, this.currentIndex);\n }\n\n /**\n * 添加滑动动画\n * @param {DOM} obj DOM对象\n * @param {number} angle 角度\n * @return {undefined}\n */\n _moveTo(obj, currentIndex) {\n this.animating = true;\n obj.style[TRANSITION] = `${TRANSFORM_CSS} .2s ease-out`; // eslint-disable-line\n this.setState({\n translateY: -currentIndex * DATE_HEIGHT,\n });\n setTimeout(() => {\n this.animating = false;\n this.props.onSelect(this.state.dates[MIDDLE_INDEX]);\n this._clearTransition(this.refs.scroll);\n }, 200);\n }\n\n handleStart(event) {\n this.touchY = event.pageY || event.targetTouches[0].pageY;\n this.translateY = this.state.translateY;\n }\n\n\n handleMove(event) {\n const touchY = event.pageY || event.targetTouches[0].pageY;\n const dir = touchY - this.touchY;\n const translateY = this.translateY + dir;\n const direction = dir > 0 ? -1 : 1;\n\n // 日期最小值,最大值限制\n const date = this.state.dates[MIDDLE_INDEX];\n const { max, min } = this.props;\n if (date.getTime() < min.getTime() ||\n date.getTime() > max.getTime()) {\n return;\n }\n\n // 检测是否更新日期列表\n if (this._checkIsUpdateDates(direction, translateY)) {\n this._updateDates(direction);\n }\n\n this.setState({ translateY });\n }\n\n handleEnd(event) {\n const touchY = event.pageY || event.changedTouches[0].pageY;\n const dir = touchY - this.touchY;\n const direction = dir > 0 ? -1 : 1;\n this._moveToNext(direction);\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.handleStart(event);\n } else if (event.type === 'touchmove') {\n this.handleMove(event);\n } else if (event.type === 'touchend') {\n this.handleEnd(event);\n }\n }\n\n /**\n * 滑动日期选择器鼠标事件\n * @param {Object} event 事件对象\n * @return {undefined}\n */\n handleContentMouseDown(event) {\n if (this.animating) return;\n this.handleStart(event);\n document.addEventListener('mousemove', this.handleContentMouseMove);\n document.addEventListener('mouseup', this.handleContentMouseUp);\n }\n\n handleContentMouseMove(event) {\n if (this.animating) return;\n this.handleMove(event);\n }\n\n handleContentMouseUp(event) {\n if (this.animating) return;\n this.handleEnd(event);\n document.removeEventListener('mousemove', this.handleContentMouseMove);\n document.removeEventListener('mouseup', this.handleContentMouseUp);\n }\n\n /**\n * 渲染一个日期DOM对象\n * @param {Object} date date数据\n * @return {Object} JSX对象\n */\n renderDatepickerItem(date, index) {\n const className =\n (date < this.props.min || date > this.props.max) ?\n 'disabled' : '';\n\n return (\n
\n {TimeUtil.convertDate(date, this.props.format)}\n \n );\n }\n\n render() {\n const scrollStyle = {\n [TRANSFORM]: `translateY(${this.state.translateY}px)`,\n marginTop: this.state.marginTop,\n };\n\n return (\n \n
\n
\n
\n {this.state.dates.map(this.renderDatepickerItem)}\n
\n
\n
\n
\n );\n }\n}\n\nDatePickerItem.propTypes = {\n value: PropTypes.object,\n min: PropTypes.object,\n max: PropTypes.object,\n format: PropTypes.string,\n typeName: PropTypes.string,\n onSelect: PropTypes.func,\n};\n\nexport default DatePickerItem;\n","/**\n * @module DatePicker Component\n */\n\nimport React, { Component, PropTypes } from 'react';\nimport DatePickerItem from './DatePickerItem.js';\nimport PureRender from './pureRender.js';\nimport { convertDate, nextDate } from './time.js';\n\n/**\n * Class DatePicker Component Class\n * @extends Component\n */\nclass DatePicker extends Component {\n constructor(props) {\n super(props);\n this.state = {\n value: nextDate(this.props.value),\n };\n\n this.handleFinishBtnClick = this.handleFinishBtnClick.bind(this);\n this.handleDateSelect = this.handleDateSelect.bind(this);\n }\n\n componentWillReceiveProps(nextProps) {\n // update value of state\n const date = nextDate(nextProps.value);\n if (date.getTime() !== this.state.value.getTime()) {\n this.setState({ value: date });\n }\n }\n\n /**\n * Optimization component, Prevents unnecessary rendering\n * Only props or state change or value before re-rendering\n *\n * @param {Object} nextProps next props\n * @param {Object} nextState next state\n * @return {Boolean} Whether re-rendering\n */\n shouldComponentUpdate(nextProps, nextState) {\n const date = nextDate(nextState.value);\n return date.getTime() !== this.state.value.getTime() ||\n PureRender.shouldComponentUpdate(nextProps, nextState, this.props, this.state);\n }\n\n /**\n * 点击完成按钮事件\n * @return {undefined}\n */\n handleFinishBtnClick() {\n this.props.onSelect(this.state.value);\n }\n\n /**\n * 选择下一个日期\n * @return {undefined}\n */\n handleDateSelect(value) {\n this.setState({ value });\n }\n\n /**\n * render函数\n * @return {Object} JSX对象\n */\n render() {\n const { min, max, theme, dateFormat } = this.props;\n const value = this.state.value;\n const themeClassName =\n ['default', 'dark', 'ios', 'android', 'android-dark'].indexOf(theme) === -1 ?\n 'default' : theme;\n\n return (\n \n
{convertDate(value, 'YYYY/MM/DD')}
\n
\n \n \n \n
\n
\n
\n );\n }\n }\n\nDatePicker.propTypes = {\n theme: PropTypes.string,\n value: PropTypes.object,\n min: PropTypes.object,\n max: PropTypes.object,\n dateFormat: PropTypes.array,\n onSelect: PropTypes.func,\n onCancel: PropTypes.func,\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 (