okami

0.2.5 • Public • Published

Okami

Primitives React Components to build a Calendar

Build Status Code Coverage version MIT License

Project status

Okami is used in production, we consider evolving its API, but it works as expected!

Introduction

It's a set of Primitives React Components to build a Calendar. Handle the logic so you can focus on UI/UX. Similar to downshift or selectless.

We use composition to construct the calendar, which simply means:

  • A monthly calendar is composed of weekly calendar.
  • A weekly calendar is composed of daily calendar.

This allow to have a lot fo flexibility without repeating the logic and avoid complexity.

We strongly recommend to use okami with date-fns.

Install

yarn add okami npm install --save okami

Basic Usage

For more examples, look at the storybook :)

 
import React from 'react'
import frLocale from 'date-fns/locale/fr'
import { Calendar, DailyCalendar, Navigation, HoursLabels } from 'okami'
 
import data from './stories/data'
 
const Container = props =>
  <div style={{ display: 'flex', alignItems: 'stretch', justifyContent: 'center'}} {...props} />
 
const CalendarContainer = props =>
  <div style={{ display: 'flex', alignItems: 'stretch', justifyContent: 'flex-start', width: '100%' }} {...props} />
 
export default props => (
  <Calendar
    data={data}
    startingDay="monday"
    dateFormat="ddd DD/MM"
    hourFormat="HH"
    startHour="PT3H"
    endHour="PT22H"
    locale={frLocale}
  >
    <DailyCalendar showNow {...props}>
      {({calendar, dayEvents, rowHeight}) => (
        <div style={{display: 'flex', flexDirection:'column'}}>
          <div style={{display:'flex'}}>
            <Navigation dateFormat="ddd DD MMMM">
              {({next, prev, today, currentDate}) => (
                <div style={{display:'flex'}}>
                  <button onClick={today}>Today</button>
                  <button onClick={prev}>Prev day</button>
                  <button onClick={next}>Next day</button>
                  <span>{currentDate}</span>
                </div>
              )}
            </Navigation>
          </div>
          <Container>
            <div style={{paddingTop: rowHeight * (dayEvents.length + 1)}}>
              <HoursLabels renderChild={props => <span style={{height: rowHeight}} {...props} />} />
            </div>
            <CalendarContainer style={{flexDirection: 'column'}}>
              {dayEvents.map(props => <Event {...props} />)}
              {calendar.events.map(props => <Event {...props} />)}
            </CalendarContainer>
          </Container>
        </div>
      )}
    </DailyCalendar>
  </Calendar>
)
 

Documentation

Props Calendar

property type required default description
data array yes - List of events
startHour string no PT0H Hour to start the calendar
endHour string no PT24H Hour to end the calendar
dateFormat string no MM/DD/YYYY Format of the date string
hourFormat string no HH:mm Format of the hour string
startingDay string no sunday Starting day of the week
locale object no en Local from date-fns
rowHeight number no 30 Height of a row

To define property that will be use as duration like startHours or endHour. We use ISO-8601 format for durations.

Every prop passed to Calendar can be overwritten as the sub component level.

  <Calendar
    data={data}
    startingDay="monday"
    dateFormat="ddd DD/MM"
    hourFormat="HH"
    startHour="PT3H"
    endHour="PT22H"
  >
    <MonthlyCalendar>{...}</MonthlyCalendar>
    <DailyCalendar dateFormat="DD-MM-YYYY">{...}</DailyCalendar>
  </Calendar>

This will use the dateFormat from <Calendar> in <MonthlyCalendar> but <DailyCalendar> will use his custom dateFormat when it renders.


Daily Calendar

Render a day.

Props

property type default description
start Date new Date() Day to show
showNow boolean false Send props to show the time of day

Child Callback Function

property type description
calendar Object events, label and date of the day
start Date date of the day
showNowProps Object if showNow is true, props to the showNow container (postion)
hours Array Array of formatted string for hours labels
rowHeight Number Height of the row
dayEvents Array Array of the events that last more than a day of the all day

calendar

property type
date Date
events Array

dayEvents

property type
key event.id
event Object
style Object

The style object is passed only if the getColumnProp is called and we have a ref available.

methods description
nextDay Go to next day
prevDay Go to previous day
gotoToday Go to today
dateLabel get the date formatted
getColumnProps get the props for the container of the events

dateLabel

Allow you to render the current day with a special format.

  • dateFormat: use the convention from date-fns format

getColumnProps

Allow to get the ref to your column element for calculation of the events position.

  • refKey: if you're rendering a composite component, that component will need to accept a prop which it forwards to the root DOM element. Commonly, folks call this innerRef. So you'd call: getRootProps({refKey: 'innerRef'}) and your composite component would forward like:
    . By default, it will use the react default ref key

Weekly Calendar

Render a week.

Props

property type default description
start Date new Date() Day of the week to show
showNow boolean false Send props to show the time of day

