{"id":22642439,"url":"https://github.com/kilix/okami","last_synced_at":"2026-02-16T20:12:46.368Z","repository":{"id":57313986,"uuid":"100718918","full_name":"Kilix/okami","owner":"Kilix","description":"Primitives react component for calendar","archived":false,"fork":false,"pushed_at":"2018-09-19T07:51:42.000Z","size":2461,"stargazers_count":19,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T03:39:22.808Z","etag":null,"topics":["calendar","composable","primitives","react"],"latest_commit_sha":null,"homepage":"https://okami-website-jaltwitsba.now.sh/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kilix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-18T14:16:23.000Z","updated_at":"2019-07-09T21:19:48.000Z","dependencies_parsed_at":"2022-09-20T23:21:38.978Z","dependency_job_id":null,"html_url":"https://github.com/Kilix/okami","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kilix%2Fokami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kilix%2Fokami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kilix%2Fokami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kilix%2Fokami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kilix","download_url":"https://codeload.github.com/Kilix/okami/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248493303,"owners_count":21113229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendar","composable","primitives","react"],"created_at":"2024-12-09T05:06:50.503Z","updated_at":"2026-02-16T20:12:46.269Z","avatar_url":"https://github.com/Kilix.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  Okami\n  \u003cbr\u003e\n\u003c/h1\u003e\n\u003cp align=\"center\" style=\"font-size: 1.2rem;\"\u003ePrimitives React Components to build a Calendar\u003c/p\u003e\n\n[![Build Status][build-badge]][build]\n[![Code Coverage][coverage-badge]][coverage]\n[![version][version-badge]][package]\n[![MIT License][license-badge]][LICENSE]\n\n## Project status\nOkami is used in production, we consider evolving its API, but it works as expected!\n\n## Introduction\nIt's a set of Primitives React Components to build a Calendar. Handle the logic so you can focus on UI/UX. Similar to [downshift](https://github.com/paypal/downshift) or [selectless](https://github.com/Kilix/selectless).\n\nWe use composition to construct the calendar, which simply means:\n\n- A monthly calendar is composed of weekly calendar.\n- A weekly calendar is composed of daily calendar.\n\nThis allow to have a lot fo flexibility without repeating the logic and avoid complexity.\n\nWe strongly recommend to use `okami` with [date-fns](https://date-fns.org/).\n\n## Install\n\n```yarn add okami```\n```npm install --save okami```\n\n## Basic Usage\n\nFor more examples, look at the storybook :)\n\n```jsx\n\nimport React from 'react'\nimport frLocale from 'date-fns/locale/fr'\nimport { Calendar, DailyCalendar, Navigation, HoursLabels } from 'okami'\n\nimport data from './stories/data'\n\nconst Container = props =\u003e\n  \u003cdiv style={{ display: 'flex', alignItems: 'stretch', justifyContent: 'center'}} {...props} /\u003e\n\nconst CalendarContainer = props =\u003e\n  \u003cdiv style={{ display: 'flex', alignItems: 'stretch', justifyContent: 'flex-start', width: '100%' }} {...props} /\u003e\n\nexport default props =\u003e (\n  \u003cCalendar\n    data={data}\n    startingDay=\"monday\"\n    dateFormat=\"ddd DD/MM\"\n    hourFormat=\"HH\"\n    startHour=\"PT3H\"\n    endHour=\"PT22H\"\n    locale={frLocale}\n  \u003e\n    \u003cDailyCalendar showNow {...props}\u003e\n      {({calendar, dayEvents, rowHeight}) =\u003e (\n        \u003cdiv style={{display: 'flex', flexDirection:'column'}}\u003e\n          \u003cdiv style={{display:'flex'}}\u003e\n            \u003cNavigation dateFormat=\"ddd DD MMMM\"\u003e\n              {({next, prev, today, currentDate}) =\u003e (\n                \u003cdiv style={{display:'flex'}}\u003e\n                  \u003cbutton onClick={today}\u003eToday\u003c/button\u003e\n                  \u003cbutton onClick={prev}\u003ePrev day\u003c/button\u003e\n                  \u003cbutton onClick={next}\u003eNext day\u003c/button\u003e\n                  \u003cspan\u003e{currentDate}\u003c/span\u003e\n                \u003c/div\u003e\n              )}\n            \u003c/Navigation\u003e\n          \u003c/div\u003e\n          \u003cContainer\u003e\n            \u003cdiv style={{paddingTop: rowHeight * (dayEvents.length + 1)}}\u003e\n              \u003cHoursLabels renderChild={props =\u003e \u003cspan style={{height: rowHeight}} {...props} /\u003e} /\u003e\n            \u003c/div\u003e\n            \u003cCalendarContainer style={{flexDirection: 'column'}}\u003e\n              {dayEvents.map(props =\u003e \u003cEvent {...props} /\u003e)}\n              {calendar.events.map(props =\u003e \u003cEvent {...props} /\u003e)}\n            \u003c/CalendarContainer\u003e\n          \u003c/Container\u003e\n        \u003c/div\u003e\n      )}\n    \u003c/DailyCalendar\u003e\n  \u003c/Calendar\u003e\n)\n\n```\n\n## Documentation\n\n### Props Calendar\n\n| property      | type      | required | default    | description                  |\n|---------------|-----------|----------|------------|------------------------------|\n| `data`        | `array`   | yes      | -          | List of events               |\n| `startHour`   | `string`  | no       | PT0H       | Hour to start the calendar   |\n| `endHour`     | `string`  | no       | PT24H      | Hour to end the calendar     |\n| `dateFormat`  | `string`  | no       | MM/DD/YYYY | Format of the date string    |\n| `hourFormat`  | `string`  | no       | HH:mm      | Format of the hour string    |\n| `startingDay` | `string`  | no       | sunday     | Starting day of the week     |\n| `locale`      | `object`  | no       | en         | Local from `date-fns`        |\n| `rowHeight`   | `number`  | no       | 30         | Height of a row              |\n\nTo define property that will be use as duration like `startHours` or `endHour`.\nWe use [ISO-8601](https://fr.wikipedia.org/wiki/ISO_8601) format for durations.\n\nEvery prop passed to Calendar can be overwritten as the sub component level.\n\n```jsx\n  \u003cCalendar\n    data={data}\n    startingDay=\"monday\"\n    dateFormat=\"ddd DD/MM\"\n    hourFormat=\"HH\"\n    startHour=\"PT3H\"\n    endHour=\"PT22H\"\n  \u003e\n    \u003cMonthlyCalendar\u003e{...}\u003c/MonthlyCalendar\u003e\n    \u003cDailyCalendar dateFormat=\"DD-MM-YYYY\"\u003e{...}\u003c/DailyCalendar\u003e\n  \u003c/Calendar\u003e\n```\nThis will use the `dateFormat` from `\u003cCalendar\u003e` in `\u003cMonthlyCalendar\u003e` but `\u003cDailyCalendar\u003e` will use his custom `dateFormat` when it renders.\n\n---\n\n### Daily Calendar\n\nRender a day.\n\n#### Props\n\n| property      | type      | default      | description                        |\n|---------------|-----------|--------------|------------------------------------|\n| `start`       | `Date`    | `new Date()` | Day to show                        |\n| `showNow`     | `boolean` | `false`      | Send props to show the time of day |\n\n#### Child Callback Function\n\n| property         | type       | description                                                    |\n|------------------|------------|----------------------------------------------------------------|\n| `calendar`       | `Object`   | events, label and date of the day                              |\n| `start`          | `Date`     | date of the day                                                |\n| `showNowProps`   | `Object`   | if `showNow` is true, props to the showNow container (postion) |\n| `hours`          | `Array`    | Array of formatted string for hours labels                     |\n| `rowHeight`      | `Number`   | Height of the row                                              |\n| `dayEvents`      | `Array`    | Array of the events that last more than a day of the all day   |\n\n**calendar**\n\n| property | type     |\n|----------|----------|\n| `date`   | `Date`   |\n| `events` | `Array`  |\n\n\n**dayEvents**\n\n| property | type       |\n|----------|------------|\n| `key`    | `event.id` |\n| `event`  | `Object`   |\n| `style`  | `Object`   |\n\nThe style object is passed only if the `getColumnProp` is called and we have a ref available.\n\n| methods          | description                                   |\n|------------------|-----------------------------------------------|\n| `nextDay`        | Go to next day                                |\n| `prevDay`        | Go to previous day                            |\n| `gotoToday`      | Go to today                                   |\n| `dateLabel`      | get the date formatted                        |\n| `getColumnProps` | get the props for the container of the events |\n\n**dateLabel**\n\nAllow you to render the current day with a special format.\n\n- dateFormat: use the convention from `date-fns` [format](https://date-fns.org/v1.28.5/docs/format)\n\n**getColumnProps**\n\nAllow to get the ref to your column element for calculation of the events position.\n\n- 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: \u003cdiv ref={props.innerRef} /\u003e.\nBy default, it will use the react default ref key\n\n---\n\n### Weekly Calendar\n\nRender a week.\n\n#### Props\n\n| property      | type      | default      | description                        |\n|---------------|-----------|--------------|------------------------------------|\n| `start`       | `Date`    | `new Date()` | Day of the week to show            |\n| `showNow`     | `boolean` | `false`      | Send props to show the time of day |\n\n#### Child Callback Function\n\n| property         | type       | description                                                    |\n|------------------|------------|----------------------------------------------------------------|\n| `calendar`       | `Array`    | list of day for the week                                       |\n| `end`            | `Date`     | end of the week                                                |\n| `start`          | `Date`     | start of the week                                              |\n| `showNowProps`   | `Object`   | if `showNow` is true, props to the showNow container (postion) |\n| `hours`          | `Array`    | Array of formatted string for hours labels                     |\n| `rowHeight`      | `Number`   | Height of the row                                              |\n| `weekEvents`     | `Array`    | Array of the events that last more than a day of the all week  |\n\n**weekEvents**\n\n| property | type       |\n|----------|------------|\n| `key`    | `event.id` |\n| `event`  | `Object`   |\n| `style`  | `Object`   |\n\nThe style object is passed only if the `getContainerProps` is called and we have a ref available.\n\n| methods             | description                                   |\n|---------------------|-----------------------------------------------|\n| `nextWeek`          | Go to next week                               |\n| `prevWeek`          | Go to previous week                           |\n| `gotoToday`         | Go to today                                   |\n| `dateLabel`         | get the date formatted                        |\n| `getContainerProps` | get the props for the container of the events |\n\n\n**dateLabel**\n\nAllow you to render the current week with a special format.\n\n- dateFormat: use the convention from `date-fns` [format](https://date-fns.org/v1.28.5/docs/format)\n\n**getContainerProps**\n\nAllow to get the ref to your column element for calculation of the events position.\n\n- 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: \u003cdiv ref={props.innerRef} /\u003e.\nBy default, it will use the react default ref key.\n\n---\n\n### Monthly Calendar\n\nRender a month.\n\n#### Props\n\n| property      | type      | default      | description                        |\n|---------------|-----------|--------------|------------------------------------|\n| `start`       | `Date`    | `new Date()` | Date of the curent month           |\n\n#### Child Callback Function\n\n| property         | type       | description                                                    |\n|------------------|------------|----------------------------------------------------------------|\n| `calendar`       | `Array`    | List of first day of the week for the month                    |\n| `end`            | `Date`     | end of the month                                               |\n| `start`          | `Date`     | start of the month                                             |\n| `weeks`          | `Array`    | List of the first day of week for the month                    |\n| `rowHeight`      | `Number`   | Height of the row                                              |\n\n| methods             | description                                   |\n|---------------------|-----------------------------------------------|\n| `nextMonth`          | Go to next month                             |\n| `prevMonth`          | Go to previous month                         |\n| `gotoToday`         | Go to today                                   |\n| `dateLabel`         | get the date formatted                        |\n\n**dateLabel**\n\nAllow you to render the current month with a special format.\n\n- dateFormat: use the convention from `date-fns` [format](https://date-fns.org/v1.28.5/docs/format)\n\n---\n\n### Navigation\n\nrender the navigation for the calendar and the current label. The navigation and label are based on the type.\nIf 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.\nYou also get access to the function to toggle weekends on the calendar.\n\nIf you force showWeekend on a sub component, don't forget to update manually this props.\n\n#### Props\n| property      | type      | description                        |\n|---------------|-----------|------------------------------------|\n| `dateFormat`  | `string`  | format of the date                 |\n\n#### Child Callback Function\n\n| property       | type       | description                                                    |\n|----------------|------------|----------------------------------------------------------------|\n| `type`         | `string`   | Type of calendar ('monthly', 'weekly', 'daily')                |\n| `currentDate`  | `string`   | Formatted date based on type                                   |\n\n| methods         | description                   |\n|-----------------|-------------------------------|\n| `next`          | Go to next based on type      |\n| `prev`          | Go to previous based on type  |\n| `today`         | Go to today                   |\n| `toggleWeekend` | show/hide weekend on calendar |\n\n**toggleWeekend**\n\nLet you toggle the weekend in the calendar.\nIf you don't pass a pamarater, it will toggle the prop. If you pass a boolean, it will force the value.\n\n```javascript\n\nconst showWeekend = true\n\ntoggleWeekend() // showWeekend = false\ntoggleWeekend(true) // showWeekend = true\ntoggleWeekend(true) // showWeekend = true\ntoggleWeekend(false) // showWeekend = false\n[...]\n\n```\n\n---\n\n### DaysLabels / HoursLabels\n\nrender the days/hours labels for the calendar.\nYou have 3 options to render those components:\n - Child Callback function : allow full control\n - `renderChild` props: pass a component that receive pre formatted props\n - The default render that let you style the `div` container.\n\n#### Props\n| property      | type                  |\n|---------------|-----------------------|\n| `renderChild`  | `Element|Component`  |\n\n#### Child Callback Function\n\n**DaysLabels**\n\n| property       | type       | description                                                    |\n|----------------|------------|----------------------------------------------------------------|\n| `weeks`         | `array`   | Array of the formatted day labels                              |\n\n**HoursLabels**\n\n| property       | type       | description                                                    |\n|----------------|------------|----------------------------------------------------------------|\n| `hours`        | `array`   | Array of the formatted hour labels                              |\n\n```jsx\n  \u003cHoursLabels\u003e\n    { hours =\u003e hours.map(h =\u003e \u003cspan\u003e{h}\u003c/span\u003e} }\n  \u003c/HoursLabels\u003e\n```\n\n#### `renderChild` prop\n\nprops from the HoursLabels/DaysLabels are passed down to the container and the labels are rendered with the component from `renderChild`.\n\n```jsx\n  \u003cHoursLabels renderChild={props =\u003e \u003cspan {...props} /\u003e} /\u003e\n```\n\n#### The default render function\n\nprops from the HoursLabels/DaysLabels are passed down to the container.\n\n```\u003cHoursLabels /\u003e```\n\nThis is the render function used :\n```jsx\n\u003cdiv {...props}\u003e\n  {formattedDays.map((h, idx) =\u003e (\n    \u003cdiv key={`day_label_${idx}`} style={{height: rowHeight}}\u003e\n      {h}\n    \u003c/div\u003e\n  ))}\n\u003c/div\u003e\n```\n---\n\n### Data structure\n\n`data` is an array of objects, the object requires a few properties :\n\n| property | type              | description                  |\n|----------|-------------------|------------------------------|\n| `id`     | `ID`              | Identifier of the event      |\n| `title`  | `string`          | Title of the event           |\n| `allDay` | `boolean | Date`  | Determine the type of event  |\n| `start`  | `Date`            | Beggining of the event       |\n| `end`    | `Date`            | End of the event             |\n\n`allDay` has 3 states :\n - `true`, the event is on multiple days\n - `false`, the event is no longer than a day\n - `Date`, the event last all day\n\nif `allDay` is a boolean, you need to provide a `start` and `end` properties.\nIf you want to create an event for the all day, you just put the date in `allDay`.\n\n```javascript\n\n// Event of 2 hours:\n{\n  id: 0,\n  title: 'Diner',\n  allDay: false,\n  start : 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)',\n  end: 'Wed Sep 06 2017 14:07:52 GMT+0200 (CEST)'\n}\n\n// Event of all day:\n{\n  id: 0,\n  title: 'Diner',\n  allDay: 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)'\n}\n\n// Event of 2 days:\n{\n  id: 0,\n  title: 'Diner',\n  allDay: true,\n  start : 'Wed Sep 06 2017 12:07:52 GMT+0200 (CEST)',\n  end: 'Wed Sep 08 2017 14:07:52 GMT+0200 (CEST)'\n}\n\n```\n\n\n# LICENSE\n\n MIT\n\n\n[build-badge]: https://img.shields.io/travis/Kilix/okami.svg?style=flat-square\n[build]: https://travis-ci.org/Kilix/okami\n[coverage-badge]: https://img.shields.io/codecov/c/github/Kilix/okami.svg?style=flat-square\n[coverage]: https://codecov.io/github/Kilix/okami\n[version-badge]: https://img.shields.io/npm/v/okami.svg?style=flat-square\n[package]: https://www.npmjs.com/package/okami\n[license-badge]: https://img.shields.io/npm/l/okami.svg?style=flat-square\n[license]: https://github.com/paypal/okami/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkilix%2Fokami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkilix%2Fokami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkilix%2Fokami/lists"}