1.0.7 • Published 5 years ago

react-flex-picker v1.0.7

Weekly downloads
1
License
MIT
Repository
github
Last release
5 years ago

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:

nametypedescription
initialEndDateMomentInitial end date in range for range picker. Ignore for single picker.
initialStartDateMomentInitial start date in range for range picker. Also it is used as initial date for single picker.
isSinglebooleanSwitch to single picker.
isWeeksSelectionbooleanSwitch to weeks selection.
localestringCurrent locale. Default value: en
maxDateMomentMaximum available date for choosing. All dates after maximum date will be disabled.
maxDaysCountnumberMaximum number of days in range.
minDateMomentMinimum available date for choosing. All dates before minimum date will be disabled.
minDaysCountnumberMinimum number of days in range.
onChangeWidthfunctionExecutes when picker width was changed. Sometimes this info can be useful when you build your own calendar.
onDatesChangefunction(startDate: Moment, endDate: Moment)Executes when new date is picked up.
onTitleClickfunctionExecutes when calendar title is clicked.
pickerTypestringPickerProvider has to know what type of picker it controls. Available values are day, month. Default value: day
showOutsideDaysbooleanFirst and last week of month will be filled with days from nearby months.
stylesobjectObject with class names to override current css styles.
unitCountnumberNumber 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 styles 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...