react-native-schedule-week-view
Version:
Week View Calendar for React Native
255 lines (204 loc) • 13.4 kB
Markdown
# react-native-schedule-week-view
The week view component for react-native.

## Key features
* Supported in Android and iOS
* Many user interactions supported: **drag and drop events**, swipe through pages, event press and long-press, grid press and long-press
* Customizable styles
* Multiple locale support
## Installation
> `npm install --save react-native-schedule-week-view`
or
> `yarn add react-native-schedule-week-view`
Requires react-native 0.59 or above (from `react-native-schedule-week-view >= 0.7.0`)
## Basic usage
```js
import WeekView from 'react-native-schedule-week-view';
const myEvents = [
{
id: 1,
description: 'Event',
startDate: new Date(2021, 3, 15, 12, 0),
endDate: new Date(2021, 3, 15, 12, 30),
color: 'blue',
// ... more properties if needed,
},
// More events...
];
const MyComponent = () => (
<WeekView
events={myEvents}
selectedDate={new Date(2021, 3, 15)}
numberOfDays={7}
/>
);
```
## Full API
### Props
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `events` | _Array_ | **required** | Events to display, in `Event Item` format ([see below](#event-item)). |
| `selectedDate` | _Date_ | **required** | Date to show the week-view in the first render. Note: changing this prop after the first render will not have any effect in the week-view; to actually move the week-view, use the `goToDate()` method, [see below](#methods). |
| `numberOfDays` | _Number_, one of `1`, `3`, `5`, `7` | **required** | Number of days to show in the week-view. |
|**_Gesture <br> interactions_**|
| `onEventPress` | _Function:_ `(event) => {}` | `null` | Callback when an event item is pressed, receives the event-item pressed: `(event) => {}`. |
| `onEventLongPress` | _Function:_ `(event) => {}` | `null` | Callback when an event item is long pressed, same signature as `onEventPress`. |
| `onSwipeNext` | _Function:_ `(date) => {}` | `null` | Callback when week-view is swiped to next week/days, receives new date shown. |
| `onSwipePrev` | _Function:_ `(date) => {}` | `null` | Callback when week-view is swiped to previous week/days, same signature as `onSwipeNext`. |
| `onGridClick` | _Function:_ `(pressEvent, startHour, date) => {}` | `null` | Callback when the grid view is pressed. Arguments: `pressEvent`: object passed by the [TouchableWithoutFeedback.onPress() method](https://reactnative.dev/docs/touchablewithoutfeedback#onpress) (not an event item); `startHour`: _Number_, hour pressed; `date` _Date_, date object indicating day and time pressed with precision up to seconds. Note: `startHour` is redundant (can be extracted from `date`), but is kept for backward-compatibility. |
| `onGridLongPress` | _Function:_ `(pressEvent, startHour, date) => {}` | `null` | Callback when the grid view is long-pressed. Same signature as `onGridClick` |
| `onDragEvent` | _Function:_ `(event, newStartDate, newEndDate) => update DB` | `null` | Callback when an event item is dragged to another position. Arguments: `event`: event-item moved, and the `newStartDate` and `newEndDate` are `Date` objects with day and hour of the new position (precision up to minutes). **With this callback you must trigger an update on the `events` prop (i.e. update your DB), with the updated information from the event.** |
| `onDayPress` | _Function:_ `(date, formattedDate) => {}` | `null` | Callback when a day from the header is pressed. |
| `onMonthPress` | _Function:_ `(date, formattedDate) => {}` | `null` | Callback when the month at the top left (title) is pressed. |
|**_Week-view <br> customizations_**|
| `startHour` | _Number_ | `8` (8 am) | Vertical position of the week-view in the first render (vertically in the agenda). |
| `initialHour` | _Number_ | `3600` (6 am) in minutes | Send the time in minutes so it can start as per the sent. For example, if you send 3600 it will show 6 hours. Vertical position of the week-view in the first render (vertically in the agenda). |
| `finalHour` | _Number_ | `23` (23 am) in hour | Vertical position of the week-view in the first render (vertically in the agenda). |
| `weekStartsOn` | _Number_ | `1` (Monday) | First day of the week, i.e. day to show at the left of the week-view (0 is Sunday, 1 is Monday, and so on). Only useful when `numberOfDays === 7` or `fixedHorizontally` is true. |
| `showTitle` | _Boolean_ | `true` | Show or hide the selected month and year in the top-left corner (a.k.a the title). |
| `hoursInDisplay` | _Number_ | `6` | Amount of hours to display vertically in the agenda. Increasing this number will make the events look smaller. |
| `timeStep` | _Number_ | `60` (minutes) | Number of minutes to use as step in the time labels at the left. Increasing this number will increase the vertical space between grid lines. |
| `formatDateHeader` | _String_ | `"MMM D"` (e.g. "Apr 3") | Formatter for dates in the header. See [all formatters in momentjs](https://momentjs.com/docs/#/displaying/format/). |
| `formatTimeLabel` | _String_ | `"H:mm"` (24 hours) | Formatter for the time labels at the left. Other examples, AM/PM: `"h:mm A"` or `"h:mm a"` for lowercase. See [all formatters in momentjs](https://momentjs.com/docs/#/displaying/format/). |
| `EventComponent` | _ReactComponent_ | `Text` | Custom component rendered inside an event. By default, is a `Text` with the `event.description`. See [sub-section below](#custom-eventcomponent) for details on the component. |
| `TodayHeaderComponent` | _ReactComponent_ | `null` | Custom component to highlight today in the header (by default, *today* looks the same than every day). See details in [sub-section below](#custom-todaycomponent) |
| `showNowLine` | _Boolean_ | `false` | If `true`, displays a line indicating the time right now. |
| `nowLineColor` | _String_ | `red (#E53935)` | Color used for the now-line. |
| `fixedHorizontally` | _Boolean_ | `false` | If `true`, the component can be used to display a single fixed week. See example in [sub-section below](#fixed-week). |
| `isRefreshing` | _Boolean_ | `false` | When `true`, the week-view will show an `<ActivityIndicator />` in the middle of the grid. |
| `RefreshComponent` | _ReactComponent_ | `ActivityIndicator` | Custom component used when `isRefreshing` is `true`. See [example below](#custom-refreshcomponent). |
| `locale` | _String_ | `"en"` | Locale for the dates (e.g. header). There's an `addLocale()` function to add customized locale, [see below](#locales-customization). |
| `rightToLeft` | _Boolean_ | `false` | If `true`, render older days to the right and more recent days to the left. |
| **_Style <br> props_** |
| `headerStyle` | _Object_ | - | Custom styles for header container. Example: `{ backgroundColor: '#4286f4', color: '#fff', borderColor: '#fff' }` |
| `headerTextStyle` | _Object_ | - | Custom styles for text inside header. Applied to day names and month name (i.e. title) |
| `hourTextStyle` | _Object_ | - | Custom styles for text displaying hours at the left. |
| `eventContainerStyle` | _Object_ | - | Custom styles for each event item container. Note: the background color and (absolute) positioning are already set. |
|**_Grid lines <br> props_**|
| `gridRowStyle` | _Object_ | `width: 1`, `color: grey (#E9EDF0)` | Prop to customize width and color of horizontal lines, provide: `{ borderTopWidth: <width>, borderColor: <color> }` |
| `gridColumnStyle` | _Object_ | same as above | Prop to customize width and color of vertical lines, provide: `{ borderLeftWidth: <width>, borderColor: <color> }` |
|**_Other props <br> (patch RN bugs)_**|
| `prependMostRecent` | _Boolean_ | `false` | If `true`, the horizontal prepending is done in the most recent dates when scrolling.|
### Event Item
```js
{
id: 1,
description: 'Event',
startDate: new Date(2021, 3, 15, 12, 0),
endDate: new Date(2021, 3, 15, 12, 30),
color: 'blue',
// ... more properties if needed,
}
```
### Methods
To use the component methods save a reference to it:
```js
<WeekView
// ... other props
ref={(ref) => { this.weekViewRef = ref; }}
/>
```
* **`goToDate(date, animated = true)`**: the component navigates to a custom date. Note: if the target date has not been rendered before, there may be a delay on the animation.
* **`goToNextPage(animated = true)`**: the component navigates to the next page (to the future). Note: if `prependMostRecent` is `true`, and the component is near the last page rendered, there may be a delay on the animation.
* **`goToPrevPage(animated = true)`**: the component navigates to the previous page (to the past). Note: if `prependMostRecent` is `false` (the default), and the component is near the first page rendered, there may be a delay on the animation.
### Custom `EventComponent`
The custom component will be rendered inside a `TouchableOpacity`, which has the background color set to `event.color`, and is placed with absolute position in the grid. The component receives two props:
* **`event`** _(Event)_ - Event item as described before.
* **`position`**: _(Object)_ - object containing `top`, `left`, `height` and `width` values in pixels.
For example, to display an icon inside each event, such as a [react-native-elements Icon](https://react-native-elements.github.io/react-native-elements/docs/icon/):
```js
const MyEventComponent = ({ event, position }) => (
<Icon
name={event.iconName}
type={event.iconType}
color={event.color}
size={position.height}
/>
);
<WeekView
// ... other props
EventComponent={MyEventComponent}
/>
```
### Custom TodayComponent
Use this prop to highlight today in the header, by rendering it differently from the other days. The component `TodayHeaderComponent` receives these props:
* `date` _(moment Date)_ - moment date object containing today's date.
* `formattedDate` _(String)_ - day formatted according to `formatDateHeader`, e.g. `"Mon 3"`.
* `textStyle` _(Object)_ - text style used for every day.
For example, to highlight today with a bold font:
```js
const MyTodayComponent = ({ formattedDate, textStyle }) => (
<Text style={[textStyle, { fontWeight: 'bold' }]}>{formattedDate}</Text>
);
<WeekView
// ... other props
TodayHeaderComponent={MyTodayComponent}
/>
```
### Locales customization
There's a `addLocale` function to add customized locale for the component. The component depends on `momentjs`, you can refer to https://momentjs.com/docs/#/customization/ for more information.
Example:
```js
export WeekView, { addLocale } from 'react-native-schedule-week-view';
// add customized localed before using locale prop.
addLocale('fr', {
months: 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
monthsShort: 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
weekdays: 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
weekdaysShort: 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
});
```
### Custom RefreshComponent
* `RefreshComponent` is a _ReactComponent_ that receives a `style` prop that must be used (since it sets the component position).
* Note: the `ActivityIndicator` default color in some devices may be white.
Example:
```js
const MyRefreshComponent = ({ style }) => (
<Text style={style}>loading...</Text>
);
<WeekView
// ... other props
RefreshComponent={MyRefreshComponent}
/>
```
## Other example usages
### Fixed week
The `WeekView` component can be used to display a fixed week (as a timetable):
* Use the prop `fixedHorizontally={true}`. This prop should not be changed after the first render
* To set `startDate` and `endDate` in each event, you should use the function provided: `createFixedWeekDate(day, hour, minutes=0, seconds=0)`, where:
* `day`: _(Number|String)_ - specify day of the week as number (1 is monday, 2 is tuesday, etc) or as string (will be parsed with the current locale, e.g. `"Monday"`, `"Tuesday"`, etc. for english).
* `hour`: _(Number)_ - specify hour of the day as number (from 0 to 23)
* `minutes`: _(Number)_ - specify minutes of the day as number (from 0 to 59), defaults to 0
* `seconds`: _(Number)_ - specify seconds of the day as number (from 0 to 59), defaults to 0
If you choose to not use `createFixedWeekDate()`, make sure that `startDate` and `endDate` are `Date` objects within this week, otherwise the events will not be displayed correctly in the timetable.
* If the `numberOfDays` is other than 7, will display the first days of the week. E.g. if `numberOfDays === 5`, will display from monday to friday.
```js
import WeekView, { createFixedWeekDate } from 'react-native-schedule-week-view';
const myEvents = [
{
id: 1,
description: 'Event 1',
startDate: createFixedWeekDate('Monday', 12), // Day may be passed as string
endDate: createFixedWeekDate(1, 14), // Or as number, 1 = monday
color: 'blue',
},
{
id: 2,
description: 'Event 2',
startDate: createFixedWeekDate('wed', 16),
endDate: createFixedWeekDate(3, 16, 30),
color: 'red',
},
];
const MyComponent = () => (
<WeekView
events={myEvents}
fixedHorizontally={true}
// Recommended props:
showTitle={false} // if true, shows this month and year
numberOfDays={7}
formatDateHeader="ddd" // display short name days, e.g. Mon, Tue, etc
// ... other props
/>
);
```