react-flex-picker
v1.0.7
Published
Helps to build your own calendar by using prepared components and api to control them
Downloads
26
Maintainers
Readme
react-flex-picker
For online demo go to https://unbugx.github.io/react-flex-picker/
To run demo on your own computer:
- Clone this repository
npm install
npm run storybook
- Open http://localhost:9002/
Getting Started
npm install --save react-flex-picker
Add the following import to your application if you use Webpack with CSS loader:
import 'react-flex-picker/dist/react-flex-picker.css';
Make own datepickers
Using a few simple components you can build your own calendar with any logic you want. Just import these components:
import {PickerProvider, PickerConsumer, DayPickerController, MonthPickerController} from 'react-flex-picker';
PickerProvider
This picker based on React Context Api. It creates provider that keeps all business logic and all data to control calendar. PickerProvider has following list of properties:
|name|type|description|
|---|---|---|
|initialEndDate|Moment|Initial end date in range for range picker. Ignore for single picker.|
|initialStartDate|Moment|Initial start date in range for range picker. Also it is used as initial date for single picker.|
|isSingle|boolean|Switch to single picker.|
|isWeeksSelection|boolean|Switch to weeks selection.|
|locale|string|Current locale. Default value: en
|
|maxDate|Moment|Maximum available date for choosing. All dates after maximum date will be disabled.|
|maxDaysCount|number|Maximum number of days in range.|
|minDate|Moment|Minimum available date for choosing. All dates before minimum date will be disabled.|
|minDaysCount|number|Minimum number of days in range.|
|onChangeWidth|function|Executes when picker width was changed. Sometimes this info can be useful when you build your own calendar.|
|onDatesChange|function(startDate: Moment, endDate: Moment)|Executes when new date is picked up.|
|onTitleClick|function|Executes when calendar title is clicked.|
|pickerType|string|PickerProvider has to know what type of picker it controls. Available values are day
, month
. Default value: day
|
|showOutsideDays|boolean|First and last week of month will be filled with days from nearby months.|
|styles|object|Object with class names to override current css styles.|
|unitCount|number|Number of months for DayPickerController and number of years for MonthPickerController visible at a time. Default value: 1
|
PickerConsumer
Works as common consumer in context api.
It takes function as child that has one arguments with set of useful properties.
The most useful properties are handlePrevUnit
and handleNextUnit
to switch months or years.
import * as React from 'react';
import {PickerProvider, PickerConsumer, DayPickerController} from 'react-flex-picker';
import * as moment from 'moment';
<PickerProvider
initialStartDate={moment().add(-7, 'day')}
onDatesChange={(startDate) => {console.log(startDate)}}
isSingle
>
<PickerConsumer>
{({handlePrevUnit, handleNextUnit}) => (
<div className='calendar'}>
<div className='right' onClick={handleNextUnit}>→</div>
<div className='left' onClick={handlePrevUnit}>←</div>
<DayPickerController />
</div>
)}
</PickerConsumer>
</PickerProvider>
DayPickerController and MonthPickerController
Widgets of day picker and month picker accordingly.
Overriding styles
Here it's supposed you use webpack and css-loader. Css-loader allows you import styles as object with classes in keys:
import * as styles from '../styles.styl';
console.log(styles);
It will print out object like this:
{
day: "customCalendarStyles___day"
dayClickable: "customCalendarStyles___dayClickable"
dayFirstSelected: "customCalendarStyles___dayFirstSelected"
dayHovered: "customCalendarStyles___dayHovered"
}
Where key
is class name in styles.styl
file and value is dynamic class name generated by css-loader that will be inserted in resulting html.
To override existing styles just pass styles
property to PickerProvider. Look at example below:
// calendar.styl
.wrapper {
background: #29323f;
overflow: hidden;
display: inline-block;
user-select: none;
font-family: 'Courier', sans-serif;
> div {
white-space: nowrap;
}
}
.month {
margin: 0 10px;
width: 280px;
display: inline-block;
vertical-align: top;
white-space: normal;
.day {
cursor: pointer;
display: inline-block;
text-align: center;
width: 36px;
height: 36px;
line-height: 36px;
border: 2px solid #29323f;
color: #fff;
border-radius: 50%;
}
.headerMonth {
font-weight: bold;
height: 30px;
line-height: 30px;
text-align: center;
display: inline-block;
width: 100%;
cursor: default;
color: #fcee6d;
}
.headerWeekDays {
border-bottom: 1px grey solid;
span {
display: inline-block;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: default;
color: #999;
}
}
.dayClickable:hover {
border-color: #e7d84f;
}
.dayFirstSelected, .dayLastSelected {
border-color: #e7d84f;
background: #e7d84f !important;
color: #29323f;
font-weight: bold;
}
.daySelected, .dayHovered {
border-color: #e7d84f;
background: #29323f;
}
}
import * as React from 'react';
import {PickerProvider, PickerConsumer, DayPickerController} from 'react-flex-picker';
import * as moment from 'moment';
import * as styles from './calendar.styl';
<PickerProvider
onDatesChange={() => {}}
styles={customStyles}
>
<PickerConsumer>
{({handlePrevUnit, handleNextUnit}) => (
<div className='calendar'>
<div className='right' onClick={handleNextUnit}>→</div>
<div className='left' onClick={handlePrevUnit}>←</div>
<DayPickerController />
</div>
)}
</PickerConsumer>
</PickerProvider>
Below list of all available class that can be overridden:
wrapper
, transition
, day
, dayDisabled
, dayOff
, daySelected
,
dayFirstSelected
, dayLastSelected
, dayClickable
, dayHovered
,
month
, headerMonthWrapper
, headerMonth
, headerClickable
,
headerWeekDays
, daysWeek
, year
, headerYear
.
Examples
For more examples go to https://unbugx.github.io/react-flex-picker/ and source code of storybook examples https://github.com/unbugx/react-flex-picker/tree/master/src/stories
Below a few more interested examples.
Date presets and Apply button
import * as React from 'react';
import {PickerProvider, PickerConsumer, DayPickerController} from 'react-flex-picker';
import * as moment from 'moment';
import * as styles from './styles.styl'; // here is should be your own file with css
const today = moment();
const yesterday = moment().add(-1, 'day');
const nextMonthStart = moment().add(1, 'month').startOf('month');
const nextMonthEnd = moment().add(1, 'month').endOf('month');
class CalendarWithPresets extends React.Component {
constructor(props) {
super(props);
this.state = {
initialStartDate: moment().add(-7, 'day'),
initialEndDate: moment(),
selectedStartDate: moment().add(-7, 'day'),
selectedEndDate: moment(),
};
this.handlePreset = this.handlePreset.bind(this);
this.handleDatesChange = this.handleDatesChange.bind(this);
this.handleApply = this.handleApply.bind(this);
}
handlePreset(newStartDate, newEndDate) {
this.setState({
initialStartDate: newStartDate,
initialEndDate: newEndDate,
selectedStartDate: newStartDate,
selectedEndDate: newEndDate,
});
}
handleDatesChange(selectedStartDate, selectedEndDate) {
this.setState({selectedStartDate, selectedEndDate});
}
handleApply() {
if (this.state.selectedStartDate && this.state.selectedEndDate) {
// you can execute any callback here to pass selected data and hide calendar
console.log(this.state.selectedStartDate.format('DD.MM.YYYY'), this.state.selectedEndDate.format('DD.MM.YYYY'));
}
}
render() {
return (
<PickerProvider
onDatesChange={this.handleDatesChange}
unitCount={3}
showOutsideDays
initialStartDate={this.state.initialStartDate}
initialEndDate={this.state.initialEndDate}
>
<PickerConsumer>
{({handlePrevUnit, handleNextUnit}) => (
<div className={styles.calendar}>
<div className={styles.right} onClick={handleNextUnit}>→</div>
<div className={styles.left} onClick={handlePrevUnit}>←</div>
<DayPickerController />
<div>
<button
onClick={() => this.handlePreset(today, today)}
>
Today
</button>
<button
onClick={() => this.handlePreset(yesterday, yesterday)}
>
Yesterday
</button>
<button
onClick={() => this.handlePreset(nextMonthStart, nextMonthEnd)}
>
Next month
</button>
<button onClick={this.handleApply}>Apply</button>
</div>
</div>
)}
</PickerConsumer>
</PickerProvider>
);
}
}
More examples are coming soon...