Skip to content

Commit c9bb71d

Browse files
author
Maja Wichrowska
committed
Add DateRangePicker example with presets
1 parent c9c35c9 commit c9bb71d

File tree

4 files changed

+252
-0
lines changed

4 files changed

+252
-0
lines changed

.storybook-css/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function loadStories() {
6767
require('../stories/DayPickerRangeController');
6868
require('../stories/DayPickerSingleDateController');
6969
require('../stories/DayPicker');
70+
require('../stories/PresetDateRangePicker');
7071
}
7172

7273
setAddon(infoAddon);

.storybook/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ function loadStories() {
6767
require('../stories/DayPickerRangeController');
6868
require('../stories/DayPickerSingleDateController');
6969
require('../stories/DayPicker');
70+
require('../stories/PresetDateRangePicker');
7071
}
7172

7273
setAddon(infoAddon);

examples/PresetDateRangePicker.jsx

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import momentPropTypes from 'react-moment-proptypes';
4+
import moment from 'moment';
5+
import omit from 'lodash/omit';
6+
7+
import { withStyles, withStylesPropTypes, css } from 'react-with-styles';
8+
9+
import DateRangePicker from '../src/components/DateRangePicker';
10+
11+
import { DateRangePickerPhrases } from '../src/defaultPhrases';
12+
import DateRangePickerShape from '../src/shapes/DateRangePickerShape';
13+
import { START_DATE, END_DATE, HORIZONTAL_ORIENTATION, ANCHOR_LEFT } from '../src/constants';
14+
import isSameDay from '../src/utils/isSameDay';
15+
16+
const propTypes = {
17+
...withStylesPropTypes,
18+
19+
// example props for the demo
20+
autoFocus: PropTypes.bool,
21+
autoFocusEndDate: PropTypes.bool,
22+
initialStartDate: momentPropTypes.momentObj,
23+
initialEndDate: momentPropTypes.momentObj,
24+
presets: PropTypes.arrayOf(PropTypes.shape({
25+
text: PropTypes.string,
26+
start: momentPropTypes.momentObj,
27+
end: momentPropTypes.momentObj,
28+
})),
29+
30+
...omit(DateRangePickerShape, [
31+
'startDate',
32+
'endDate',
33+
'onDatesChange',
34+
'focusedInput',
35+
'onFocusChange',
36+
]),
37+
};
38+
39+
const defaultProps = {
40+
// example props for the demo
41+
autoFocus: false,
42+
autoFocusEndDate: false,
43+
initialStartDate: null,
44+
initialEndDate: null,
45+
presets: [],
46+
47+
// input related props
48+
startDateId: START_DATE,
49+
startDatePlaceholderText: 'Start Date',
50+
endDateId: END_DATE,
51+
endDatePlaceholderText: 'End Date',
52+
disabled: false,
53+
required: false,
54+
screenReaderInputMessage: '',
55+
showClearDates: false,
56+
showDefaultInputIcon: false,
57+
customInputIcon: null,
58+
customArrowIcon: null,
59+
customCloseIcon: null,
60+
61+
// calendar presentation and interaction related props
62+
renderMonth: null,
63+
orientation: HORIZONTAL_ORIENTATION,
64+
anchorDirection: ANCHOR_LEFT,
65+
horizontalMargin: 0,
66+
withPortal: false,
67+
withFullScreenPortal: false,
68+
initialVisibleMonth: null,
69+
numberOfMonths: 2,
70+
keepOpenOnDateSelect: false,
71+
reopenPickerOnClearDates: false,
72+
isRTL: false,
73+
74+
// navigation related props
75+
navPrev: null,
76+
navNext: null,
77+
onPrevMonthClick() {},
78+
onNextMonthClick() {},
79+
onClose() {},
80+
81+
// day presentation and interaction related props
82+
renderDay: null,
83+
minimumNights: 0,
84+
enableOutsideDays: false,
85+
isDayBlocked: () => false,
86+
isOutsideRange: day => false,
87+
isDayHighlighted: () => false,
88+
89+
// internationalization
90+
displayFormat: () => moment.localeData().longDateFormat('L'),
91+
monthFormat: 'MMMM YYYY',
92+
phrases: DateRangePickerPhrases,
93+
};
94+
95+
class DateRangePickerWrapper extends React.Component {
96+
constructor(props) {
97+
super(props);
98+
99+
let focusedInput = null;
100+
if (props.autoFocus) {
101+
focusedInput = START_DATE;
102+
} else if (props.autoFocusEndDate) {
103+
focusedInput = END_DATE;
104+
}
105+
106+
this.state = {
107+
focusedInput,
108+
startDate: props.initialStartDate,
109+
endDate: props.initialEndDate,
110+
};
111+
112+
this.onDatesChange = this.onDatesChange.bind(this);
113+
this.onFocusChange = this.onFocusChange.bind(this);
114+
this.renderDatePresets = this.renderDatePresets.bind(this);
115+
}
116+
117+
onDatesChange({ startDate, endDate }) {
118+
this.setState({ startDate, endDate });
119+
}
120+
121+
onFocusChange(focusedInput) {
122+
this.setState({ focusedInput });
123+
}
124+
125+
renderDatePresets() {
126+
const { presets, styles } = this.props;
127+
const { startDate, endDate } = this.state;
128+
129+
return (
130+
<div {...css(styles.PresetDateRangePicker_panel)}>
131+
{presets.map(({ text, start, end }) => {
132+
const isSelected = isSameDay(start, startDate) && isSameDay(end, endDate);
133+
return (
134+
<button
135+
key={text}
136+
{...css(
137+
styles.PresetDateRangePicker_button,
138+
isSelected && styles.PresetDateRangePicker_button__selected,
139+
)}
140+
type="button"
141+
onClick={() => this.onDatesChange({ startDate: start, endDate: end })}
142+
>
143+
{text}
144+
</button>
145+
);
146+
})}
147+
</div>
148+
);
149+
}
150+
151+
render() {
152+
const { focusedInput, startDate, endDate } = this.state;
153+
154+
// autoFocus, autoFocusEndDate, initialStartDate and initialEndDate are helper props for the
155+
// example wrapper but are not props on the SingleDatePicker itself and
156+
// thus, have to be omitted.
157+
const props = omit(this.props, [
158+
'autoFocus',
159+
'autoFocusEndDate',
160+
'initialStartDate',
161+
'initialEndDate',
162+
'presets',
163+
]);
164+
165+
return (
166+
<div>
167+
<DateRangePicker
168+
{...props}
169+
renderCalendarInfo={this.renderDatePresets}
170+
onDatesChange={this.onDatesChange}
171+
onFocusChange={this.onFocusChange}
172+
focusedInput={focusedInput}
173+
startDate={startDate}
174+
endDate={endDate}
175+
/>
176+
</div>
177+
);
178+
}
179+
}
180+
181+
DateRangePickerWrapper.propTypes = propTypes;
182+
DateRangePickerWrapper.defaultProps = defaultProps;
183+
184+
export default withStyles(({ reactDates: { color } }) => ({
185+
PresetDateRangePicker_panel: {
186+
padding: '0 22px 11px 22px',
187+
},
188+
189+
PresetDateRangePicker_button: {
190+
position: 'relative',
191+
height: '100%',
192+
textAlign: 'center',
193+
background: 'none',
194+
border: `2px solid ${color.core.primary}`,
195+
color: color.core.primary,
196+
padding: '4px 12px',
197+
marginRight: 8,
198+
font: 'inherit',
199+
fontWeight: 700,
200+
lineHeight: 'normal',
201+
overflow: 'visible',
202+
boxSizing: 'border-box',
203+
cursor: 'pointer',
204+
205+
':active': {
206+
outline: 0,
207+
},
208+
},
209+
210+
PresetDateRangePicker_button__selected: {
211+
color: color.core.white,
212+
background: color.core.primary,
213+
},
214+
}))(DateRangePickerWrapper);

stories/PresetDateRangePicker.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react';
2+
import { storiesOf } from '@storybook/react';
3+
import moment from 'moment';
4+
5+
import PresetDateRangePicker from '../examples/PresetDateRangePicker';
6+
7+
const today = moment();
8+
const tomorrow = moment().add(1, 'day');
9+
const presets = [{
10+
text: 'Today',
11+
start: today,
12+
end: today,
13+
},
14+
{
15+
text: 'Tomorrow',
16+
start: tomorrow,
17+
end: tomorrow,
18+
},
19+
{
20+
text: 'Next Week',
21+
start: today,
22+
end: moment().add(1, 'week'),
23+
},
24+
{
25+
text: 'Next Month',
26+
start: today,
27+
end: moment().add(1, 'month'),
28+
}];
29+
30+
storiesOf('PresetDatePicker', module)
31+
.addWithInfo('default', () => (
32+
<PresetDateRangePicker
33+
presets={presets}
34+
autoFocus
35+
/>
36+
));

0 commit comments

Comments
 (0)