Okami
Primitives react component for calendar
Install / Use
/learn @Kilix/OkamiREADME
[![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] [![version][version-badge]][package] [![MIT License][license-badge]][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-fnsformat
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: <div ref={props.innerRef} />. 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-fnsformat
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: <div ref={props.innerRef} />. By default, it will use the react default ref key.
Monthly Calendar
Render a month.
Props
| property | type | default | description
