npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

okami

v0.2.5

Published

<h1 align="center"> Okami <br> </h1> <p align="center" style="font-size: 1.2rem;">Primitives React Components to build a Calendar</p>

Downloads

444

Readme

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