diff --git a/README.md b/README.md index 3f2346138..d224f7555 100644 --- a/README.md +++ b/README.md @@ -17,39 +17,8 @@ $ npm install --save react-date-range ``` ## Usage -### Date Picker -```javascript -import React, { Component } from 'react'; -import { Calendar } from 'react-date-range'; - -class MyComponent extends Component { - handleSelect(date){ - console.log(date); // Momentjs object - } - - render(){ - return ( -
- -
- ) - } -} - -``` - -###### Available Options (props) -* **date:** *(String, Moment.js object, Function)* - default: today -* **format:** *(String)* - default: DD/MM/YYY -* **firstDayOfWeek** *(Number)* - default: [moment.localeData().firstDayOfWeek()](http://momentjs.com/docs/#/i18n/locale-data/) -* **theme:** *(Object)* see [Demo's source](https://github.com/Adphorus/react-date-range/blob/master/demo/src/components/Main.js#L130) -* **onInit:** *(Function)* default: none -* **onChange:** *(Function)* default: none -### Range Picker +### ```javascript import React, { Component } from 'react'; import { DateRange } from 'react-date-range'; @@ -85,3 +54,11 @@ class MyComponent extends Component { * **linkedCalendars:** *(Boolean)* default: false * **calendars:** *(Number)* default: 2 * **ranges:** *(Object)* default: none +* **selectYear** *(Boolean)* default: false +Activates select year dropdown. +* **yearRange** *(Object)* default: ```{start: 10, end: 10}``` +Specifies the year range of the options in selectYear dropdown. +* **pickSingleDate** *(Boolean)* +Calendar only picks a single date. +* **showIndex** *(Number)* +Specifies the calendar where the date will be shown if there are multiple calendars. diff --git a/demo/build.js b/demo/build.js index 176bdd06e..a7ba16d51 100644 --- a/demo/build.js +++ b/demo/build.js @@ -63,7 +63,7 @@ if (NODE_ENV === 'production') { })); } else if (NODE_ENV === 'development') { config.entry.main.unshift('webpack/hot/only-dev-server'); - config.entry.main.unshift('webpack-dev-server/client?http://0.0.0.0:3000'); + config.entry.main.unshift('webpack-dev-server/client?http://0.0.0.0:5000'); config.plugins.push(new webpack.HotModuleReplacementPlugin()); } @@ -83,8 +83,8 @@ if (NODE_ENV === 'development') { } }); - server.listen(3000, 'localhost', function(){ - console.log('Webpack Dev Server is listening on port 3000'); + server.listen(5000, 'localhost', function(){ + console.log('Webpack Dev Server is listening on port 5000'); }); } else if (NODE_ENV === 'production') { compiler.run(function (err, stats) { diff --git a/demo/src/components/Main.js b/demo/src/components/Main.js index 1ba8fb4a9..07eb46126 100644 --- a/demo/src/components/Main.js +++ b/demo/src/components/Main.js @@ -34,7 +34,7 @@ export default class Main extends Component {

React-date-range

-
+
{ - return '11/12/2015'; - }} - onInit={ this.handleChange.bind(this, 'rangePicker') } - onChange={ this.handleChange.bind(this, 'rangePicker') } - /> -
- -
-
- - -
- { - return '9/10/2015'; - }} - endDate={ now => { - return '13/11/2015'; - }} + pickSingleDate={ true } linkedCalendars={ true } - onInit={ this.handleChange.bind(this, 'linked') } - onChange={ this.handleChange.bind(this, 'linked') } - /> -
- -
-
- -
- { return now.add(-4, 'days') } } - onInit={ this.handleChange.bind(this, 'datePicker') } - onChange={ this.handleChange.bind(this, 'datePicker') } - /> -
- -
-
- -
- { return now.add(-4, 'days') } } - onInit={ this.handleChange.bind(this, 'firstDayOfWeek') } - onChange={ this.handleChange.bind(this, 'firstDayOfWeek') } - /> -
- -
-
- - -
- -
- -
-
-
diff --git a/demo/src/styles/main.css b/demo/src/styles/main.css index 54e26a64f..5aa998a6a 100644 --- a/demo/src/styles/main.css +++ b/demo/src/styles/main.css @@ -32,7 +32,7 @@ } :local(.Demo) { - width: 560px; + width: 700px; float: left; } diff --git a/lib/Calendar.js b/lib/Calendar.js index c8a5c6da3..9799158a0 100644 --- a/lib/Calendar.js +++ b/lib/Calendar.js @@ -69,10 +69,15 @@ var Calendar = (function (_Component) { var theme = props.theme; var offset = props.offset; var firstDayOfWeek = props.firstDayOfWeek; + var index = props.index; var date = (0, _utilsParseInputJs2['default'])(props.date, format); + var test = range && range['endDate'] || date; + var state = { date: date, + index: index, + inputtedDate: props.date ? true : false, shownDate: (range && range['endDate'] || date).clone().add(offset, 'months'), firstDayOfWeek: firstDayOfWeek || _moment2['default'].localeData().firstDayOfWeek() }; @@ -105,10 +110,10 @@ var Calendar = (function (_Component) { var _props2 = this.props; var link = _props2.link; var onChange = _props2.onChange; + var offset = _props2.offset; var date = this.state.date; onChange && onChange(newDate, Calendar); - if (!link) { this.setState({ date: newDate }); } @@ -139,7 +144,42 @@ var Calendar = (function (_Component) { var month = _moment2['default'].months(shownDate.month()); var year = shownDate.year(); var styles = this.styles; - var onlyClasses = this.props.onlyClasses; + var _props4 = this.props; + var onlyClasses = _props4.onlyClasses; + var offset = _props4.offset; + var index = _props4.index; + var calendarEnd = _props4.calendarEnd; + var pickSingleDate = _props4.pickSingleDate; + var changeYear = _props4.changeYear; + var yearRange = _props4.yearRange; + var selectYear = _props4.selectYear; + + var start = index === 0; + var end = index === calendarEnd; + + var showStart = undefined, + showEnd = undefined; + + if (pickSingleDate) { + showStart = start ? { visibility: 'visible' } : { visibility: 'hidden' }; + showEnd = end ? { visibility: 'visible' } : { visibility: 'hidden' }; + } else { + showStart = {}; + showEnd = {}; + } + + var generateYearRange = function generateYearRange() { + var yearOptions = []; + var currentYear = parseInt((0, _moment2['default'])().format('YYYY')); + for (var i = currentYear - yearRange.start; i <= currentYear + yearRange.end; i++) { + yearOptions.push(_react2['default'].createElement( + 'option', + { value: i }, + i + )); + } + return yearOptions; + }; return _react2['default'].createElement( 'div', @@ -147,7 +187,7 @@ var Calendar = (function (_Component) { _react2['default'].createElement( 'button', { - style: onlyClasses ? undefined : _extends({}, styles['MonthButton'], { float: 'left' }), + style: onlyClasses ? undefined : _extends({}, styles['MonthButton'], showStart, { float: 'left' }), className: classes.prevButton, onClick: this.changeMonth.bind(this, -1) }, _react2['default'].createElement('i', { style: onlyClasses ? undefined : _extends({}, styles['MonthArrow'], styles['MonthArrowPrev']) }) @@ -168,13 +208,17 @@ var Calendar = (function (_Component) { _react2['default'].createElement( 'span', { className: classes.year }, - year + start && pickSingleDate && selectYear ? _react2['default'].createElement( + 'select', + { onChange: changeYear, value: year }, + generateYearRange() + ) : year ) ), _react2['default'].createElement( 'button', { - style: onlyClasses ? undefined : _extends({}, styles['MonthButton'], { float: 'right' }), + style: onlyClasses ? undefined : _extends({}, styles['MonthButton'], showEnd, { float: 'right' }), className: classes.nextButton, onClick: this.changeMonth.bind(this, +1) }, _react2['default'].createElement('i', { style: onlyClasses ? undefined : _extends({}, styles['MonthArrow'], styles['MonthArrowNext']) }) @@ -208,17 +252,18 @@ var Calendar = (function (_Component) { // TODO: Split this logic into smaller chunks var styles = this.styles; - var _props4 = this.props; - var range = _props4.range; - var minDate = _props4.minDate; - var maxDate = _props4.maxDate; - var format = _props4.format; - var onlyClasses = _props4.onlyClasses; + var _props5 = this.props; + var range = _props5.range; + var minDate = _props5.minDate; + var maxDate = _props5.maxDate; + var format = _props5.format; + var onlyClasses = _props5.onlyClasses; var shownDate = this.getShownDate(); var _state = this.state; var date = _state.date; var firstDayOfWeek = _state.firstDayOfWeek; + var inputtedDate = _state.inputtedDate; var dateUnix = date.unix(); @@ -260,7 +305,7 @@ var Calendar = (function (_Component) { var dayMoment = data.dayMoment; var isPassive = data.isPassive; - var isSelected = !range && dayMoment.unix() === dateUnix; + var isSelected = !range && dayMoment.unix() === dateUnix && shownDate; var isInRange = range && checkRange(dayMoment, range); var isStartEdge = range && checkStartEdge(dayMoment, range); var isEndEdge = range && checkEndEdge(dayMoment, range); @@ -288,9 +333,9 @@ var Calendar = (function (_Component) { key: 'render', value: function render() { var styles = this.styles; - var _props5 = this.props; - var onlyClasses = _props5.onlyClasses; - var classNames = _props5.classNames; + var _props6 = this.props; + var onlyClasses = _props6.onlyClasses; + var classNames = _props6.classNames; var classes = _extends({}, _stylesJs.defaultClasses, classNames); @@ -327,7 +372,12 @@ Calendar.defaultProps = { }; Calendar.propTypes = { + index: _react.PropTypes.number, sets: _react.PropTypes.string, + yearRange: _react.PropTypes.shape({ + start: _react.PropTypes.number, + end: _react.PropTypes.number + }), range: _react.PropTypes.shape({ startDate: _react.PropTypes.object, endDate: _react.PropTypes.object diff --git a/lib/DateRange.js b/lib/DateRange.js index f891f319d..2cc4872ff 100644 --- a/lib/DateRange.js +++ b/lib/DateRange.js @@ -12,6 +12,8 @@ var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_ag function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } @@ -51,9 +53,10 @@ var DateRange = (function (_Component) { var format = props.format; var linkedCalendars = props.linkedCalendars; var theme = props.theme; + var pickSingleDate = props.pickSingleDate; var startDate = (0, _utilsParseInputJs2['default'])(props.startDate, format); - var endDate = (0, _utilsParseInputJs2['default'])(props.endDate, format); + var endDate = pickSingleDate ? (0, _utilsParseInputJs2['default'])(props.startDate, format) : (0, _utilsParseInputJs2['default'])(props.endDate, format); this.state = { range: { startDate: startDate, endDate: endDate }, @@ -89,17 +92,39 @@ var DateRange = (function (_Component) { }, { key: 'setRange', value: function setRange(range, source) { - var onChange = this.props.onChange; + var _props = this.props; + var onChange = _props.onChange; + var pickSingleDate = _props.pickSingleDate; range = this.orderRange(range); this.setState({ range: range }); - onChange && onChange(range, source); + if (pickSingleDate) { + onChange && onChange(range.startDate, source); + } else { + onChange && onChange(range, source); + } + } + }, { + key: 'changeYear', + value: function changeYear(e) { + var link = this.state.link; + + this.setState({ + link: link.clone().isoWeekYear(e.target.value) + }); } }, { key: 'handleSelect', value: function handleSelect(date, source) { + if (this.props.pickSingleDate) { + return this.setRange({ + startDate: date, + endDate: date + }, source); + } + if (date.startDate && date.endDate) { this.step = 0; return this.setRange(date, source); @@ -125,6 +150,7 @@ var DateRange = (function (_Component) { range['endDate'] = date; this.step = 0; break; + } this.setRange(range, source); @@ -162,17 +188,21 @@ var DateRange = (function (_Component) { value: function render() { var _this = this; - var _props = this.props; - var ranges = _props.ranges; - var format = _props.format; - var linkedCalendars = _props.linkedCalendars; - var style = _props.style; - var calendars = _props.calendars; - var firstDayOfWeek = _props.firstDayOfWeek; - var minDate = _props.minDate; - var maxDate = _props.maxDate; - var classNames = _props.classNames; - var onlyClasses = _props.onlyClasses; + var _props2 = this.props; + var ranges = _props2.ranges; + var format = _props2.format; + var linkedCalendars = _props2.linkedCalendars; + var style = _props2.style; + var calendars = _props2.calendars; + var firstDayOfWeek = _props2.firstDayOfWeek; + var minDate = _props2.minDate; + var maxDate = _props2.maxDate; + var classNames = _props2.classNames; + var onlyClasses = _props2.onlyClasses; + var pickSingleDate = _props2.pickSingleDate; + var showIndex = _props2.showIndex; + var yearRange = _props2.yearRange; + var selectYear = _props2.selectYear; var _state = this.state; var range = _state.range; var link = _state.link; @@ -192,13 +222,19 @@ var DateRange = (function (_Component) { onlyClasses: onlyClasses, classNames: classes }), (function () { - var _calendars = []; - for (var i = Number(calendars) - 1; i >= 0; i--) { - _calendars.push(_react2['default'].createElement(_CalendarJs2['default'], { + var _calendars = [].concat(_toConsumableArray(Array(calendars).keys())).map(function (i) { + var offset = i - showIndex; + return _react2['default'].createElement(_CalendarJs2['default'], { key: i, - offset: -i, + index: i, + offset: offset, + changeYear: _this.changeYear.bind(_this), link: linkedCalendars && link, + calendarEnd: calendars - 1, linkCB: _this.handleLinkChange.bind(_this), + pickSingleDate: pickSingleDate, + yearRange: yearRange, + selectYear: selectYear, range: range, format: format, firstDayOfWeek: firstDayOfWeek, @@ -207,8 +243,8 @@ var DateRange = (function (_Component) { maxDate: maxDate, onlyClasses: onlyClasses, classNames: classes, - onChange: _this.handleSelect.bind(_this) })); - } + onChange: _this.handleSelect.bind(_this) }); + }); return _calendars; })() ); @@ -219,15 +255,21 @@ var DateRange = (function (_Component) { })(_react.Component); DateRange.defaultProps = { + pickSingleDate: false, linkedCalendars: false, + selectYear: false, theme: {}, format: 'DD/MM/YYYY', calendars: 2, onlyClasses: false, + showIndex: 0, classNames: {} }; DateRange.propTypes = { + selectYear: _react.PropTypes.bool, + pickSingleDate: _react.PropTypes.bool, + showIndex: _react.PropTypes.number, format: _react.PropTypes.string, firstDayOfWeek: _react.PropTypes.number, calendars: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.number]), diff --git a/src/Calendar.js b/src/Calendar.js index 83c8693e2..eb33f377a 100644 --- a/src/Calendar.js +++ b/src/Calendar.js @@ -35,11 +35,14 @@ class Calendar extends Component { constructor(props, context) { super(props, context); - const { format, range, theme, offset, firstDayOfWeek } = props; - + const { format, range, theme, offset, firstDayOfWeek, index } = props; const date = parseInput(props.date, format) + const test = (range && range['endDate'] || date) + const state = { date, + index: index, + inputtedDate: props.date ? true : false, shownDate : (range && range['endDate'] || date).clone().add(offset, 'months'), firstDayOfWeek: (firstDayOfWeek || moment.localeData().firstDayOfWeek()), } @@ -55,18 +58,16 @@ class Calendar extends Component { getShownDate() { const { link, offset } = this.props; - const shownDate = (link) ? link.clone().add(offset, 'months') : this.state.shownDate; return shownDate; } handleSelect(newDate) { - const { link, onChange } = this.props; + const { link, onChange, offset } = this.props; const { date } = this.state; onChange && onChange(newDate, Calendar); - if (!link) { this.setState({ date : newDate }); } @@ -93,27 +94,52 @@ class Calendar extends Component { const month = moment.months(shownDate.month()); const year = shownDate.year(); const { styles } = this; - const { onlyClasses } = this.props; + const { onlyClasses, offset, index, calendarEnd, pickSingleDate, changeYear, yearRange, selectYear } = this.props; + const start = index === 0 + const end = index === calendarEnd + + let showStart, showEnd; + + if(pickSingleDate) { + showStart = start ? {visibility: 'visible'} : {visibility: 'hidden'} + showEnd = end ? {visibility: 'visible'} : {visibility: 'hidden'} + } else { + showStart = {} + showEnd = {} + } + + const generateYearRange = ()=>{ + const yearOptions = [] + const currentYear = parseInt(moment().format('YYYY')) + for (var i = currentYear - yearRange.start; i <= (currentYear + yearRange.end); i++) { + yearOptions.push() + } + return yearOptions + } return (
- + {month} - - {year} + + { + (start && pickSingleDate && selectYear) ? : year + } + - +
) } @@ -142,7 +168,7 @@ class Calendar extends Component { const { range, minDate, maxDate, format, onlyClasses } = this.props; const shownDate = this.getShownDate(); - const { date, firstDayOfWeek } = this.state; + const { date, firstDayOfWeek, inputtedDate } = this.state; const dateUnix = date.unix(); const monthNumber = shownDate.month(); @@ -181,7 +207,7 @@ class Calendar extends Component { const today = moment().startOf('day'); return days.map((data, index) => { const { dayMoment, isPassive } = data; - const isSelected = !range && (dayMoment.unix() === dateUnix); + const isSelected = !range && (dayMoment.unix() === dateUnix) && shownDate; const isInRange = range && checkRange(dayMoment, range); const isStartEdge = range && checkStartEdge(dayMoment, range); const isEndEdge = range && checkEndEdge(dayMoment, range); @@ -232,7 +258,12 @@ Calendar.defaultProps = { } Calendar.propTypes = { + index : PropTypes.number, sets : PropTypes.string, + yearRange : PropTypes.shape({ + start : PropTypes.number, + end : PropTypes.number, + }), range : PropTypes.shape({ startDate : PropTypes.object, endDate : PropTypes.object diff --git a/src/DateRange.js b/src/DateRange.js index c6bde59d3..fa2b37c9a 100644 --- a/src/DateRange.js +++ b/src/DateRange.js @@ -10,10 +10,10 @@ class DateRange extends Component { constructor(props, context) { super(props, context); - const { format, linkedCalendars, theme } = props; + const { format, linkedCalendars, theme, pickSingleDate } = props; const startDate = parseInput(props.startDate, format); - const endDate = parseInput(props.endDate, format); + const endDate = pickSingleDate ? parseInput(props.startDate, format) : parseInput(props.endDate, format); this.state = { range : { startDate, endDate }, @@ -42,15 +42,34 @@ class DateRange extends Component { } setRange(range, source) { - const { onChange } = this.props + const { onChange, pickSingleDate } = this.props range = this.orderRange(range); this.setState({ range }); - onChange && onChange(range, source); + if (pickSingleDate) { + onChange && onChange(range.startDate, source) + } else { + onChange && onChange(range, source); + } + } + + changeYear(e){ + const { link } = this.state; + + this.setState({ + link : link.clone().isoWeekYear(e.target.value), + }); } handleSelect(date, source) { + if (this.props.pickSingleDate) { + return this.setRange({ + startDate: date, + endDate: date, + }, source) + } + if (date.startDate && date.endDate) { this.step = 0; return this.setRange(date, source); @@ -74,6 +93,7 @@ class DateRange extends Component { range['endDate'] = date; this.step = 0; break; + } this.setRange(range, source); @@ -106,10 +126,9 @@ class DateRange extends Component { } render() { - const { ranges, format, linkedCalendars, style, calendars, firstDayOfWeek, minDate, maxDate, classNames, onlyClasses } = this.props; + const { ranges, format, linkedCalendars, style, calendars, firstDayOfWeek, minDate, maxDate, classNames, onlyClasses, pickSingleDate, showIndex, yearRange, selectYear } = this.props; const { range, link } = this.state; const { styles } = this; - const classes = { ...defaultClasses, ...classNames }; return ( @@ -126,25 +145,29 @@ class DateRange extends Component { )} {()=>{ - const _calendars = []; - for (var i = Number(calendars) - 1; i >= 0; i--) { - _calendars.push( - - ); - } + const _calendars = [...Array(calendars).keys()].map( i => { + const offset = i - showIndex + return + }) return _calendars; }()} @@ -153,15 +176,26 @@ class DateRange extends Component { } DateRange.defaultProps = { + pickSingleDate : false, linkedCalendars : false, + selectYear : false, theme : {}, + yearRange : {start: 10, end:10}, format : 'DD/MM/YYYY', calendars : 2, onlyClasses : false, + showIndex : 0, classNames : {} } DateRange.propTypes = { + selectYear : PropTypes.bool, + pickSingleDate : PropTypes.bool, + showIndex : PropTypes.number, + yearRange : PropTypes.shape({ + start : PropTypes.number, + end : PropTypes.number, + }), format : PropTypes.string, firstDayOfWeek : PropTypes.number, calendars : PropTypes.oneOfType([PropTypes.string, PropTypes.number]),