React Native Calendar Components 🗓️ 📆
This module includes various customizable React-Native calendar components.
The package is both Android and iOS compatible.
You can run example module by performing these steps:
$ git clone [email protected]:wix/react-native-calendars.git $ npm install $ react-native run-ios
You can check example screens source code in example module screens
This project is compatible with Expo/CRNA (without ejecting), and the examples have been published on Expo
$ npm install --save react-native-calendars
The solution is implemented in JavaScript so no native module linking is required.
import {Calendar, CalendarList, Agenda
} from 'react-native-calendars';
All parameters for components are optional. By default the month of current local date will be displayed.
Event handler callbacks are called with
calendar objectslike this:
{ day: 1, // day of month (1-31) month: 1, // month of year (1-12) year: 2017, // year timestamp, // UTC timestamp representing 00:00 AM of this date dateString: '2016-05-13' // date formatted as 'YYYY-MM-DD' string }
Parameters that require date types accept
YYYY-MM-DDformated
date-strings, JavaScript date objects,
calendar objectsand
UTC timestamps.
Calendars can be localized by adding custom locales to
LocaleConfigobject:
import {LocaleConfig} from 'react-native-calendars';LocaleConfig.locales['fr'] = { monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin','Juil.','Août','Sept.','Oct.','Nov.','Déc.'], dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'], today: 'Aujourd'hui' }; LocaleConfig.defaultLocale = 'fr';
{console.log('selected day', day)}} // Handler which gets executed on day long press. Default = undefined onDayLongPress={(day) => {console.log('selected day', day)}} // Month format in calendar title. Formatting values: http://arshaw.com/xdate/#Formatting monthFormat={'yyyy MM'} // Handler which gets executed when visible month changes in calendar. Default = undefined onMonthChange={(month) => {console.log('month changed', month)}} // Hide month navigation arrows. Default = false hideArrows={true} // Replace default arrows with custom ones (direction can be 'left' or 'right') renderArrow={(direction) => ()} // Do not show days of other months in month page. Default = false hideExtraDays={true} // If hideArrows=false and hideExtraDays=false do not switch month when tapping on greyed out // day from another month that is visible in calendar page. Default = false disableMonthChange={true} // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday. firstDay={1} // Hide day names. Default = false hideDayNames={true} // Show week numbers to the left. Default = false showWeekNumbers={true} // Handler which gets executed when press arrow icon left. It receive a callback can go back month onPressArrowLeft={subtractMonth => subtractMonth()} // Handler which gets executed when press arrow icon right. It receive a callback can go next month onPressArrowRight={addMonth => addMonth()} // Disable left arrow. Default = false disableArrowLeft={true} // Disable right arrow. Default = false disableArrowRight={true} // Disable all touch events for disabled days. can be override with disableTouchEvent in markedDates disableAllTouchEventsForDisabledDays={true} // Replace default month and year title with custom one. the function receive a date as parameter. renderHeader={(date) => {/*Return JSX*/}} // Enable the option to swipe between months. Default = false enableSwipeMonths={true} />
Disclaimer: Make sure that
markedDatesparam is immutable. If you change
markedDatesobject content but the reference to it does not change calendar update will not be triggered.
Dot marking
You can customize a dot color for each day independently.
Multi-Dot marking
Use
markingType={'multi-dot'}if you want to display more than one dot. Both the and support multiple dots by using
dotsarray in
markedDatesprop. The property
coloris mandatory while
keyand
selectedColorare optional. If key is omitted then the array index is used as key. If
selectedColoris omitted then
colorwill be used for selected dates.
const vacation = {key:'vacation', color: 'red', selectedDotColor: 'blue'}; const massage = {key:'massage', color: 'blue', selectedDotColor: 'blue'}; const workout = {key:'workout', color: 'green'};
Period marking
Multi-period marking
CAUTION: This marking is only fully supported by the
component because it expands its height. Usage with might lead to overflow issues.Custom marking allows you to customize each marker with custom styles.
NEW! While we still don't support multi marking type, we add the possibility to combine between
periodand
simple.
javascript
Keep in mind that different marking types are not compatible. You can use just one marking style for a calendar.
The loading indicator next to the month name will be displayed if
hasdisplayLoadingIndicatorprop and the
markedDatescollection does not have a value for every day of the month in question. When you load data for days, just set
[]or special marking value to all days in
markedDatescollection.
If you want to have complete control over the calendar styles you can do it by overriding default
style.jsfiles. For example, if you want to override style first you have to find stylesheet id for this file:
https://github.com/wix/react-native-calendars/blob/master/src/calendar/header/style.js#L4
In this case it is
stylesheet.calendar.header. Next you can add overriding stylesheet to your theme with this id.
https://github.com/wix/react-native-calendars/blob/master/example/src/screens/calendars.js#L56
theme={{ arrowColor: 'white', 'stylesheet.calendar.header': { week: { marginTop: 5, flexDirection: 'row', justifyContent: 'space-between' } } }}
Disclaimer: Issues that arise because something breaks after using stylesheet override will not be supported. Use this option at your own risk.
If you need custom functionality not supported by current day component implementations you can pass your own custom day component to the calendar.
{ return ( {date.day} ); }} />
The
dayComponentprop has to receive a RN component or a function that receive props. The
dayComponentwill receive such props:
markedDatesvalue for this day.
Tip: Don't forget to implement
shouldComponentUpdate()for your custom day component to make the calendar perform better
If you implement an awesome day component please make a PR so that other people could use it :)
{console.log('now these months are visible', months);}} // Max amount of months allowed to scroll to the past. Default = 50 pastScrollRange={50} // Max amount of months allowed to scroll to the future. Default = 50 futureScrollRange={50} // Enable or disable scrolling of calendar list scrollEnabled={true} // Enable or disable vertical scroll indicator. Default = false showScrollIndicator={true} ...calendarParams />
You can also make the
CalendarListscroll horizontally. To do that you need to pass specific props to the
CalendarList:
An advanced
Agendacomponent that can display interactive listings for calendar day items.
{console.log('trigger items loading')}} // Callback that fires when the calendar is opened or closed onCalendarToggled={(calendarOpened) => {console.log(calendarOpened)}} // Callback that gets called on day press onDayPress={(day)=>{console.log('day pressed')}} // Callback that gets called when day changes while scrolling agenda list onDayChange={(day)=>{console.log('day changed')}} // Initially selected day selected={'2012-05-16'} // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined minDate={'2012-05-10'} // Maximum date that can be selected, dates after maxDate will be grayed out. Default = undefined maxDate={'2012-05-30'} // Max amount of months allowed to scroll to the past. Default = 50 pastScrollRange={50} // Max amount of months allowed to scroll to the future. Default = 50 futureScrollRange={50} // Specify how each item should be rendered in agenda renderItem={(item, firstItemInDay) => {return ();}} // Specify how each date should be rendered. day can be undefined if the item is not first in that day. renderDay={(day, item) => {return ();}} // Specify how empty date content with no items should be rendered renderEmptyDate={() => {return ();}} // Specify how agenda knob should look like renderKnob={() => {return ();}} // Specify what should be rendered instead of ActivityIndicator renderEmptyData = {() => {return ();}} // Specify your item comparison function for increased performance rowHasChanged={(r1, r2) => {return r1.text !== r2.text}} // Hide knob button. Default = false hideKnob={true} // By default, agenda dates are marked if they have at least one item, but you can override this if needed markedDates={{ '2012-05-16': {selected: true, marked: true}, '2012-05-17': {marked: true}, '2012-05-18': {disabled: true} }} // If disabledByDefault={true} dates flagged as not disabled will be enabled. Default = false disabledByDefault={true} // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly. onRefresh={() => console.log('refreshing...')} // Set this true while waiting for new data from a refresh refreshing={false} // Add a custom RefreshControl component, used to provide pull-to-refresh functionality for the ScrollView. refreshControl={null} // Agenda theme theme={{ ...calendarTheme, agendaDayTextColor: 'yellow', agendaDayNumColor: 'green', agendaTodayColor: 'red', agendaKnobColor: 'blue' }} // Agenda container style style={{}} />
See also the list of contributors who participated in this project.
Pull requests are most welcome! Please
npm run testand
npm run lintbefore push. Don't forget to add a title and a description that explain the issue you're trying to solve and your suggested solution. Screenshots and gifs are very helpful.