Child Callback Function

property type description
calendar Array list of day for the week
end Date end of the week
start Date start of the week
showNowProps Object if showNow is true, props to the showNow container (postion)
hours Array Array of formatted string for hours labels
rowHeight Number Height of the row
weekEvents Array Array of the events that last more than a day of the all week

weekEvents

property type
key event.id
event Object
style Object

The style object is passed only if the getContainerProps is called and we have a ref available.

methods description
nextWeek Go to next week
prevWeek Go to previous week
gotoToday Go to today
dateLabel get the date formatted
getContainerProps get the props for the container of the events

dateLabel

Allow you to render the current week with a special format.

  • dateFormat: use the convention from date-fns format

getContainerProps

Allow to get the ref to your column element for calculation of the events position.

  • refKey: if you're rendering a composite component, that component will need to accept a prop which it forwards to the root DOM element. Commonly, folks call this innerRef. So you'd call: getRootProps({refKey: 'innerRef'}) and your composite component would forward like:
    . By default, it will use the react default ref key.

Monthly Calendar

Render a month.

Props

property type default description
start Date new Date() Date of the curent month

Child Callback Function

property type description
calendar Array List of first day of the week for the month
end Date end of the month
start Date start of the month
weeks Array List of the first day of week for the month
rowHeight Number Height of the row
methods description
nextMonth Go to next month
prevMonth Go to previous month
gotoToday Go to today
dateLabel get the date formatted

dateLabel

Allow you to render the current month with a special format.

  • dateFormat: use the convention from date-fns format

Navigation

render the navigation for the calendar and the current label. The navigation and label are based on the type. If you use this in a DailyCalendar, next() will jump to the next day but if you use it in MonthlyCalendar, it will jump to the next month. You also get access to the function to toggle weekends on the calendar.

If you force showWeekend on a sub component, don't forget to update manually this props.

Props

property type description
dateFormat string format of the date

Child Callback Function

property type description
type string Type of calendar ('monthly', 'weekly', 'daily')
currentDate string Formatted date based on type
methods description
next Go to next based on type
prev Go to previous based on type
today Go to today
toggleWeekend show/hide weekend on calendar

toggleWeekend

Let you toggle the weekend in the calendar. If you don't pass a pamarater, it will toggle the prop. If you pass a boolean, it will force the value.

 
const showWeekend = true
 
toggleWeekend() // showWeekend = false
toggleWeekend(true) // showWeekend = true
toggleWeekend(true) // showWeekend = true
toggleWeekend(false) // showWeekend = false
[...]
 

DaysLabels / HoursLabels

render the days/hours labels for the calendar. You have 3 options to render those components:

  • Child Callback function : allow full control
  • renderChild props: pass a component that receive pre formatted props
  • The default render that let you style the div container.

Props

property type
renderChild Element|Component

Child Callback Function

DaysLabels

property type description
weeks array Array of the formatted day labels

HoursLabels

property type description
hours array Array of the formatted hour labels
  <HoursLabels>
    { hours => hours.map(h => <span>{h}</span>} }
  </HoursLabels>

renderChild prop

props from the HoursLabels/DaysLabels are passed down to the container and the labels are rendered with the component from renderChild.

  <HoursLabels renderChild={props => <span {...props} />} />

The default render function

props from the HoursLabels/DaysLabels are passed down to the container.

<HoursLabels />

This is the render function used :

<div {...props}>
  {formattedDays.map((h, idx) => (
    <div key={`day_label_${idx}`} style={{height: rowHeight}}>
      {h}
    </div>
  ))}
</div>

Data structure

data is an array of objects, the object requires a few properties :

property type description
id ID Identifier of the event
title string Title of the event
allDay boolean | Date Determine the type of event
start Date Beggining of the event
end Date End of the event

allDay has 3 states :

  • true, the event is on multiple days
  • false, the event is no longer than a day
  • Date, the event last all day

if allDay is a boolean, you need to provide a start and end properties. If you want to create an event for the all day, you just put the date in allDay.

 
// Event of 2 hours:
{
  id: 0,
  title: 'Diner',
  allDay: false,
  start : 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)',
  end: 'Wed Sep 06 2017 14:07:52 GMT+0200 (CEST)'
}
 
// Event of all day:
{
  id: 0,
  title: 'Diner',
  allDay: 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)'
}
 
// Event of 2 days:
{
  id: 0,
  title: 'Diner',
  allDay: true,
  start : 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)',
  end: 'Wed Sep 08 2017 14:07:52 GMT+0200 (CEST)'
}
 

LICENSE

MIT

Package Sidebar

Install

npm i okami

Weekly Downloads

52

Version

0.2.5

License

MIT

Unpacked Size

127 kB

Total Files

6

Last publish

Collaborators

  • kilix_user
  • alefevre19
  • shegunmb
  • wcastand