Helps to build your own calendar by using prepared components and api to control them.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.storybook
src
.gitignore
.npmignore
.npmrc
.travis.yml
LICENSE
README.md
package.json
tsconfig.json
tslint.json
webpack.config.js

README.md

react-flex-picker Build Status

For online demo go to https://unbugx.github.io/react-flex-picker/

To run demo on your own computer:

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}>&rarr;</div>
        <div className='left' onClick={handlePrevUnit}>&larr;</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 customStyles from './calendar.styl';

<PickerProvider
  onDatesChange={() => {}}
  styles={customStyles}
>
  <PickerConsumer>
    {({handlePrevUnit, handleNextUnit}) => (
      <div className='calendar'>
        <div className='right' onClick={handleNextUnit}>&rarr;</div>
        <div className='left' onClick={handlePrevUnit}>&larr;</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}>&rarr;</div>
              <div className={styles.left} onClick={handlePrevUnit}>&larr;</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...