Skip to content

Commit

Permalink
Merge pull request react-toolbox#116 from react-toolbox/datepicker
Browse files Browse the repository at this point in the history
Datepicker
  • Loading branch information
soyjavi committed Nov 16, 2015
2 parents e285625 + 0e54523 commit 73fb8f3
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 55 deletions.
4 changes: 2 additions & 2 deletions components/date_picker/_config.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ $datepicker-primary-color: unquote("rgb(#{$datepicker-primary})") !default;
$datepicker-primary-hover-color: unquote("rgba(#{$datepicker-primary}, 0.20)") !default;
$datepicker-primary-contrast-color: unquote("rgb(#{$datepicker-primary-contrast})") !default;
$datepicker-primary-dark-color: unquote("rgb(#{$datepicker-primary-dark})") !default;
$datepicker-dialog-width: 30 * $unit;
$datepicker-dialog-width: 33 * $unit;
$datepicker-inactive-opacity: .6;
$datepicker-weekday-line-height: 2 * $unit;
$datepicker-weekday-font-size: $font-size-small;
$datepicker-month-font-size: $font-size-big;
$datepicker-day-font-size: 5 * $unit;
$datepicker-day-line-height: 4 * $unit;
$datepicker-year-font-size: 1.8 * $unit;
$datepicker-year-font-size: $font-size-small;
1 change: 1 addition & 0 deletions components/date_picker/calendar/_config.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ $calendar-arrows-font-size: 2 * $unit;
$calendar-arrows-ripple-duration: 450ms;
$calendar-year-font-size: 2.4;
$calendar-day-font-size: 1.3 * $unit;
$calendar-day-disable-opacity: 0.25;
$calendar-row-height: 3 * $unit;
$calendar-day-padding: .2 * $unit;
$calendar-total-height: $calendar-row-height * 8 + $calendar-day-padding * 12;
5 changes: 4 additions & 1 deletion components/date_picker/calendar/day.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import style from './style';
class Day extends React.Component {
static propTypes = {
day: React.PropTypes.number,
disabled: React.PropTypes.bool,
onClick: React.PropTypes.func,
selectedDate: React.PropTypes.object,
viewDate: React.PropTypes.object
Expand All @@ -26,7 +27,9 @@ class Day extends React.Component {
}

render () {
const className = this.isSelected() ? `${style.day} ${style.active}` : style.day;
let className = this.isSelected() ? `${style.day} ${style.active}` : style.day;
if (this.props.disabled) className += ` ${style.disabled}`;

return (
<div className={className} style={this.dayStyle()}>
<span onClick={this.props.onClick}>
Expand Down
4 changes: 4 additions & 0 deletions components/date_picker/calendar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import style from './style';
class Calendar extends React.Component {
static propTypes = {
display: React.PropTypes.oneOf(['months', 'years']),
maxDate: React.PropTypes.object,
minDate: React.PropTypes.object,
onChange: React.PropTypes.func,
selectedDate: React.PropTypes.object,
viewDate: React.PropTypes.object
Expand Down Expand Up @@ -98,6 +100,8 @@ class Calendar extends React.Component {
<CSSTransitionGroup transitionName={animation} transitionEnterTimeout={350} transitionLeaveTimeout={350}>
<Month
key={this.state.viewDate.getMonth()}
maxDate={this.props.maxDate}
minDate={this.props.minDate}
viewDate={this.state.viewDate}
selectedDate={this.props.selectedDate}
onDayClick={this.handleDayClick} />
Expand Down
8 changes: 7 additions & 1 deletion components/date_picker/calendar/month.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import style from './style';

class Month extends React.Component {
static propTypes = {
maxDate: React.PropTypes.object,
minDate: React.PropTypes.object,
onDayClick: React.PropTypes.func,
selectedDate: React.PropTypes.object,
viewDate: React.PropTypes.object
Expand All @@ -22,11 +24,15 @@ class Month extends React.Component {

renderDays () {
return utils.range(1, utils.time.getDaysInMonth(this.props.viewDate) + 1).map(i => {
const date = new Date(this.props.viewDate.getFullYear(), this.props.viewDate.getMonth(), i);
const disabled = utils.time.dateOutOfRange(date, this.props.minDate, this.props.maxDate);

return (
<Day
key={i}
day={i}
onClick={this.handleDayClick.bind(this, i)}
disabled={disabled}
onClick={!disabled ? this.handleDayClick.bind(this, i) : null}
selectedDate={this.props.selectedDate}
viewDate={this.props.viewDate}
/>
Expand Down
15 changes: 9 additions & 6 deletions components/date_picker/calendar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,19 @@
.week {
display: flex;
height: $calendar-row-height;
flex-wrap: wrap;
font-size: $calendar-day-font-size;
line-height: $calendar-row-height;
opacity: .5;

flex-wrap: wrap;
> span {
flex: 0 0 (100% / 7);
}
}

.days {
display: flex;
font-size: $calendar-day-font-size;

flex-wrap: wrap;
font-size: $calendar-day-font-size;
}

.day {
Expand All @@ -75,17 +73,22 @@
width: $calendar-row-height;
height: $calendar-row-height;
line-height: $calendar-row-height;
cursor: pointer;
border-radius: 50%;
}
&:hover:not(.active) > span {
&:hover:not(.active):not(.disabled) > span {
color: $calendar-primary-contrast-color;
background: $calendar-primary-hover-color;
}
&.active > span {
color: $calendar-primary-contrast-color;
background: $calendar-primary-color;
}
&:hover:not(.disabled) > span {
cursor: pointer;
}
&.disabled {
opacity: $calendar-day-disable-opacity;
}
}

.month {
Expand Down
24 changes: 14 additions & 10 deletions components/date_picker/dialog.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import style from './style';
import time from '../utils/time';
import Calendar from './calendar';
import Dialog from '../dialog';
import style from './style';
import time from '../utils/time';

class CalendarDialog extends React.Component {
static propTypes = {
active: React.PropTypes.bool,
maxDate: React.PropTypes.object,
minDate: React.PropTypes.object,
onDismiss: React.PropTypes.func,
onSelect: React.PropTypes.func,
value: React.PropTypes.object
Expand All @@ -23,7 +25,11 @@ class CalendarDialog extends React.Component {
};

handleCalendarChange = (value) => {
this.setState({date: value, display: 'months'});
const state = {display: 'months', date: value};
if (time.dateOutOfRange(value, this.props.minDate, this.props.maxDate)) {
state.date = this.props.maxDate || this.props.minDate;
}
this.setState(state);
};

handleSelect = () => {
Expand All @@ -46,21 +52,19 @@ class CalendarDialog extends React.Component {
return (
<Dialog active={this.props.active} type="custom" className={style.dialog} actions={this.actions}>
<header className={headerClassName}>
<span className={style.weekday}>
{time.getFullDayOfWeek(this.state.date.getDay())}
</span>
<div onClick={this.handleSwitchDisplay.bind(this, 'months')}>
<span className={style.month}>{time.getShortMonth(this.state.date)}</span>
<span className={style.day}>{this.state.date.getDate()}</span>
</div>
<span className={style.year} onClick={this.handleSwitchDisplay.bind(this, 'years')}>
{this.state.date.getFullYear()}
</span>
<h3 className={style.date} onClick={this.handleSwitchDisplay.bind(this, 'months')}>
{time.getShortDayOfWeek(this.state.date.getDay())}, {time.getShortMonth(this.state.date)} {this.state.date.getDate()}
</h3>
</header>

<div className={style.wrapper}>
<Calendar
display={this.state.display}
maxDate={this.props.maxDate}
minDate={this.props.minDate}
onChange={this.handleCalendarChange}
selectedDate={this.state.date} />
</div>
Expand Down
9 changes: 7 additions & 2 deletions components/date_picker/index.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import CalendarDialog from './dialog';
import Input from '../input';
import events from '../utils/events';
import time from '../utils/time';
import Input from '../input';
import style from './style';
import time from '../utils/time';

class DatePicker extends React.Component {
static propTypes = {
maxDate: React.PropTypes.object,
minDate: React.PropTypes.object,
onChange: React.PropTypes.func,
value: React.PropTypes.object
};
Expand All @@ -32,6 +34,7 @@ class DatePicker extends React.Component {
render () {
const { value } = this.props;
const date = value ? `${value.getDate()} ${time.getFullMonth(value)} ${value.getFullYear()}` : null;

return (
<div data-toolbox='date-picker'>
<Input
Expand All @@ -44,6 +47,8 @@ class DatePicker extends React.Component {
/>
<CalendarDialog
active={this.state.active}
maxDate={this.props.maxDate}
minDate={this.props.minDate}
onDismiss={this.handleDismiss}
onSelect={this.handleSelect}
value={this.props.value}
Expand Down
7 changes: 5 additions & 2 deletions components/date_picker/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ A [dialog](https://www.google.com/design/spec/components/pickers.html#pickers-da
```jsx
import DatePicker from 'react-toolbox/lib/date_picker';

const datetime = new Date(1995, 11, 17);
const datetime = new Date(2015, 10, 16);
const min_datetime = new Date(new Date(datetime).setDate(8));
datetime.setHours(17);
datetime.setMinutes(28);

Expand All @@ -25,7 +26,7 @@ class DatePickerTest extends React.Component {
return (
<section>
<DatePicker value={this.state.date1} onChange={this.handleChange.bind(this, 'date1')} />
<DatePicker value={this.state.date2} onChange={this.handleChange.bind(this, 'date2')} />
<DatePicker minDate={min_datetime} value={this.state.date2} onChange={this.handleChange.bind(this, 'date2')} />
</section>
);
}
Expand All @@ -36,5 +37,7 @@ class DatePickerTest extends React.Component {

| Name | Type | Default | Description|
|:-----|:-----|:-----|:-----|
| `maxDate` | `Date` | | Date object with the maximum selectable date. |
| `minDate` | `Date` | | Date object with the minimum selectable date. |
| `onChange` | `Function` | | Callback called when the picker value is changed.|
| `value` | `Date` | | Date object with the currently selected date. |
40 changes: 13 additions & 27 deletions components/date_picker/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,36 @@
}

.header {
padding-bottom: $unit;
padding: 1.6 * $unit 2 * $unit;
color: $datepicker-primary-contrast-color;
text-align: center;
background-color: $datepicker-primary-color;
}

.weekday {
display: block;
width: 100%;
font-size: $datepicker-weekday-font-size;
line-height: $datepicker-weekday-line-height;
background-color: $datepicker-primary-dark-color;
}

.month {
display: block;
padding: $unit;
font-size: $datepicker-month-font-size;
text-transform: uppercase;
cursor: pointer;
}

.day {
display: block;
font-size: $datepicker-day-font-size;
line-height: $datepicker-day-line-height;
cursor: pointer;;
}

.year {
display: inline-block;
margin-top: $unit;
font-size: $datepicker-year-font-size;
cursor: pointer;
transition: opacity, font-size $animation-duration $animation-curve-default;
}

.date {
display: block;
font-weight: $font-weight-semi-bold;
text-transform: capitalize;
transition: opacity $animation-duration $animation-curve-default;
}

.wrapper {
padding: $unit .5 * $unit 0;
}

.display-years {
.day, .month {
.date {
opacity: $datepicker-inactive-opacity;
}
.year {
font-size: $font-size-normal;
}
}

.display-months {
Expand Down
4 changes: 4 additions & 0 deletions components/utils/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ module.exports = {
if (hours.length < 2) hours = '0' + hours;
if (mins.length < 2) mins = '0' + mins;
return hours + ':' + mins;
},

dateOutOfRange (date, minDate, maxDate) {
return ((minDate && !(date >= minDate)) || (maxDate && !(date <= maxDate)));
}

};
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const datetime = new Date(1995, 11, 17);
const datetime = new Date(2015, 10, 16);
const min_datetime = new Date(new Date(datetime).setDate(8));
const max_datetime = new Date(new Date(datetime).setDate(24));
datetime.setHours(17);
datetime.setMinutes(28);

Expand All @@ -17,7 +19,12 @@ class DatePickerTest extends React.Component {
return (
<section>
<DatePicker value={this.state.date1} onChange={this.handleChange.bind(this, 'date1')} />
<DatePicker value={this.state.date2} onChange={this.handleChange.bind(this, 'date2')} />
<DatePicker
maxDate={max_datetime}
minDate={min_datetime}
value={this.state.date2}
onChange={this.handleChange.bind(this, 'date2')}
/>
</section>
);
}
Expand Down
12 changes: 10 additions & 2 deletions spec/components/pickers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import React from 'react';
import DatePicker from '../../components/date_picker';
import TimePicker from '../../components/time_picker';

const datetime = new Date(1995, 11, 17);

const datetime = new Date(2015, 10, 16);
const min_datetime = new Date(new Date(datetime).setDate(8));
const max_datetime = new Date(new Date(datetime).setDate(24));
datetime.setHours(17);
datetime.setMinutes(28);

Expand All @@ -25,7 +28,12 @@ class PickersTest extends React.Component {
<p>Date pickers and time pickers with Material flavour.</p>

<DatePicker value={this.state.date1} onChange={this.handleChange.bind(this, 'date1')} />
<DatePicker value={this.state.date2} onChange={this.handleChange.bind(this, 'date2')} />
<DatePicker
maxDate={max_datetime}
minDate={min_datetime}
value={this.state.date2}
onChange={this.handleChange.bind(this, 'date2')}
/>

<TimePicker value={this.state.time1} onChange={this.handleChange.bind(this, 'time1')} />
<TimePicker value={this.state.time2} format='ampm' onChange={this.handleChange.bind(this, 'time2')} />
Expand Down

0 comments on commit 73fb8f3

Please sign in to comment.