From 32d54e93cd956366f0c0a0669cbbcfe4680a00d1 Mon Sep 17 00:00:00 2001 From: ahmad Date: Tue, 23 Jan 2018 14:32:18 +0500 Subject: [PATCH 01/13] updated README for mainColor prop of color --- readme.md | 58 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/readme.md b/readme.md index 9fd6907..85bbfb1 100644 --- a/readme.md +++ b/readme.md @@ -2,44 +2,38 @@ A date picker component like Airbnb. You can select a date period from the calendar modal. - ### Examples #### iOS Examples - - #### Android Examples - - ### Usage - > This component use `moment.js` to process date. **install from npm** -``` shell +```shell npm install --save react-native-calendar-select ``` **import in project** -``` js -import Calendar from 'react-native-calendar-select'; +```js +import Calendar from "react-native-calendar-select" ``` ```js @@ -82,7 +76,8 @@ render() { }; // optional property, too. let color = { - subColor: '#f0f0f0' + subColor: '#f0f0f0', + mainColor: "#f4995d" }; return ( @@ -106,28 +101,33 @@ render() { ### Properties - -| Property | Type | Default | Description | -| --- | --- | --- | --- | -| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | -| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | -| color | Object | {} | Customize color. | -| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | -| minDate | String / Object | - | Min date of calendar | -| maxDate | String / Object | - | Max date of calendar | -| startDate | String / Object | null | Start date of selection | -| endDate | String / Object | null | End date of selection | -| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | +| Property | Type | Default | Description | +| ---------- | --------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | +| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | +| color | Object | {} | Customize color. | +| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | +| minDate | String / Object | - | Min date of calendar | +| maxDate | String / Object | - | Max date of calendar | +| startDate | String / Object | null | Start date of selection | +| endDate | String / Object | null | End date of selection | +| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | ### Instance methods -| Method | Description | -| --- | --- | -| cancel | Cancel modification of state and close modal | -| close | Close select modal | -| open | Open select modal | -| clear | Reset state of component | -| confirm | Confirm selection and close modal | +| Method | Description | +| ------- | -------------------------------------------- | +| cancel | Cancel modification of state and close modal | +| close | Close select modal | +| open | Open select modal | +| clear | Reset state of component | +| confirm | Confirm selection and close modal | + +### Color properties +| Prop | Description | +| --------- | ----------------------------------------- | +| subColor | Sets the Text Color | +| mainColor | Sets the Background Color of the Calendar | LICENSE MIT From fb2015773fcf160421303880a896b618f411a084 Mon Sep 17 00:00:00 2001 From: ahmad Date: Tue, 23 Jan 2018 14:37:38 +0500 Subject: [PATCH 02/13] updated README for borderColor prop of color --- readme.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 85bbfb1..65f83fe 100644 --- a/readme.md +++ b/readme.md @@ -125,9 +125,10 @@ render() { ### Color properties -| Prop | Description | -| --------- | ----------------------------------------- | -| subColor | Sets the Text Color | -| mainColor | Sets the Background Color of the Calendar | +| Prop | Description | +| ----------- | ----------------------------------------- | +| subColor | Sets the Text Color | +| mainColor | Sets the Background Color of the Calendar | +| borderColor | Sets the Color of the Calendar border | LICENSE MIT From ab32e50ee1c7ff892bad5f35556f6f35c925cddc Mon Sep 17 00:00:00 2001 From: ahmad Date: Tue, 23 Jan 2018 14:42:48 +0500 Subject: [PATCH 03/13] updated proptype of Color prop of Calendar from Object to shapeof --- Calendar.js | 640 ++++++++++++++++++++++++++-------------------------- 1 file changed, 326 insertions(+), 314 deletions(-) diff --git a/Calendar.js b/Calendar.js index ed32f6e..fc355c6 100644 --- a/Calendar.js +++ b/Calendar.js @@ -2,322 +2,334 @@ * Created by TinySymphony on 2017-05-08. */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react" +import PropTypes from "prop-types" import { - View, - Text, - Modal, - Image, - StyleSheet, - ScrollView, - Dimensions, - TouchableHighlight -} from 'react-native'; -import Moment from 'moment'; -import styles from './CalendarStyle'; -import MonthList from './MonthList'; + View, + Text, + Modal, + Image, + StyleSheet, + ScrollView, + Dimensions, + TouchableHighlight +} from "react-native" +import Moment from "moment" +import styles from "./CalendarStyle" +import MonthList from "./MonthList" const ICON = { - close: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADGklEQVR4Xu3b3XXTMBTAcV1Leu8I3YAyAWECygSlE9BOQJmAdAK6QWGCphNQNmAE+mzZl6Mc5xzXtiLJ1r0STfLqJM3/Z9muPwTiwF9w4P3iCHAcAQ4BRDxt2/aDEOKkqqqfAPD0P2EZYy6EEJ/sbwaATVVVtwDwd9gwuQkYY+wHv9n43QcQca21vi4dARFPmqa5F0Ks+r8VEZ+UUu+HCCMAu+abpvnVj+990Z1S6rJUBBtvjHkAgLOp34iIX7XWN/1lI4Cmaa4Q0a5916tIBF+8jUHER631i5ExAqjr+gYAvnjWclEIIfHBAIh41m0CvpFeBEJofBdzqZS627sJ2IV1Xa8B4LNPQAiRFSEmfmr4b48QrkhjjJWyhxLfKwtCZPxvpdQq+DC4Ky4VIVX83hFQKkLK+CAA+6ZSRkLq+GCAEhAo4qMAciJQxUcD5ECgjJ8FwIlAHT8bgAOBI34RACUCV/xiAAoEzvgkACkRuOOTAaRAyBGfFGAJQq745ABzEHLGkwDEItgLMK5reP3zcER0ntL6ztf3LSe7MRJxAuX9/VTxZCNgxqm0E4EynhwgcnMYIVDHswDMReCIZwOIReCKZwOIOdR12wHbhVayo8Bug54Rv/soCwIpwIJ4NgQygATxLAgkAAnjyRGSA8TE27199+BFtjtQSQFi43e3qyL+bU6+Y0wGMDd+xr/NSRGSACyNz4mwGCBVfC6ERQCp43MgzAagiudGmAVAHc+JEA3AFc+FEAXAHc+BEAyQK54aIQggdzwlgheglHgqhL0ApcVTIDgBSo1PjTAJUHp8SgTXfIGH4fP2U3cuOK/euu6chJ5KI+Kt1vpq+D0jgG6yxHfnrZpuQQnxsSNBSvl2OPNl6nH5DQC82wdQUnwMAgBcSynX/bZogBLjIxA+KqV++ACcEyZKjg9AeJZSnobMGbLzbuxm8KYvZZ+3V0qdTz1y7ttfcC+fmO/wjIjnWuuNdydo39AdBu0eczu/BgDsdbgXMy24o2L/nn3wom3bFSL+kVLaFTqaMrdti/3i1/b+I8BrW6OxPQc/Av4BDSZYbnPWwJkAAAAASUVORK5CYII=' -}; + close: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADGklEQVR4Xu3b3XXTMBTAcV1Leu8I3YAyAWECygSlE9BOQJmAdAK6QWGCphNQNmAE+mzZl6Mc5xzXtiLJ1r0STfLqJM3/Z9muPwTiwF9w4P3iCHAcAQ4BRDxt2/aDEOKkqqqfAPD0P2EZYy6EEJ/sbwaATVVVtwDwd9gwuQkYY+wHv9n43QcQca21vi4dARFPmqa5F0Ks+r8VEZ+UUu+HCCMAu+abpvnVj+990Z1S6rJUBBtvjHkAgLOp34iIX7XWN/1lI4Cmaa4Q0a5916tIBF+8jUHER631i5ExAqjr+gYAvnjWclEIIfHBAIh41m0CvpFeBEJofBdzqZS627sJ2IV1Xa8B4LNPQAiRFSEmfmr4b48QrkhjjJWyhxLfKwtCZPxvpdQq+DC4Ky4VIVX83hFQKkLK+CAA+6ZSRkLq+GCAEhAo4qMAciJQxUcD5ECgjJ8FwIlAHT8bgAOBI34RACUCV/xiAAoEzvgkACkRuOOTAaRAyBGfFGAJQq745ABzEHLGkwDEItgLMK5reP3zcER0ntL6ztf3LSe7MRJxAuX9/VTxZCNgxqm0E4EynhwgcnMYIVDHswDMReCIZwOIReCKZwOIOdR12wHbhVayo8Bug54Rv/soCwIpwIJ4NgQygATxLAgkAAnjyRGSA8TE27199+BFtjtQSQFi43e3qyL+bU6+Y0wGMDd+xr/NSRGSACyNz4mwGCBVfC6ERQCp43MgzAagiudGmAVAHc+JEA3AFc+FEAXAHc+BEAyQK54aIQggdzwlgheglHgqhL0ApcVTIDgBSo1PjTAJUHp8SgTXfIGH4fP2U3cuOK/euu6chJ5KI+Kt1vpq+D0jgG6yxHfnrZpuQQnxsSNBSvl2OPNl6nH5DQC82wdQUnwMAgBcSynX/bZogBLjIxA+KqV++ACcEyZKjg9AeJZSnobMGbLzbuxm8KYvZZ+3V0qdTz1y7ttfcC+fmO/wjIjnWuuNdydo39AdBu0eczu/BgDsdbgXMy24o2L/nn3wom3bFSL+kVLaFTqaMrdti/3i1/b+I8BrW6OxPQc/Av4BDSZYbnPWwJkAAAAASUVORK5CYII=" +} export default class Calendar extends Component { - static propTypes = { - i18n: PropTypes.string, - format: PropTypes.string, - customI18n: PropTypes.object, - color: PropTypes.object, - minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), - maxDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]) - } - static defaultProps = { - format: 'YYYY-MM-DD', - i18n: 'en', - customI18n: {}, - color: {} - } - static I18N_MAP = { - 'zh': { - 'w': ['', '一', '二', '三', '四', '五', '六', '日'], - 'weekday': ['', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'], - 'text': { - 'start': '开 始', - 'end': '结 束', - 'date': '日 期', - 'save': '保 存', - 'clear': '清除' - }, - 'date': 'M月D日' - }, - 'en': { - 'w': ['', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'], - 'weekday': ['', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], - 'text': { - 'start': 'Start', - 'end': 'End', - 'date': 'Date', - 'save': 'Save', - 'clear': 'Reset' - }, - 'date': 'DD / MM' - }, - 'jp': { - 'w': ['', '月', '火', '水', '木', '金', '土', '日'], - 'weekday': ['', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日'], - 'text': { - 'start': 'スタート', - 'end': 'エンド', - 'date': '時 間', - 'save': '確 認', - 'clear': 'クリア' - }, - 'date': 'M月D日' - } - } - constructor (props) { - super(props); - this.state = { - isModalVisible: false - }; - this._today = Moment(); - this._year = this._today.year(); - this._i18n = this._i18n.bind(this); - this._getDateRange = this._getDateRange.bind(this); - this._onChoose = this._onChoose.bind(this); - this._resetCalendar = this._resetCalendar.bind(this); - this.close = this.close.bind(this); - this.cancel = this.cancel.bind(this); - this.open = this.open.bind(this); - this.clear = this.clear.bind(this); - this.confirm = this.confirm.bind(this); - this._getDateRange(); - } - componentDidMount () { - this._resetCalendar(); - } - _i18n (data, type) { - const { - i18n, - customI18n - } = this.props; - if (~['w', 'weekday', 'text'].indexOf(type)) { - return (customI18n[type] || {})[data] || Calendar.I18N_MAP[i18n][type][data]; - } - if (type === 'date') { - return data.format(customI18n[type] || Calendar.I18N_MAP[i18n][type]); - } - } - _resetCalendar () { - const { - startDate, - endDate, - format - } = this.props; - let start = Moment(startDate, format); - let end = Moment(endDate, format); - let isStartValid = start.isValid() && start >= this._minDate && start <= this._maxDate; - let isEndValid = end.isValid() && end >= this._minDate && end <= this._maxDate; - this.setState({ - startDate: isStartValid ? start : null, - startDateText: isStartValid ? this._i18n(start, 'date') : '', - startWeekdayText: isStartValid ? this._i18n(start.isoWeekday(), 'weekday') : '', - endDate: isEndValid ? end: null, - endDateText: isEndValid ? this._i18n(end, 'date') : '', - endWeekdayText: isEndValid ? this._i18n(end.isoWeekday(), 'weekday') : '' - }); - } - _getDateRange () { - const { - maxDate, - minDate, - format - } = this.props; - let max = Moment(maxDate, format); - let min = Moment(minDate, format); - let maxValid = max.isValid(); - let minValid = min.isValid(); - if (!maxValid && !minValid) { - max = Moment().add(3, 'months'); - min = Moment(); - } - if (!maxValid && minValid) { - max = min.add(3, 'months'); - } - if (maxValid && !minValid) { - min = max.subtract(3, 'months'); - } - if (min.isSameOrAfter(max)) return {}; - this._minDate = min; - this._maxDate = max; - } - _onChoose (day) { - const { - startDate, - endDate - } = this.state; - if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { - this.setState({ - startDate: day, - endDate: null, - startDateText: this._i18n(day, 'date'), - startWeekdayText: this._i18n(day.isoWeekday(), 'weekday'), - endDateText: '', - endWeekdayText: '', - }); - } else if (startDate && !endDate && day > startDate) { - this.setState({ - endDate: day, - endDateText: this._i18n(day, 'date'), - endWeekdayText: this._i18n(day.isoWeekday(), 'weekday') - }); - } - } - cancel () { - this.close(); - this._resetCalendar(); - } - close () { - this.setState({ - isModalVisible: false - }); - } - open () { - this.setState({ - isModalVisible: true - }); - } - clear () { - this.setState({ - startDate: null, - endDate: null, - startDateText: '', - startWeekdayText: '', - endDateText: '', - endWeekdayText: '' - }); - } - confirm () { - const { - startDate, - endDate - } = this.state; - let startMoment = startDate ? startDate.clone() : null; - let endMoment = endDate ? endDate.clone() : null; - this.props.onConfirm && this.props.onConfirm({ - startDate: startMoment ? startMoment.toDate() : null, - endDate: endMoment ? endMoment.toDate() : null, - startMoment, - endMoment - }); - this.close(); - } - render () { - const { - startDate, - endDate, - startDateText, - startWeekdayText, - endDateText, - endWeekdayText - } = this.state; - const { - mainColor = '#15aaaa', - subColor = '#fff', - borderColor = 'rgba(255, 255, 255, 0.50)' - } = this.props.color; - let color = {mainColor, subColor, borderColor}; - let mainBack = {backgroundColor: mainColor}; - let subBack = {backgroundColor: subColor}; - let mainFontColor = {color: mainColor}; - let subFontColor = {color: subColor}; - let isValid = !startDate || endDate; - let isClearVisible = startDate || endDate; - return ( - - - - - - - {isClearVisible && - {this._i18n('clear', 'text')} - } - - - - - {startDateText || this._i18n('start', 'text')} - - - {startWeekdayText || this._i18n('date', 'text')} - - - - - - {endDateText || this._i18n('end', 'text')} - - - {endWeekdayText || this._i18n('date', 'text')} - - - - - {[7, 1, 2, 3, 4, 5, 6].map(item => - {this._i18n(item, 'w')} - )} - - - - - - {isValid ? - - - - {this._i18n('save', 'text')} - - - : - - - - {this._i18n('save', 'text')} - - - - } - - - - ); - } + static propTypes = { + i18n: PropTypes.string, + format: PropTypes.string, + customI18n: PropTypes.object, + color: PropTypes.shape({ + mainColor: PropTypes.string, + subColor: PropTypes.string, + borderColor: PropTypes.string + }), + minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), + maxDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]) + } + static defaultProps = { + format: "YYYY-MM-DD", + i18n: "en", + customI18n: {}, + color: {} + } + static I18N_MAP = { + zh: { + w: ["", "一", "二", "三", "四", "五", "六", "日"], + weekday: ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], + text: { + start: "开 始", + end: "结 束", + date: "日 期", + save: "保 存", + clear: "清除" + }, + date: "M月D日" + }, + en: { + w: ["", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"], + weekday: [ + "", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" + ], + text: { + start: "Start", + end: "End", + date: "Date", + save: "Save", + clear: "Reset" + }, + date: "DD / MM" + }, + jp: { + w: ["", "月", "火", "水", "木", "金", "土", "日"], + weekday: ["", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"], + text: { + start: "スタート", + end: "エンド", + date: "時 間", + save: "確 認", + clear: "クリア" + }, + date: "M月D日" + } + } + constructor(props) { + super(props) + this.state = { + isModalVisible: false + } + this._today = Moment() + this._year = this._today.year() + this._i18n = this._i18n.bind(this) + this._getDateRange = this._getDateRange.bind(this) + this._onChoose = this._onChoose.bind(this) + this._resetCalendar = this._resetCalendar.bind(this) + this.close = this.close.bind(this) + this.cancel = this.cancel.bind(this) + this.open = this.open.bind(this) + this.clear = this.clear.bind(this) + this.confirm = this.confirm.bind(this) + this._getDateRange() + } + componentDidMount() { + this._resetCalendar() + } + _i18n(data, type) { + const { i18n, customI18n } = this.props + if (~["w", "weekday", "text"].indexOf(type)) { + return (customI18n[type] || {})[data] || Calendar.I18N_MAP[i18n][type][data] + } + if (type === "date") { + return data.format(customI18n[type] || Calendar.I18N_MAP[i18n][type]) + } + } + _resetCalendar() { + const { startDate, endDate, format } = this.props + let start = Moment(startDate, format) + let end = Moment(endDate, format) + let isStartValid = start.isValid() && start >= this._minDate && start <= this._maxDate + let isEndValid = end.isValid() && end >= this._minDate && end <= this._maxDate + this.setState({ + startDate: isStartValid ? start : null, + startDateText: isStartValid ? this._i18n(start, "date") : "", + startWeekdayText: isStartValid ? this._i18n(start.isoWeekday(), "weekday") : "", + endDate: isEndValid ? end : null, + endDateText: isEndValid ? this._i18n(end, "date") : "", + endWeekdayText: isEndValid ? this._i18n(end.isoWeekday(), "weekday") : "" + }) + } + _getDateRange() { + const { maxDate, minDate, format } = this.props + let max = Moment(maxDate, format) + let min = Moment(minDate, format) + let maxValid = max.isValid() + let minValid = min.isValid() + if (!maxValid && !minValid) { + max = Moment().add(3, "months") + min = Moment() + } + if (!maxValid && minValid) { + max = min.add(3, "months") + } + if (maxValid && !minValid) { + min = max.subtract(3, "months") + } + if (min.isSameOrAfter(max)) return {} + this._minDate = min + this._maxDate = max + } + _onChoose(day) { + const { startDate, endDate } = this.state + if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { + this.setState({ + startDate: day, + endDate: null, + startDateText: this._i18n(day, "date"), + startWeekdayText: this._i18n(day.isoWeekday(), "weekday"), + endDateText: "", + endWeekdayText: "" + }) + } else if (startDate && !endDate && day > startDate) { + this.setState({ + endDate: day, + endDateText: this._i18n(day, "date"), + endWeekdayText: this._i18n(day.isoWeekday(), "weekday") + }) + } + } + cancel() { + this.close() + this._resetCalendar() + } + close() { + this.setState({ + isModalVisible: false + }) + } + open() { + this.setState({ + isModalVisible: true + }) + } + clear() { + this.setState({ + startDate: null, + endDate: null, + startDateText: "", + startWeekdayText: "", + endDateText: "", + endWeekdayText: "" + }) + } + confirm() { + const { startDate, endDate } = this.state + let startMoment = startDate ? startDate.clone() : null + let endMoment = endDate ? endDate.clone() : null + this.props.onConfirm && + this.props.onConfirm({ + startDate: startMoment ? startMoment.toDate() : null, + endDate: endMoment ? endMoment.toDate() : null, + startMoment, + endMoment + }) + this.close() + } + render() { + const { + startDate, + endDate, + startDateText, + startWeekdayText, + endDateText, + endWeekdayText + } = this.state + const { + mainColor = "#15aaaa", + subColor = "#fff", + borderColor = "rgba(255, 255, 255, 0.50)" + } = this.props.color + let color = { mainColor, subColor, borderColor } + let mainBack = { backgroundColor: mainColor } + let subBack = { backgroundColor: subColor } + let mainFontColor = { color: mainColor } + let subFontColor = { color: subColor } + let isValid = !startDate || endDate + let isClearVisible = startDate || endDate + return ( + + + + + + + {isClearVisible && ( + + + {this._i18n("clear", "text")} + + + )} + + + + + {startDateText || this._i18n("start", "text")} + + + {startWeekdayText || this._i18n("date", "text")} + + + + + + {endDateText || this._i18n("end", "text")} + + + {endWeekdayText || this._i18n("date", "text")} + + + + + {[7, 1, 2, 3, 4, 5, 6].map(item => ( + + {this._i18n(item, "w")} + + ))} + + + + + + {isValid ? ( + + + + {this._i18n("save", "text")} + + + + ) : ( + + + + {this._i18n("save", "text")} + + + + )} + + + + ) + } } From 1b63eb8feeec995ce86dde5ec2fbe100b8ec47cf Mon Sep 17 00:00:00 2001 From: ahmad Date: Tue, 23 Jan 2018 17:29:16 +0500 Subject: [PATCH 04/13] added selectionType prop for single date selection --- .eslintrc | 48 +++++ Calendar.js | 172 +++++++++--------- Day/index.js | 159 ++++++++-------- Month/index.js | 249 ++++++++++++++------------ package.json | 14 +- yarn.lock | 478 +++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 817 insertions(+), 303 deletions(-) create mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..04b00bf --- /dev/null +++ b/.eslintrc @@ -0,0 +1,48 @@ +{ + "root": true, + "extends": ["standard"], + "env": { + "node": true, + "jest": true, + "browser": true + }, + "globals": { + "__DEV__": true + }, + "parser": "babel-eslint", + "plugins": ["prettier", "react"], + "rules": { + "react/jsx-uses-react": "error", + "react/jsx-uses-vars": "error", + "no-underscore-dangle": "off", + "quotes": [ + 2, + "double", + { + "avoidEscape": true + } + ], + "indent": [2, "tab"], + "no-tabs": 0, + "arrow-parens": 0, + "no-var": 2, + "prefer-const": 1, + "camelcase": [ + "error", + { + "properties": "always" + } + ], + "key-spacing": [ + "error", + { + "beforeColon": false, + "afterColon": true, + "align": "colon" + } + ], + "object-curly-spacing": ["error", "always"], + "curly": ["error", "all"], + "brace-style": ["error", "1tbs"] + } +} diff --git a/Calendar.js b/Calendar.js index fc355c6..6f3ca5c 100644 --- a/Calendar.js +++ b/Calendar.js @@ -5,16 +5,7 @@ import React, { Component } from "react" import PropTypes from "prop-types" -import { - View, - Text, - Modal, - Image, - StyleSheet, - ScrollView, - Dimensions, - TouchableHighlight -} from "react-native" +import { View, Text, Modal, Image, TouchableHighlight } from "react-native" import Moment from "moment" import styles from "./CalendarStyle" import MonthList from "./MonthList" @@ -24,38 +15,39 @@ const ICON = { } export default class Calendar extends Component { static propTypes = { - i18n: PropTypes.string, - format: PropTypes.string, + i18n : PropTypes.string, + format : PropTypes.string, customI18n: PropTypes.object, - color: PropTypes.shape({ - mainColor: PropTypes.string, - subColor: PropTypes.string, + color : PropTypes.shape({ + mainColor : PropTypes.string, + subColor : PropTypes.string, borderColor: PropTypes.string }), - minDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), - maxDate: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]) + minDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), + maxDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), + selectionType: PropTypes.string } static defaultProps = { - format: "YYYY-MM-DD", - i18n: "en", + format : "YYYY-MM-DD", + i18n : "en", customI18n: {}, - color: {} + color : {} } static I18N_MAP = { zh: { - w: ["", "一", "二", "三", "四", "五", "六", "日"], + w : ["", "一", "二", "三", "四", "五", "六", "日"], weekday: ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], - text: { + text : { start: "开 始", - end: "结 束", - date: "日 期", - save: "保 存", + end : "结 束", + date : "日 期", + save : "保 存", clear: "清除" }, date: "M月D日" }, en: { - w: ["", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"], + w : ["", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"], weekday: [ "", "Monday", @@ -68,27 +60,27 @@ export default class Calendar extends Component { ], text: { start: "Start", - end: "End", - date: "Date", - save: "Save", + end : "End", + date : "Date", + save : "Save", clear: "Reset" }, date: "DD / MM" }, jp: { - w: ["", "月", "火", "水", "木", "金", "土", "日"], + w : ["", "月", "火", "水", "木", "金", "土", "日"], weekday: ["", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"], - text: { + text : { start: "スタート", - end: "エンド", - date: "時 間", - save: "確 認", + end : "エンド", + date : "時 間", + save : "確 認", clear: "クリア" }, date: "M月D日" } } - constructor(props) { + constructor (props) { super(props) this.state = { isModalVisible: false @@ -106,10 +98,10 @@ export default class Calendar extends Component { this.confirm = this.confirm.bind(this) this._getDateRange() } - componentDidMount() { + componentDidMount () { this._resetCalendar() } - _i18n(data, type) { + _i18n (data, type) { const { i18n, customI18n } = this.props if (~["w", "weekday", "text"].indexOf(type)) { return (customI18n[type] || {})[data] || Calendar.I18N_MAP[i18n][type][data] @@ -118,27 +110,27 @@ export default class Calendar extends Component { return data.format(customI18n[type] || Calendar.I18N_MAP[i18n][type]) } } - _resetCalendar() { + _resetCalendar () { const { startDate, endDate, format } = this.props - let start = Moment(startDate, format) - let end = Moment(endDate, format) - let isStartValid = start.isValid() && start >= this._minDate && start <= this._maxDate - let isEndValid = end.isValid() && end >= this._minDate && end <= this._maxDate + const start = Moment(startDate, format) + const end = Moment(endDate, format) + const isStartValid = start.isValid() && start >= this._minDate && start <= this._maxDate + const isEndValid = end.isValid() && end >= this._minDate && end <= this._maxDate this.setState({ - startDate: isStartValid ? start : null, - startDateText: isStartValid ? this._i18n(start, "date") : "", + startDate : isStartValid ? start : null, + startDateText : isStartValid ? this._i18n(start, "date") : "", startWeekdayText: isStartValid ? this._i18n(start.isoWeekday(), "weekday") : "", - endDate: isEndValid ? end : null, - endDateText: isEndValid ? this._i18n(end, "date") : "", - endWeekdayText: isEndValid ? this._i18n(end.isoWeekday(), "weekday") : "" + endDate : isEndValid ? end : null, + endDateText : isEndValid ? this._i18n(end, "date") : "", + endWeekdayText : isEndValid ? this._i18n(end.isoWeekday(), "weekday") : "" }) } - _getDateRange() { + _getDateRange () { const { maxDate, minDate, format } = this.props let max = Moment(maxDate, format) let min = Moment(minDate, format) - let maxValid = max.isValid() - let minValid = min.isValid() + const maxValid = max.isValid() + const minValid = min.isValid() if (!maxValid && !minValid) { max = Moment().add(3, "months") min = Moment() @@ -149,67 +141,85 @@ export default class Calendar extends Component { if (maxValid && !minValid) { min = max.subtract(3, "months") } - if (min.isSameOrAfter(max)) return {} + if (min.isSameOrAfter(max)) { + return {} + } this._minDate = min this._maxDate = max } - _onChoose(day) { + _onChoose (day, selectionType) { const { startDate, endDate } = this.state + + if (selectionType === "day") { + if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { + this.setState({ + startDate : day, + endDate : day, + startDateText : this._i18n(day, "date"), + startWeekdayText: this._i18n(day.isoWeekday(), "weekday"), + endDateText : this._i18n(day, "date"), + endWeekdayText : this._i18n(day.isoWeekday(), "weekday") + }) + } + + return + } + if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { this.setState({ - startDate: day, - endDate: null, - startDateText: this._i18n(day, "date"), + startDate : day, + endDate : null, + startDateText : this._i18n(day, "date"), startWeekdayText: this._i18n(day.isoWeekday(), "weekday"), - endDateText: "", - endWeekdayText: "" + endDateText : "", + endWeekdayText : "" }) } else if (startDate && !endDate && day > startDate) { this.setState({ - endDate: day, - endDateText: this._i18n(day, "date"), + endDate : day, + endDateText : this._i18n(day, "date"), endWeekdayText: this._i18n(day.isoWeekday(), "weekday") }) } } - cancel() { + cancel () { this.close() this._resetCalendar() } - close() { + close () { this.setState({ isModalVisible: false }) } - open() { + open () { this.setState({ isModalVisible: true }) } - clear() { + clear () { this.setState({ - startDate: null, - endDate: null, - startDateText: "", + startDate : null, + endDate : null, + startDateText : "", startWeekdayText: "", - endDateText: "", - endWeekdayText: "" + endDateText : "", + endWeekdayText : "" }) } - confirm() { + confirm () { const { startDate, endDate } = this.state - let startMoment = startDate ? startDate.clone() : null - let endMoment = endDate ? endDate.clone() : null + const startMoment = startDate ? startDate.clone() : null + const endMoment = endDate ? endDate.clone() : null this.props.onConfirm && this.props.onConfirm({ startDate: startMoment ? startMoment.toDate() : null, - endDate: endMoment ? endMoment.toDate() : null, + endDate : endMoment ? endMoment.toDate() : null, startMoment, endMoment }) this.close() } - render() { + render () { const { startDate, endDate, @@ -218,18 +228,18 @@ export default class Calendar extends Component { endDateText, endWeekdayText } = this.state + const { selectionType } = this.props const { mainColor = "#15aaaa", subColor = "#fff", borderColor = "rgba(255, 255, 255, 0.50)" } = this.props.color - let color = { mainColor, subColor, borderColor } - let mainBack = { backgroundColor: mainColor } - let subBack = { backgroundColor: subColor } - let mainFontColor = { color: mainColor } - let subFontColor = { color: subColor } - let isValid = !startDate || endDate - let isClearVisible = startDate || endDate + const color = { mainColor, subColor, borderColor } + const mainBack = { backgroundColor: mainColor } + const subBack = { backgroundColor: subColor } + const subFontColor = { color: subColor } + const isValid = !startDate || endDate + const isClearVisible = startDate || endDate return ( this._onChoose(day, selectionType)} i18n={this.props.i18n} color={color} /> diff --git a/Day/index.js b/Day/index.js index 57e321d..0637678 100644 --- a/Day/index.js +++ b/Day/index.js @@ -2,90 +2,83 @@ * Created by TinySymphony on 2017-05-11. */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react" +import PropTypes from "prop-types" -import { - View, - Text, - StyleSheet, - TouchableHighlight -} from 'react-native'; -import Moment from 'moment'; -import styles from './style'; +import { View, Text, TouchableHighlight } from "react-native" +import styles from "./style" export default class Day extends Component { - static propTypes = { - onChoose: PropTypes.func - } - constructor (props) { - super(props); - this._chooseDay = this._chooseDay.bind(this); - this._statusCheck = this._statusCheck.bind(this); - this._statusCheck(); - } - _chooseDay () { - this.props.onChoose && this.props.onChoose(this.props.date); - } - _statusCheck (props) { - const { - startDate, - endDate, - today, - date = null, - minDate, - maxDate, - empty - } = props || this.props; - this.isToday = today.isSame(date, 'd'); - this.isValid = date && - (date >= minDate || date.isSame(minDate, 'd')) && - (date <= maxDate || date.isSame(maxDate, 'd')); - this.isMid = date > startDate && date < endDate || - (!date && empty >= startDate && empty <= endDate); - this.isStart = date && date.isSame(startDate, 'd'); - this.isStartPart = this.isStart && endDate; - this.isEnd = date && date.isSame(endDate, 'd'); - this.isFocus = this.isMid || this.isStart || this.isEnd; - return this.isFocus; - } - shouldComponentUpdate (nextProps) { - let prevStatus = this.isFocus; - let nextStatus = this._statusCheck(nextProps); - if (prevStatus || nextStatus) return true; - return false; - } - render () { - const { - date, - color - } = this.props; - let text = date ? date.date() : ''; - let mainColor = {color: color.mainColor}; - let subColor = {color: color.subColor}; - let mainBack = {backgroundColor: color.mainColor}; - let subBack = {backgroundColor: color.subColor}; - return ( - - {this.isValid ? - - {text} - : - - {text} - - } - - ); - } + static propTypes = { + onChoose: PropTypes.func + } + constructor (props) { + super(props) + this._chooseDay = this._chooseDay.bind(this) + this._statusCheck = this._statusCheck.bind(this) + this._statusCheck() + } + _chooseDay () { + this.props.onChoose && this.props.onChoose(this.props.date) + } + _statusCheck (props) { + const { startDate, endDate, today, date = null, minDate, maxDate, empty } = + props || this.props + this.isToday = today.isSame(date, "d") + this.isValid = + date && + (date >= minDate || date.isSame(minDate, "d")) && + (date <= maxDate || date.isSame(maxDate, "d")) + this.isMid = + (date > startDate && date < endDate) || + (!date && empty >= startDate && empty <= endDate) + this.isStart = date && date.isSame(startDate, "d") + this.isStartPart = this.isStart && endDate + this.isEnd = date && date.isSame(endDate, "d") + this.isFocus = this.isMid || this.isStart || this.isEnd + return this.isFocus + } + shouldComponentUpdate (nextProps) { + const prevStatus = this.isFocus + const nextStatus = this._statusCheck(nextProps) + if (prevStatus || nextStatus) { + return true + } + return false + } + render () { + const { date, color } = this.props + const text = date ? date.date() : "" + const mainColor = { color: color.mainColor } + const subColor = { color: color.subColor } + const mainBack = { backgroundColor: color.mainColor } + const subBack = { backgroundColor: color.subColor } + return ( + + {this.isValid ? ( + + + {text} + + + ) : ( + + {text} + + )} + + ) + } } diff --git a/Month/index.js b/Month/index.js index 17ebf6a..4eb433e 100644 --- a/Month/index.js +++ b/Month/index.js @@ -2,125 +2,138 @@ * Created by TinySymphony on 2017-05-11. */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import React, { Component } from "react" +import PropTypes from "prop-types" -import { - View, - Text, - StyleSheet, - TouchableHighlight -} from 'react-native'; -import Moment from 'moment'; -import styles from './style'; -import Day from '../Day'; +import { View, Text, StyleSheet, TouchableHighlight } from "react-native" +import Moment from "moment" +import styles from "./style" +import Day from "../Day" export default class Month extends Component { - constructor (props) { - super(props); - this._getDayList = this._getDayList.bind(this); - this._renderDayRow = this._renderDayRow.bind(this); - this._getMonthText = this._getMonthText.bind(this); - } - static I18N_MAP = { - 'zh': [ - '一月', '二月', '三月', '四月', '五月', '六月', - '七月', '八月', '九月', '十月', '十一月', '十二月' - ], - 'jp': [ - '一月', '二月', '三月', '四月', '五月', '六月', - '七月', '八月', '九月', '十月', '十一月', '十二月' - ], - 'en': [ - 'January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December' - ] - } - _getMonthText () { - const { - month, - today, - i18n - } = this.props; - let y = month.year(); - let m = month.month(); - let year = today.year(); - if (year === y) { - return Month.I18N_MAP[i18n][m]; - } else { - if (i18n === 'en') { - return `${Month.I18N_MAP[i18n][m]}, ${y}`; - } - return month.format('YYYY年M月'); - } - } - _getDayList (date) { - let dayList; - let month = date.month(); - let weekday = date.isoWeekday(); - if (weekday === 7) { - dayList = []; - } else { - dayList = new Array(weekday).fill({ - empty: date.clone().subtract(1, 'h') - }); - } - while (date.month() === month) { - dayList.push({ - date: date.clone() - }); - date.add(1, 'days'); - } - date.subtract(1, 'days'); - weekday = date.isoWeekday(); - if (weekday === 7) { - return dayList.concat(new Array(6).fill({ - empty: date.clone().hour(1) - })); - } - return dayList.concat(new Array(Math.abs(weekday - 6)).fill({ - empty: date.clone().hour(1) - })); - } - _renderDayRow (dayList, index) { - const { - startDate, - endDate, - today - } = this.props; - return ( - - {dayList.map((item, i) => - - )} - - ); - } - render () { - const { - month, - today, - color - } = this.props; - let subColor = {color: color.subColor}; - let titleText = this._getMonthText(); - let dayList = this._getDayList(month.clone()); - let rowArray = new Array(dayList.length / 7).fill(''); - return ( - - - {titleText} - - - {rowArray.map((item, i) => - this._renderDayRow(dayList.slice(i * 7, i * 7 + 7), i) - )} - - - ); - } + constructor(props) { + super(props) + this._getDayList = this._getDayList.bind(this) + this._renderDayRow = this._renderDayRow.bind(this) + this._getMonthText = this._getMonthText.bind(this) + } + static I18N_MAP = { + zh: [ + "一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "九月", + "十月", + "十一月", + "十二月" + ], + jp: [ + "一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "九月", + "十月", + "十一月", + "十二月" + ], + en: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ] + } + _getMonthText() { + const { month, today, i18n } = this.props + let y = month.year() + let m = month.month() + let year = today.year() + if (year === y) { + return Month.I18N_MAP[i18n][m] + } else { + if (i18n === "en") { + return `${Month.I18N_MAP[i18n][m]}, ${y}` + } + return month.format("YYYY年M月") + } + } + _getDayList(date) { + let dayList + let month = date.month() + let weekday = date.isoWeekday() + if (weekday === 7) { + dayList = [] + } else { + dayList = new Array(weekday).fill({ + empty: date.clone().subtract(1, "h") + }) + } + while (date.month() === month) { + dayList.push({ + date: date.clone() + }) + date.add(1, "days") + } + date.subtract(1, "days") + weekday = date.isoWeekday() + if (weekday === 7) { + return dayList.concat( + new Array(6).fill({ + empty: date.clone().hour(1) + }) + ) + } + return dayList.concat( + new Array(Math.abs(weekday - 6)).fill({ + empty: date.clone().hour(1) + }) + ) + } + _renderDayRow(dayList, index) { + const { startDate, endDate, today } = this.props + return ( + + {dayList.map((item, i) => ( + + ))} + + ) + } + render() { + const { month, today, color } = this.props + let subColor = { color: color.subColor } + let titleText = this._getMonthText() + let dayList = this._getDayList(month.clone()) + let rowArray = new Array(dayList.length / 7).fill("") + return ( + + + {titleText} + + + {rowArray.map((item, i) => + this._renderDayRow(dayList.slice(i * 7, i * 7 + 7), i) + )} + + + ) + } } diff --git a/package.json b/package.json index 07aac9e..31d63c2 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,22 @@ "react-native": "^0.41.2" }, "devDependencies": { - "coveralls": "^2.13.1", - "cz-conventional-changelog": "^2.0.0", + "babel-eslint": "^8.2.1", "babel-jest": "21.2.0", "babel-preset-react-native": "4.0.0", + "coveralls": "^2.13.1", + "cz-conventional-changelog": "^2.0.0", "enzyme": "^3.2.0", "enzyme-adapter-react-16": "^1.1.0", + "eslint": "^4.13.0", + "eslint-config-react": "^1.1.7", + "eslint-config-standard": "^10.2.1", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-node": "^5.2.1", + "eslint-plugin-prettier": "^2.3.1", + "eslint-plugin-promise": "^3.6.0", + "eslint-plugin-react": "^7.5.1", + "eslint-plugin-standard": "^3.0.1", "istanbul": "^0.4.5", "jest": "21.2.1", "react": "^16.1.0", diff --git a/yarn.lock b/yarn.lock index ee50ebd..28cd6ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,58 @@ # yarn lockfile v1 +"@babel/code-frame@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.36.tgz#2349d7ec04b3a06945ae173280ef8579b63728e4" + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +"@babel/helper-function-name@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.36.tgz#366e3bc35147721b69009f803907c4d53212e88d" + dependencies: + "@babel/helper-get-function-arity" "7.0.0-beta.36" + "@babel/template" "7.0.0-beta.36" + "@babel/types" "7.0.0-beta.36" + +"@babel/helper-get-function-arity@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.36.tgz#f5383bac9a96b274828b10d98900e84ee43e32b8" + dependencies: + "@babel/types" "7.0.0-beta.36" + +"@babel/template@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.36.tgz#02e903de5d68bd7899bce3c5b5447e59529abb00" + dependencies: + "@babel/code-frame" "7.0.0-beta.36" + "@babel/types" "7.0.0-beta.36" + babylon "7.0.0-beta.36" + lodash "^4.2.0" + +"@babel/traverse@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.36.tgz#1dc6f8750e89b6b979de5fe44aa993b1a2192261" + dependencies: + "@babel/code-frame" "7.0.0-beta.36" + "@babel/helper-function-name" "7.0.0-beta.36" + "@babel/types" "7.0.0-beta.36" + babylon "7.0.0-beta.36" + debug "^3.0.1" + globals "^11.1.0" + invariant "^2.2.0" + lodash "^4.2.0" + +"@babel/types@7.0.0-beta.36": + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.36.tgz#64f2004353de42adb72f9ebb4665fc35b5499d23" + dependencies: + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^2.0.0" + "@types/node@*": version "8.0.57" resolved "http://registry.npm.taobao.org/@types/node/download/@types/node-8.0.57.tgz#e5d8b4dc112763e35cfc51988f4f38da3c486d99" @@ -42,10 +94,28 @@ acorn-globals@^3.1.0: dependencies: acorn "^4.0.4" +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + acorn@^4.0.4: version "4.0.13" resolved "http://registry.npm.taobao.org/acorn/download/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" +acorn@^5.2.1: + version "5.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822" + +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + ajv@^4.9.1: version "4.11.8" resolved "http://registry.npm.taobao.org/ajv/download/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -62,6 +132,15 @@ ajv@^5.1.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "http://registry.npm.taobao.org/align-text/download/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -152,6 +231,13 @@ array-filter@~0.0.0: version "0.0.1" resolved "http://registry.npm.taobao.org/array-filter/download/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + array-map@~0.0.0: version "0.0.0" resolved "http://registry.npm.taobao.org/array-map/download/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" @@ -160,15 +246,21 @@ array-reduce@~0.0.0: version "0.0.0" resolved "http://registry.npm.taobao.org/array-reduce/download/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" -array-uniq@^1.0.2: +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: version "1.0.3" - resolved "http://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" array-unique@^0.2.1: version "0.2.1" resolved "http://registry.npm.taobao.org/array-unique/download/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" -arrify@^1.0.1: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "http://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -222,7 +314,7 @@ aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -254,6 +346,17 @@ babel-core@^6.0.0, babel-core@^6.24.1, babel-core@^6.26.0, babel-core@^6.7.2: slash "^1.0.0" source-map "^0.5.6" +babel-eslint@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.1.tgz#136888f3c109edc65376c23ebf494f36a3e03951" + dependencies: + "@babel/code-frame" "7.0.0-beta.36" + "@babel/traverse" "7.0.0-beta.36" + "@babel/types" "7.0.0-beta.36" + babylon "7.0.0-beta.36" + eslint-scope "~3.7.1" + eslint-visitor-keys "^1.0.0" + babel-generator@^6.18.0, babel-generator@^6.24.1, babel-generator@^6.26.0: version "6.26.0" resolved "http://registry.npm.taobao.org/babel-generator/download/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" @@ -787,6 +890,10 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26 lodash "^4.17.4" to-fast-properties "^1.0.3" +babylon@7.0.0-beta.36: + version "7.0.0-beta.36" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.36.tgz#3a3683ba6a9a1e02b0aa507c8e63435e39305b9e" + babylon@^6.18.0: version "6.18.0" resolved "http://registry.npm.taobao.org/babylon/download/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" @@ -919,7 +1026,7 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" -builtin-modules@^1.0.0: +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "http://registry.npm.taobao.org/builtin-modules/download/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -931,6 +1038,16 @@ bytes@2.4.0: version "2.4.0" resolved "http://registry.npm.taobao.org/bytes/download/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + callsites@^2.0.0: version "2.0.0" resolved "http://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -968,7 +1085,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: version "2.3.0" resolved "http://registry.npm.taobao.org/chalk/download/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: @@ -995,6 +1112,10 @@ ci-info@^1.0.0: version "1.1.2" resolved "http://registry.npm.taobao.org/ci-info/download/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + cli-cursor@^2.1.0: version "2.1.0" resolved "http://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -1139,6 +1260,10 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "http://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + content-type-parser@^1.0.1: version "1.0.2" resolved "http://registry.npm.taobao.org/content-type-parser/download/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" @@ -1292,13 +1417,13 @@ dateformat@^2.0.0: version "2.2.0" resolved "http://registry.npm.taobao.org/dateformat/download/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" -debug@2.6.9, debug@^2.2.0, debug@^2.6.8: +debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@^3.1.0: +debug@^3.0.1, debug@^3.1.0: version "3.1.0" resolved "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1335,6 +1460,18 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + delayed-stream@~1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1377,6 +1514,19 @@ discontinuous-range@1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/discontinuous-range/download/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0, doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + dependencies: + esutils "^2.0.2" + dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "http://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -1506,7 +1656,7 @@ errorhandler@~1.4.2: accepts "~1.3.0" escape-html "~1.0.3" -es-abstract@^1.6.1: +es-abstract@^1.6.1, es-abstract@^1.7.0: version "1.10.0" resolved "http://registry.npm.taobao.org/es-abstract/download/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" dependencies: @@ -1558,6 +1708,136 @@ escodegen@^1.6.1: optionalDependencies: source-map "~0.5.6" +eslint-config-react@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/eslint-config-react/-/eslint-config-react-1.1.7.tgz#a0918d0fc47d0e9bd161a47308021da85d2585b3" + +eslint-config-standard@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" + +eslint-import-resolver-node@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz#fa1b6ef31fcb3c501c09859c1b86f1fc5b986894" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.6.8" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + read-pkg-up "^2.0.0" + +eslint-plugin-node@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz#80df3253c4d7901045ec87fa660a284e32bdca29" + dependencies: + ignore "^3.3.6" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "5.3.0" + +eslint-plugin-prettier@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.5.0.tgz#39a91dd7528eaf19cd42c0ee3f2c1f684606a05f" + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + +eslint-plugin-promise@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz#54b7658c8f454813dc2a870aff8152ec4969ba75" + +eslint-plugin-react@^7.5.1: + version "7.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b" + dependencies: + doctrine "^2.0.0" + has "^1.0.1" + jsx-ast-utils "^2.0.0" + prop-types "^15.6.0" + +eslint-plugin-standard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint-scope@^3.7.1, eslint-scope@~3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + +eslint@^4.13.0: + version "4.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.16.0.tgz#934ada9e98715e1d7bbfd6f6f0519ed2fab35cc1" + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.2" + esquery "^1.0.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" + dependencies: + acorn "^5.2.1" + acorn-jsx "^3.0.0" + esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "http://registry.npm.taobao.org/esprima/download/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -1570,11 +1850,24 @@ esprima@^4.0.0: version "4.0.0" resolved "http://registry.npm.taobao.org/esprima/download/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + estraverse@^1.9.1: version "1.9.3" resolved "http://registry.npm.taobao.org/estraverse/download/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" -estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "http://registry.npm.taobao.org/estraverse/download/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -1682,6 +1975,10 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" +fast-diff@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -1727,6 +2024,13 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + filename-regex@^2.0.0: version "2.0.1" resolved "http://registry.npm.taobao.org/filename-regex/download/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -1770,6 +2074,15 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + for-in@^1.0.1: version "1.0.2" resolved "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -1856,6 +2169,10 @@ function.prototype.name@^1.0.3: function-bind "^1.1.0" is-callable "^1.1.3" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + gauge@~1.2.5: version "1.2.7" resolved "http://registry.npm.taobao.org/gauge/download/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" @@ -1944,10 +2261,25 @@ global@^4.3.0: min-document "^2.19.0" process "~0.5.1" +globals@^11.0.1, globals@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.1.0.tgz#632644457f5f0e3ae711807183700ebf2e4633e4" + globals@^9.18.0: version "9.18.0" resolved "http://registry.npm.taobao.org/globals/download/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + glogg@^1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/glogg/download/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" @@ -2151,6 +2483,10 @@ iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.8, iconv-lite@~0.4.13: version "0.4.19" resolved "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +ignore@^3.3.3, ignore@^3.3.6: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + image-size@^0.6.0: version "0.6.1" resolved "http://registry.npm.taobao.org/image-size/download/image-size-0.6.1.tgz#98122a562d59dcc097ef1b2c8191866eb8f5d663" @@ -2193,7 +2529,7 @@ inquirer@^3.0.6: strip-ansi "^4.0.0" through "^2.3.6" -invariant@^2.2.2: +invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "http://registry.npm.taobao.org/invariant/download/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -2292,6 +2628,22 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "http://registry.npm.taobao.org/is-posix-bracket/download/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -2314,6 +2666,10 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -2338,7 +2694,7 @@ isarray@0.0.1: version "0.0.1" resolved "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2510,7 +2866,7 @@ jest-diff@^21.2.1: jest-get-type "^21.2.0" pretty-format "^21.2.1" -jest-docblock@^21, jest-docblock@^21.2.0: +jest-docblock@^21, jest-docblock@^21.0.0, jest-docblock@^21.2.0: version "21.2.0" resolved "http://registry.npm.taobao.org/jest-docblock/download/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" @@ -2681,7 +3037,7 @@ js-yaml@3.6.1: argparse "^1.0.7" esprima "^2.6.0" -js-yaml@3.x, js-yaml@^3.7.0: +js-yaml@3.x, js-yaml@^3.7.0, js-yaml@^3.9.1: version "3.10.0" resolved "http://registry.npm.taobao.org/js-yaml/download/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" dependencies: @@ -2732,6 +3088,10 @@ json-schema@0.2.3: version "0.2.3" resolved "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + json-stable-stringify@^1.0.1: version "1.0.1" resolved "http://registry.npm.taobao.org/json-stable-stringify/download/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" @@ -2773,6 +3133,12 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsx-ast-utils@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz#e801b1b39985e20fffc87b40e3748080e2dcac7f" + dependencies: + array-includes "^3.0.3" + kind-of@^3.0.2: version "3.2.2" resolved "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -2813,7 +3179,7 @@ leven@^2.1.0: version "2.1.0" resolved "http://registry.npm.taobao.org/leven/download/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" -levn@~0.3.0: +levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "http://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" dependencies: @@ -2882,6 +3248,10 @@ lodash._root@^3.0.0: version "3.0.1" resolved "http://registry.npm.taobao.org/lodash._root/download/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + lodash.escape@^3.0.0: version "3.2.0" resolved "http://registry.npm.taobao.org/lodash.escape/download/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" @@ -2953,7 +3323,7 @@ lodash@^3.5.0: version "3.10.1" resolved "http://registry.npm.taobao.org/lodash/download/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1: +lodash@^4.14.0, lodash@^4.15.0, lodash@^4.16.6, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.6.1: version "4.17.4" resolved "http://registry.npm.taobao.org/lodash/download/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -3409,7 +3779,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.1: +optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" dependencies: @@ -3515,6 +3885,10 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + path-key@^2.0.0: version "2.0.1" resolved "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -3571,6 +3945,12 @@ pinkie@^2.0.0: version "2.0.4" resolved "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + plist@2.0.1: version "2.0.1" resolved "http://registry.npm.taobao.org/plist/download/plist-2.0.1.tgz#0a32ca9481b1c364e92e18dc55c876de9d01da8b" @@ -3588,6 +3968,10 @@ plist@^1.2.0: xmlbuilder "4.0.0" xmldom "0.1.x" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + prelude-ls@~1.1.2: version "1.1.2" resolved "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -3619,6 +4003,10 @@ process@~0.5.1: version "0.5.2" resolved "http://registry.npm.taobao.org/process/download/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + promise@^7.1.1: version "7.3.1" resolved "http://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" @@ -4041,10 +4429,27 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "http://registry.npm.taobao.org/require-main-filename/download/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + resolve@1.1.7, resolve@1.1.x: version "1.1.7" resolved "http://registry.npm.taobao.org/resolve/download/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve@^1.3.3, resolve@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + response-time@~2.3.1: version "2.3.2" resolved "http://registry.npm.taobao.org/response-time/download/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" @@ -4073,7 +4478,7 @@ right-pad@^1.0.1: version "1.0.1" resolved "http://registry.npm.taobao.org/right-pad/download/right-pad-1.0.1.tgz#8ca08c2cbb5b55e74dafa96bf7fd1a27d568c8d0" -rimraf@2, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: version "2.6.2" resolved "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -4144,6 +4549,10 @@ sax@~1.1.1: version "5.4.1" resolved "http://registry.npm.taobao.org/semver/download/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" +semver@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + send@0.13.2: version "0.13.2" resolved "http://registry.npm.taobao.org/send/download/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" @@ -4237,6 +4646,12 @@ slash@^1.0.0: version "1.0.0" resolved "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + slide@^1.1.5: version "1.1.6" resolved "http://registry.npm.taobao.org/slide/download/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -4352,7 +4767,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0: +string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "http://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -4427,6 +4842,17 @@ sync-exec@~0.6.x: version "0.6.2" resolved "http://registry.npm.taobao.org/sync-exec/download/sync-exec-0.6.2.tgz#717d22cc53f0ce1def5594362f3a89a2ebb91105" +table@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + tar-pack@^3.4.0: version "3.4.1" resolved "http://registry.npm.taobao.org/tar-pack/download/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -4465,6 +4891,10 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + throat@^4.0.0, throat@^4.1.0: version "4.1.0" resolved "http://registry.npm.taobao.org/throat/download/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -4498,6 +4928,10 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "http://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + tough-cookie@^2.3.2, tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" @@ -4772,6 +5206,12 @@ write-file-atomic@^2.1.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + ws@^1.1.0: version "1.1.5" resolved "http://registry.npm.taobao.org/ws/download/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" From 53cb419b61f4cf9e0b075b85899c29e090ca8f33 Mon Sep 17 00:00:00 2001 From: ahmad Date: Wed, 24 Jan 2018 15:31:32 +0500 Subject: [PATCH 05/13] setup selectionType btns n close on Day type selection --- Calendar.js | 82 +++++++++++++++-- CalendarStyle.js | 228 +++++++++++++++++++++++++---------------------- 2 files changed, 195 insertions(+), 115 deletions(-) diff --git a/Calendar.js b/Calendar.js index 6f3ca5c..480b7c3 100644 --- a/Calendar.js +++ b/Calendar.js @@ -28,10 +28,11 @@ export default class Calendar extends Component { selectionType: PropTypes.string } static defaultProps = { - format : "YYYY-MM-DD", - i18n : "en", - customI18n: {}, - color : {} + format : "YYYY-MM-DD", + i18n : "en", + customI18n : {}, + color : {}, + selectionType: "manual" } static I18N_MAP = { zh: { @@ -80,10 +81,12 @@ export default class Calendar extends Component { date: "M月D日" } } + constructor (props) { super(props) this.state = { - isModalVisible: false + isModalVisible: false, + selectionType : "manual" } this._today = Moment() this._year = this._today.year() @@ -92,15 +95,23 @@ export default class Calendar extends Component { this._onChoose = this._onChoose.bind(this) this._resetCalendar = this._resetCalendar.bind(this) this.close = this.close.bind(this) + this.selection = this.selection.bind(this) this.cancel = this.cancel.bind(this) this.open = this.open.bind(this) this.clear = this.clear.bind(this) this.confirm = this.confirm.bind(this) this._getDateRange() } + componentDidMount () { + const { selectionType } = this.props this._resetCalendar() + + this.setState({ + selectionType + }) } + _i18n (data, type) { const { i18n, customI18n } = this.props if (~["w", "weekday", "text"].indexOf(type)) { @@ -110,6 +121,7 @@ export default class Calendar extends Component { return data.format(customI18n[type] || Calendar.I18N_MAP[i18n][type]) } } + _resetCalendar () { const { startDate, endDate, format } = this.props const start = Moment(startDate, format) @@ -125,6 +137,7 @@ export default class Calendar extends Component { endWeekdayText : isEndValid ? this._i18n(end.isoWeekday(), "weekday") : "" }) } + _getDateRange () { const { maxDate, minDate, format } = this.props let max = Moment(maxDate, format) @@ -147,6 +160,7 @@ export default class Calendar extends Component { this._minDate = min this._maxDate = max } + _onChoose (day, selectionType) { const { startDate, endDate } = this.state @@ -160,8 +174,9 @@ export default class Calendar extends Component { endDateText : this._i18n(day, "date"), endWeekdayText : this._i18n(day.isoWeekday(), "weekday") }) - } + this.confirm({ startDate: day, endDate: day }) + } return } @@ -182,20 +197,44 @@ export default class Calendar extends Component { }) } } + + radioBtnsStyle (_selectionType) { + const { color: { borderColor } } = this.props + const { selectionType } = this.state + + const selected = selectionType === _selectionType + const btnColor = borderColor || "rgba(255, 255, 255, 0.5)" + + return { + backgroundColor: selected ? btnColor : "transparent" + } + } + cancel () { this.close() this._resetCalendar() } + close () { this.setState({ isModalVisible: false }) } + + selection (selectionType) { + this.clear() + + this.setState({ + selectionType + }) + } + open () { this.setState({ isModalVisible: true }) } + clear () { this.setState({ startDate : null, @@ -206,8 +245,9 @@ export default class Calendar extends Component { endWeekdayText : "" }) } - confirm () { - const { startDate, endDate } = this.state + + confirm (state) { + const { startDate, endDate } = state || this.state const startMoment = startDate ? startDate.clone() : null const endMoment = endDate ? endDate.clone() : null this.props.onConfirm && @@ -219,6 +259,7 @@ export default class Calendar extends Component { }) this.close() } + render () { const { startDate, @@ -228,7 +269,7 @@ export default class Calendar extends Component { endDateText, endWeekdayText } = this.state - const { selectionType } = this.props + const { selectionType } = this.state const { mainColor = "#15aaaa", subColor = "#fff", @@ -306,6 +347,29 @@ export default class Calendar extends Component { /> + + this.selection("day")} + > + Day + + this.selection("week")} + > + Week + + this.selection("manual")} + > + Manual + + {isValid ? ( Date: Wed, 24 Jan 2018 16:04:35 +0500 Subject: [PATCH 06/13] updated README for selctionType Example --- Calendar.js | 2 +- readme.md | 39 +++++++++++++++++------------- {GIF => screenshots}/a-en.gif | Bin {GIF => screenshots}/a-jp.gif | Bin {GIF => screenshots}/a-zh.gif | Bin {GIF => screenshots}/ios-en.gif | Bin {GIF => screenshots}/ios-jp.gif | Bin {GIF => screenshots}/ios-zh.gif | Bin screenshots/selectionTypeBtns.png | Bin 0 -> 92888 bytes 9 files changed, 23 insertions(+), 18 deletions(-) rename {GIF => screenshots}/a-en.gif (100%) rename {GIF => screenshots}/a-jp.gif (100%) rename {GIF => screenshots}/a-zh.gif (100%) rename {GIF => screenshots}/ios-en.gif (100%) rename {GIF => screenshots}/ios-jp.gif (100%) rename {GIF => screenshots}/ios-zh.gif (100%) create mode 100644 screenshots/selectionTypeBtns.png diff --git a/Calendar.js b/Calendar.js index 480b7c3..5a57da9 100644 --- a/Calendar.js +++ b/Calendar.js @@ -25,7 +25,7 @@ export default class Calendar extends Component { }), minDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), maxDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), - selectionType: PropTypes.string + selectionType: PropTypes.oneOfType(["manual", "week", "day"]) } static defaultProps = { format : "YYYY-MM-DD", diff --git a/readme.md b/readme.md index 65f83fe..d3c38d4 100644 --- a/readme.md +++ b/readme.md @@ -4,21 +4,25 @@ A date picker component like Airbnb. You can select a date period from the calen ### Examples +#### Selection Types Example + + + #### iOS Examples - + - + - + #### Android Examples - + - + - + ### Usage @@ -101,17 +105,18 @@ render() { ### Properties -| Property | Type | Default | Description | -| ---------- | --------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | -| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | -| color | Object | {} | Customize color. | -| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | -| minDate | String / Object | - | Min date of calendar | -| maxDate | String / Object | - | Max date of calendar | -| startDate | String / Object | null | Start date of selection | -| endDate | String / Object | null | End date of selection | -| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | +| Property | Type | Default | Description | +| ------------- | --------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | +| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | +| color | Object | {} | Customize color. | +| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | +| minDate | String / Object | - | Min date of calendar | +| maxDate | String / Object | - | Max date of calendar | +| startDate | String / Object | null | Start date of selection | +| endDate | String / Object | null | End date of selection | +| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | +| selectionType | String | "manual" | Initial (optional) selection type can be one of "manual", "week" and "day" | ### Instance methods diff --git a/GIF/a-en.gif b/screenshots/a-en.gif similarity index 100% rename from GIF/a-en.gif rename to screenshots/a-en.gif diff --git a/GIF/a-jp.gif b/screenshots/a-jp.gif similarity index 100% rename from GIF/a-jp.gif rename to screenshots/a-jp.gif diff --git a/GIF/a-zh.gif b/screenshots/a-zh.gif similarity index 100% rename from GIF/a-zh.gif rename to screenshots/a-zh.gif diff --git a/GIF/ios-en.gif b/screenshots/ios-en.gif similarity index 100% rename from GIF/ios-en.gif rename to screenshots/ios-en.gif diff --git a/GIF/ios-jp.gif b/screenshots/ios-jp.gif similarity index 100% rename from GIF/ios-jp.gif rename to screenshots/ios-jp.gif diff --git a/GIF/ios-zh.gif b/screenshots/ios-zh.gif similarity index 100% rename from GIF/ios-zh.gif rename to screenshots/ios-zh.gif diff --git a/screenshots/selectionTypeBtns.png b/screenshots/selectionTypeBtns.png new file mode 100644 index 0000000000000000000000000000000000000000..727ee4764254bc5c6200323852ea706f8b493f2d GIT binary patch literal 92888 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 Date: Wed, 24 Jan 2018 17:13:01 +0500 Subject: [PATCH 07/13] corrected README syntax for selectionType --- readme.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/readme.md b/readme.md index d3c38d4..4fb71c4 100644 --- a/readme.md +++ b/readme.md @@ -105,18 +105,18 @@ render() { ### Properties -| Property | Type | Default | Description | -| ------------- | --------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | -| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | -| color | Object | {} | Customize color. | -| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | -| minDate | String / Object | - | Min date of calendar | -| maxDate | String / Object | - | Max date of calendar | -| startDate | String / Object | null | Start date of selection | -| endDate | String / Object | null | End date of selection | -| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | -| selectionType | String | "manual" | Initial (optional) selection type can be one of "manual", "week" and "day" | +| Property | Type | Default | Description | +| ------------- | ----------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| i18n | String | 'en' | Language of the component, supports `en` / `zh` / `jp`. | +| customI18n | Object | {} | Customize text of the component, the structure of this object is shown in the example above. | +| color | Object | {} | Customize color. | +| format | string | 'YYYY-MM-DD' | Define date format, you can also pass Date Object or Moment Object as props. | +| minDate | String / Object | - | Min date of calendar | +| maxDate | String / Object | - | Max date of calendar | +| startDate | String / Object | null | Start date of selection | +| endDate | String / Object | null | End date of selection | +| onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | +| selectionType | enum(`manual`, `week`, `day`) | "manual" | Initial (optional) selection type can be one of `manual`, `week` and `day` | ### Instance methods From dc5b15d09826d4408ca1db66777617dd56849e6b Mon Sep 17 00:00:00 2001 From: ahmad Date: Thu, 25 Jan 2018 12:30:59 +0500 Subject: [PATCH 08/13] Setup Week selection --- Calendar.js | 36 +++++- MonthList.js | 283 +++++++++++++++++++++++++---------------------- index.android.js | 2 +- index.ios.js | 236 +++++++++++++++++++-------------------- 4 files changed, 303 insertions(+), 254 deletions(-) diff --git a/Calendar.js b/Calendar.js index 5a57da9..863970a 100644 --- a/Calendar.js +++ b/Calendar.js @@ -112,6 +112,14 @@ export default class Calendar extends Component { }) } + componentDidUpdate (nextProps, nextState) { + const { startDate, endDate } = this.state + + if (startDate && !endDate) { + this._onChoose(startDate, "week") + } + } + _i18n (data, type) { const { i18n, customI18n } = this.props if (~["w", "weekday", "text"].indexOf(type)) { @@ -180,6 +188,28 @@ export default class Calendar extends Component { return } + if (selectionType === "week") { + if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { + const startDay = day.clone().startOf("week") + this.setState({ + startDate : startDay, + endDate : null, + startDateText : this._i18n(startDay, "date"), + startWeekdayText: this._i18n(startDay.isoWeekday(), "weekday"), + endDateText : "", + endWeekdayText : "" + }) + } else if (startDate && !endDate) { + const endDay = day.clone().endOf("week") + this.setState({ + endDate : endDay, + endDateText : this._i18n(endDay, "date"), + endWeekdayText: this._i18n(endDay.isoWeekday(), "weekday") + }) + } + return + } + if ((!startDate && !endDate) || day < startDate || (startDate && endDate)) { this.setState({ startDate : day, @@ -247,7 +277,10 @@ export default class Calendar extends Component { } confirm (state) { - const { startDate, endDate } = state || this.state + let { startDate, endDate } = state // State is proxy coming from touchableOpacity + startDate = startDate || this.state.startDate + endDate = endDate || this.state.endDate + const startMoment = startDate ? startDate.clone() : null const endMoment = endDate ? endDate.clone() : null this.props.onConfirm && @@ -281,6 +314,7 @@ export default class Calendar extends Component { const subFontColor = { color: subColor } const isValid = !startDate || endDate const isClearVisible = startDate || endDate + return ( { - return r2.shouldUpdate; - } - }); - this.monthList = []; - this.state = { - dataSource: this.ds.cloneWithRows(this._getMonthList()) - }; - this._renderMonth = this._renderMonth.bind(this); - this._shouldUpdate = this._shouldUpdate.bind(this); - this._checkRange = this._checkRange.bind(this); - this._getWeekNums = this._getWeekNums.bind(this); - this._scrollToSelecetdMonth = this._scrollToSelecetdMonth.bind(this); - } - componentWillReceiveProps (nextProps) { - let isDateUpdated = ['startDate', 'endDate', 'minDate', 'maxDate'].reduce((prev, next) => { - if (prev || nextProps[next] !== this.props[next]) { - return true; - } - return prev; - }, false); - if (isDateUpdated) { - this.setState({ - dataSource: - this.state.dataSource.cloneWithRows(this._getMonthList(nextProps)) - }); - } - } - _renderMonth (month) { - return ( - - ); - } - _checkRange (date, start, end) { - if (!date || !start) return false; - if (!end) return date.year() === start.year() && date.month() === start.month(); - if (date.year() < start.year() || (date.year() === start.year() && date.month() < start.month())) return false; - if (date.year() > end.year() || (date.year() === end.year() && date.month() > end.month())) return false; - return true; - } - _shouldUpdate (month, props) { - if (!props) return false; - const { - startDate, - endDate - } = props; - const { - date - } = month; - let next = this._checkRange(date, startDate, endDate); - let prev = this._checkRange(date, this.props.startDate, this.props.endDate); - if (prev || next) return true; - return false; - } - _getMonthList (props) { - let minDate = (props || this.props).minDate.clone().date(1); - let maxDate = (props || this.props).maxDate.clone(); - let monthList = []; - if (!maxDate || !minDate) return monthList; - while (maxDate > minDate || ( - maxDate.year() === minDate.year() && - maxDate.month() === minDate.month() - )) { - let month = { - date: minDate.clone() - }; - month.shouldUpdate = this._shouldUpdate(month, props); - monthList.push(month); - minDate.add(1, 'month'); - } - return monthList; - } - _getWeekNums(start, end) { - let clonedMoment = Moment(start), date, day, num, y, m, total = 0; - while (!clonedMoment.isSame(end, 'months')) { - y = clonedMoment.year(); - m = clonedMoment.month(); - date = new Date(y, m, 1); - day = date.getDay(); - num = new Date(y, m + 1, 0).getDate(); - total += Math.ceil((num + day) / 7); - clonedMoment.add(1, 'months'); - } - return total; - } - _scrollToSelecetdMonth () { - const { - startDate, - minDate - } = this.props; - let monthOffset = 12 * (startDate.year() - minDate.year()) + - startDate.month() - minDate.month(); - let weekOffset = this._getWeekNums(minDate, startDate); - setTimeout(() => { - this.list && this.list.scrollTo({ - x: 0, - y: monthOffset * (24 + 25) + (monthOffset ? weekOffset * Math.ceil(width / 7 + 10) : 0), - animated: true - }); - }, 400); - } - componentDidMount () { - this.props.startDate && this._scrollToSelecetdMonth(); - } - render () { - return ( - {this.list = list;}} - style={styles.scrollArea} - dataSource={this.state.dataSource} - renderRow={this._renderMonth} - pageSize={2} - initialListSize={2} - showsVerticalScrollIndicator={false} - /> - ); - } + constructor (props) { + super(props) + this.ds = new ListView.DataSource({ + rowHasChanged: (r1, r2) => { + return r2.shouldUpdate + } + }) + this.monthList = [] + this.state = { + dataSource: this.ds.cloneWithRows(this._getMonthList()) + } + this._renderMonth = this._renderMonth.bind(this) + this._shouldUpdate = this._shouldUpdate.bind(this) + this._checkRange = this._checkRange.bind(this) + this._getWeekNums = this._getWeekNums.bind(this) + this._scrollToSelectedMonth = this._scrollToSelectedMonth.bind(this) + } + componentWillReceiveProps (nextProps) { + const isDateUpdated = ["startDate", "endDate", "minDate", "maxDate"].reduce( + (prev, next) => { + if (prev || nextProps[next] !== this.props[next]) { + return true + } + return prev + }, + false + ) + if (isDateUpdated) { + this.setState({ + dataSource: this.state.dataSource.cloneWithRows(this._getMonthList(nextProps)) + }) + } + } + _renderMonth (month) { + return + } + _checkRange (date, start, end) { + if (!date || !start) { + return false + } + if (!end) { + return date.year() === start.year() && date.month() === start.month() + } + if ( + date.year() < start.year() || + (date.year() === start.year() && date.month() < start.month()) + ) { + return false + } + if ( + date.year() > end.year() || + (date.year() === end.year() && date.month() > end.month()) + ) { + return false + } + return true + } + _shouldUpdate (month, props) { + if (!props) { + return false + } + const { startDate, endDate } = props + const { date } = month + const next = this._checkRange(date, startDate, endDate) + const prev = this._checkRange(date, this.props.startDate, this.props.endDate) + if (prev || next) { + return true + } + return false + } + _getMonthList (props) { + const minDate = (props || this.props).minDate.clone().date(1) + const maxDate = (props || this.props).maxDate.clone() + const monthList = [] + if (!maxDate || !minDate) { + return monthList + } + while ( + maxDate > minDate || // eslint-disable-line no-unmodified-loop-condition + (maxDate.year() === minDate.year() && maxDate.month() === minDate.month()) + ) { + const month = { + date: minDate.clone() + } + month.shouldUpdate = this._shouldUpdate(month, props) + monthList.push(month) + minDate.add(1, "month") + } + return monthList + } + _getWeekNums (start, end) { + const clonedMoment = Moment(start) + let date + let day + let num + let y + let m + let total = 0 + while (!clonedMoment.isSame(end, "months")) { + y = clonedMoment.year() + m = clonedMoment.month() + date = new Date(y, m, 1) + day = date.getDay() + num = new Date(y, m + 1, 0).getDate() + total += Math.ceil((num + day) / 7) + clonedMoment.add(1, "months") + } + return total + } + _scrollToSelectedMonth () { + const { startDate, minDate } = this.props + const monthOffset = + 12 * (startDate.year() - minDate.year()) + startDate.month() - minDate.month() + const weekOffset = this._getWeekNums(minDate, startDate) + setTimeout(() => { + this.list && + this.list.scrollTo({ + x: 0, + y: + monthOffset * (24 + 25) + + (monthOffset ? weekOffset * Math.ceil(width / 7 + 10) : 0), + animated: true + }) + }, 400) + } + componentDidMount () { + this.props.startDate && this._scrollToSelectedMonth() + } + render () { + return ( + { + this.list = list + }} + style={styles.scrollArea} + dataSource={this.state.dataSource} + renderRow={this._renderMonth} + pageSize={2} + initialListSize={2} + showsVerticalScrollIndicator={false} + /> + ) + } } diff --git a/index.android.js b/index.android.js index afbb090..61cc512 100644 --- a/index.android.js +++ b/index.android.js @@ -2,4 +2,4 @@ * Created by TinySymphony on 2017-05-08. */ -export {default} from './index.ios.js'; +export { default } from "./index.ios.js" diff --git a/index.ios.js b/index.ios.js index 353665e..9b2151d 100644 --- a/index.ios.js +++ b/index.ios.js @@ -2,127 +2,127 @@ * Created by TinySymphony on 2017-05-08. */ -import React, { Component } from 'react'; -import { - AppRegistry, - StyleSheet, - Text, - View, - TouchableHighlight -} from 'react-native'; -import Calendar from './Calendar'; +import React, { Component } from "react" +import { AppRegistry, StyleSheet, Text, View, TouchableHighlight } from "react-native" +import Calendar from "./Calendar" export default class calendar extends Component { - constructor(props) { - super(props); - this.calendar = null; - this.state = { - startDate: new Date(2017, 7, 12), - endDate: new Date(2017, 8, 23) - }; - this.openCalendar = this.openCalendar.bind(this); - this.confirmDate = this.confirmDate.bind(this); - } - // when confirm button is clicked, an object is conveyed to outer component - // contains following property: - // startDate [Date Object], endDate [Date Object] - // startMoment [Moment Object], endMoment [Moment Object] - confirmDate ({startDate, endDate, startMoment, endMoment}) { - console.log(startDate, endDate, startMoment, endMoment); - this.setState({ - startDate, - endDate - }); - } - openCalendar() { - !!this.calendar && this.calendar.open(); - } - render() { - // It's an optional property, I use this to show the structure of customI18n object. - let customI18n = { - 'w': ['', 'Mon', 'Tues', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun'], - 'weekday': ['', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], - 'text': { - 'start': 'Check in', - 'end': 'Check out', - 'date': 'Date', - 'save': 'Confirm', - 'clear': 'Reset' - }, - 'date': 'DD / MM' // date format - }; - // optional property, too. - let color = { - mainColor: '#138691' - }; - const { - startDate, - endDate - } = this.state; - let text = startDate && endDate ? startDate.toLocaleDateString() + ' / ' + endDate.toLocaleDateString() : - 'Please select a period'; - return ( - - - Choose Dates - - - {text} - - {this.calendar = calendar;}} - format="YYYYMMDD" - minDate="20170510" - maxDate="20180412" - startDate={this.state.startDate} - endDate={this.state.endDate} - onConfirm={this.confirmDate} - /> - - ); - } + constructor (props) { + super(props) + this.calendar = null + this.state = { + startDate: new Date(2017, 7, 12), + endDate : new Date(2017, 8, 23) + } + this.openCalendar = this.openCalendar.bind(this) + this.confirmDate = this.confirmDate.bind(this) + } + // when confirm button is clicked, an object is conveyed to outer component + // contains following property: + // startDate [Date Object], endDate [Date Object] + // startMoment [Moment Object], endMoment [Moment Object] + confirmDate ({ startDate, endDate, startMoment, endMoment }) { + console.log(startDate, endDate, startMoment, endMoment) + this.setState({ + startDate, + endDate + }) + } + openCalendar () { + !!this.calendar && this.calendar.open() + } + render () { + // It's an optional property, I use this to show the structure of customI18n object. + // const customI18n = { + // w : ["", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat", "Sun"], + // weekday: [ + // "", + // "Monday", + // "Tuesday", + // "Wednesday", + // "Thursday", + // "Friday", + // "Saturday", + // "Sunday" + // ], + // text: { + // start: "Check in", + // end : "Check out", + // date : "Date", + // save : "Confirm", + // clear: "Reset" + // }, + // date: "DD / MM" // date format + // } + // optional property, too. + const color = { + mainColor: "#138691" + } + const { startDate, endDate } = this.state + const text = + startDate && endDate + ? startDate.toLocaleDateString() + " / " + endDate.toLocaleDateString() + : "Please select a period" + return ( + + + Choose Dates + + + {text} + + { + this.calendar = calendar + }} + format="YYYYMMDD" + minDate="20170510" + maxDate="20180412" + startDate={this.state.startDate} + endDate={this.state.endDate} + onConfirm={this.confirmDate} + /> + + ) + } } const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#F5FCFF', - }, - btn: { - paddingHorizontal: 20, - paddingVertical: 10, - overflow: 'hidden', - borderRadius: 6, - marginBottom: 30, - backgroundColor: '#138691' - }, - btnFont: { - color: '#fff', - fontSize: 20 - }, - welcome: { - fontSize: 20, - textAlign: 'center', - margin: 10, - }, - font: { - fontSize: 24, - fontWeight: '400', - color: '#304853' - }, - instructions: { - textAlign: 'center', - color: '#333333', - marginBottom: 5, - }, -}); + container: { + flex : 1, + justifyContent : "center", + alignItems : "center", + backgroundColor: "#F5FCFF" + }, + btn: { + paddingHorizontal: 20, + paddingVertical : 10, + overflow : "hidden", + borderRadius : 6, + marginBottom : 30, + backgroundColor : "#138691" + }, + btnFont: { + color : "#fff", + fontSize: 20 + }, + welcome: { + fontSize : 20, + textAlign: "center", + margin : 10 + }, + font: { + fontSize : 24, + fontWeight: "400", + color : "#304853" + }, + instructions: { + textAlign : "center", + color : "#333333", + marginBottom: 5 + } +}) -AppRegistry.registerComponent('calendar', () => calendar); +AppRegistry.registerComponent("calendar", () => calendar) From 7ccb783726b90f219a54505c8f6d25f82272b57c Mon Sep 17 00:00:00 2001 From: ahmad Date: Thu, 25 Jan 2018 12:33:45 +0500 Subject: [PATCH 09/13] fixed selectionType prop typo from oneOfType to oneOf --- Calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Calendar.js b/Calendar.js index 863970a..efa69c6 100644 --- a/Calendar.js +++ b/Calendar.js @@ -25,7 +25,7 @@ export default class Calendar extends Component { }), minDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), maxDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), - selectionType: PropTypes.oneOfType(["manual", "week", "day"]) + selectionType: PropTypes.oneOf(["manual", "week", "day"]) } static defaultProps = { format : "YYYY-MM-DD", From af034b6a64ac971a8a2cb32059aba5d60cfedff6 Mon Sep 17 00:00:00 2001 From: ahmad Date: Thu, 25 Jan 2018 12:43:09 +0500 Subject: [PATCH 10/13] exposed modal animation prop --- Calendar.js | 16 ++++++++++------ readme.md | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Calendar.js b/Calendar.js index efa69c6..7565cc1 100644 --- a/Calendar.js +++ b/Calendar.js @@ -25,14 +25,16 @@ export default class Calendar extends Component { }), minDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), maxDate : PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]), - selectionType: PropTypes.oneOf(["manual", "week", "day"]) + selectionType: PropTypes.oneOf(["manual", "week", "day"]), + animationType: PropTypes.oneOf(["none", "slide", "fade"]) } static defaultProps = { format : "YYYY-MM-DD", i18n : "en", customI18n : {}, color : {}, - selectionType: "manual" + selectionType: "manual", + animationType: "slide" } static I18N_MAP = { zh: { @@ -300,9 +302,11 @@ export default class Calendar extends Component { startDateText, startWeekdayText, endDateText, - endWeekdayText + endWeekdayText, + isModalVisible, + selectionType } = this.state - const { selectionType } = this.state + const { animationType } = this.props const { mainColor = "#15aaaa", subColor = "#fff", @@ -317,8 +321,8 @@ export default class Calendar extends Component { return ( diff --git a/readme.md b/readme.md index 4fb71c4..b8d3fc5 100644 --- a/readme.md +++ b/readme.md @@ -117,6 +117,7 @@ render() { | endDate | String / Object | null | End date of selection | | onConfirm | Function | - | Callback function when the period is confirmed, receives an object as only parameter, contains `startDate` / `endDate` / `startMoment` / `endMoment` four property. | | selectionType | enum(`manual`, `week`, `day`) | "manual" | Initial (optional) selection type can be one of `manual`, `week` and `day` | +| animationType | enum(`slide`, `fade`, `none`) | "slide" | Initial (optional) animation type can be one of `slide`, `fade` and `none` | ### Instance methods From e8c4fc5223ff792eb0cdfa4f4cf255ae52fa3f5b Mon Sep 17 00:00:00 2001 From: ahmad Date: Thu, 25 Jan 2018 13:18:28 +0500 Subject: [PATCH 11/13] manual selection endDate not working fixed --- Calendar.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Calendar.js b/Calendar.js index 7565cc1..cf35c3a 100644 --- a/Calendar.js +++ b/Calendar.js @@ -115,9 +115,9 @@ export default class Calendar extends Component { } componentDidUpdate (nextProps, nextState) { - const { startDate, endDate } = this.state + const { startDate, endDate, selectionType } = this.state - if (startDate && !endDate) { + if (startDate && !endDate && selectionType === "week") { this._onChoose(startDate, "week") } } @@ -222,6 +222,9 @@ export default class Calendar extends Component { endWeekdayText : "" }) } else if (startDate && !endDate && day > startDate) { + console.log("=========Running endDate=============") + console.log(startDate, endDate) + console.log("====================================") this.setState({ endDate : day, endDateText : this._i18n(day, "date"), From 86ec23c67ed1b0653c0251e0f1863e3ee429b03a Mon Sep 17 00:00:00 2001 From: ahmad Date: Mon, 12 Feb 2018 16:30:49 +0500 Subject: [PATCH 12/13] removed console logs --- Calendar.js | 3 --- index.ios.js | 1 - 2 files changed, 4 deletions(-) diff --git a/Calendar.js b/Calendar.js index cf35c3a..6886da9 100644 --- a/Calendar.js +++ b/Calendar.js @@ -222,9 +222,6 @@ export default class Calendar extends Component { endWeekdayText : "" }) } else if (startDate && !endDate && day > startDate) { - console.log("=========Running endDate=============") - console.log(startDate, endDate) - console.log("====================================") this.setState({ endDate : day, endDateText : this._i18n(day, "date"), diff --git a/index.ios.js b/index.ios.js index 9b2151d..c92da13 100644 --- a/index.ios.js +++ b/index.ios.js @@ -22,7 +22,6 @@ export default class calendar extends Component { // startDate [Date Object], endDate [Date Object] // startMoment [Moment Object], endMoment [Moment Object] confirmDate ({ startDate, endDate, startMoment, endMoment }) { - console.log(startDate, endDate, startMoment, endMoment) this.setState({ startDate, endDate From fd2ca578feebb91c8ea78f59a81e5c1735a92aa2 Mon Sep 17 00:00:00 2001 From: ahmad Date: Tue, 6 Mar 2018 17:55:24 +0500 Subject: [PATCH 13/13] added Apply btn inplace of Save btn --- Calendar.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Calendar.js b/Calendar.js index 6886da9..b6f82fb 100644 --- a/Calendar.js +++ b/Calendar.js @@ -42,6 +42,7 @@ export default class Calendar extends Component { weekday: ["", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], text : { start: "开 始", + apply: "开 始", end : "结 束", date : "日 期", save : "保 存", @@ -63,6 +64,7 @@ export default class Calendar extends Component { ], text: { start: "Start", + apply: "Apply", end : "End", date : "Date", save : "Save", @@ -75,6 +77,7 @@ export default class Calendar extends Component { weekday: ["", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"], text : { start: "スタート", + apply: "スタート", end : "エンド", date : "時 間", save : "確 認", @@ -420,7 +423,7 @@ export default class Calendar extends Component { numberOfLines={1} style={[styles.confirmText, subFontColor]} > - {this._i18n("save", "text")} + {this._i18n("apply", "text")} @@ -434,7 +437,7 @@ export default class Calendar extends Component { numberOfLines={1} style={[styles.confirmText, styles.confirmTextDisabled]} > - {this._i18n("save", "text")} + {this._i18n("apply", "text")}