import dayjs from 'dayjs' ; import React from 'react' ; import { TextStyle , ViewStyle } from 'react-native' ; import { MIN_HEIGHT } from '../commonStyles' ; import { DateRangeHandler , EventCellStyle , EventRenderer , HeaderRenderer , HorizontalDirection , ICalendarEventBase , Mode , MonthHeaderRenderer , WeekNum , } from '../interfaces' ; import { useTheme } from '../theme/ThemeContext' ; import { getDatesInMonth , getDatesInNextCustomDays , getDatesInNextOneDay , getDatesInNextThreeDays , getDatesInWeek , isAllDayEvent , modeToNum , typedMemo , } from '../utils' ; import { CalendarBody } from './CalendarBody' ; import { CalendarBodyForMonthView } from './CalendarBodyForMonthView' ; import { CalendarHeader } from './CalendarHeader' ; import { CalendarHeaderForMonthView } from './CalendarHeaderForMonthView' ; export interface CalendarContainerProps < T extends ICalendarEventBase > { /**
     * Events to be rendered. This is a required prop.
     */ events : T [ ] ; /**
     * The height of calendar component. This is a required prop.
     */ height : number ; /**
     * The height of each hour row.
     */ hourRowHeight ? : number ; /**
     * Adjusts the indentation of events that occur during the same time period. Defaults to 20 on web and 8 on mobile.
     */ overlapOffset ? : number ; eventCellStyle ? : EventCellStyle < T > ; calendarContainerStyle ? : ViewStyle ; headerContainerStyle ? : ViewStyle ; headerContentStyle ? : ViewStyle ; dayHeaderStyle ? : ViewStyle ; dayHeaderHighlightColor ? : string ; weekDayHeaderHighlightColor ? : string ; bodyContainerStyle ? : ViewStyle ; renderEvent ? : EventRenderer < T > ; renderHeader ? : HeaderRenderer < T > ; renderHeaderForMonthView ? : MonthHeaderRenderer ; ampm ? : boolean ; date ? : Date ; locale ? : string ; hideNowIndicator ? : boolean ; mode ? : Mode ; scrollOffsetMinutes ? : number ; showTime ? : boolean ; swipeEnabled ? : boolean ; weekStartsOn ? : WeekNum ; onChangeDate ? : DateRangeHandler ; onPressCell ? : ( date : Date ) => void ; onPressDateHeader ? : ( date : Date ) => void ; onPressEvent ? : ( event : T ) => void ; weekEndsOn ? : WeekNum ; maxVisibleEventCount ? : number ; eventMinHeightForMonthView ? : number ; activeDate ? : Date ; headerComponent ? : React . ReactElement | null ; headerComponentStyle ? : ViewStyle ; hourStyle ? : TextStyle ; showAllDayEventCell ? : boolean ; } function _CalendarContainer < T extends ICalendarEventBase > ( { events , height , hourRowHeight , ampm = false , date , eventCellStyle , locale = 'en' , hideNowIndicator = false , mode = 'week' , overlapOffset , scrollOffsetMinutes = 0 , showTime = true , headerContainerStyle = { } , headerContentStyle = { } , dayHeaderStyle = { } , dayHeaderHighlightColor = '' , weekDayHeaderHighlightColor = '' , bodyContainerStyle = { } , swipeEnabled = true , weekStartsOn = 0 , onChangeDate , onPressCell , onPressDateHeader , onPressEvent , renderEvent , renderHeader : HeaderComponent = CalendarHeader , renderHeaderForMonthView : HeaderComponentForMonthView = CalendarHeaderForMonthView , weekEndsOn = 6 , maxVisibleEventCount = 3 , eventMinHeightForMonthView = 22 , activeDate , headerComponent = null , headerComponentStyle = { } , hourStyle = { } , showAllDayEventCell = true , } ) { const [ targetDate , setTargetDate ] = React . useState ( dayjs ( date ) ) ; React . useEffect ( ( ) => { if ( date ) { setTargetDate ( dayjs ( date ) ) ; } } , [ date ] ) ; const allDayEvents = React . useMemo ( ( ) => events . filter ( ( event ) => isAllDayEvent ( event . start , event . end ) ) , [ events ] ) ; const daytimeEvents = React . useMemo ( ( ) => events . filter ( ( event ) => ! isAllDayEvent ( event . start , event . end ) ) , [ events ] ) ; const dateRange = React . useMemo ( ( ) => { switch ( mode ) { case 'month' : return getDatesInMonth ( targetDate , locale ) ; case 'week' : return getDatesInWeek ( targetDate , weekStartsOn , locale ) ; case '3days' : return getDatesInNextThreeDays ( targetDate , locale ) ; case 'day' : return getDatesInNextOneDay ( targetDate , locale ) ; case 'custom' : return getDatesInNextCustomDays ( targetDate , weekStartsOn , weekEndsOn , locale ) ; default : throw new Error ( `[react-native-big-calendar] The mode which you specified "${ mode }" is not supported.` ) ; } } , [ mode , targetDate , locale , weekEndsOn , weekStartsOn ] ) ; React . useEffect ( ( ) => { if ( onChangeDate ) { onChangeDate ( [ dateRange [ 0 ] . toDate ( ) , dateRange . slice ( - 1 ) [ 0 ] . toDate ( ) ] ) ; } } , [ dateRange , onChangeDate ] ) ; const cellHeight = React . useMemo ( ( ) => hourRowHeight || Math . max ( height - 30 , MIN_HEIGHT ) / 24 , [ height , hourRowHeight ] ) ; const theme = useTheme ( ) ; const onSwipeHorizontal = React . useCallback ( ( direction ) => { if ( ! swipeEnabled ) { return ; } if ( ( direction === 'LEFT' && ! theme . isRTL ) || ( direction === 'RIGHT' && theme . isRTL ) ) { setTargetDate ( targetDate . add ( modeToNum ( mode , targetDate ) , 'day' ) ) ; } else { setTargetDate ( targetDate . add ( modeToNum ( mode , targetDate ) * - 1 , 'day' ) ) ; } } , [ swipeEnabled , targetDate , mode , theme . isRTL ] ) ; const commonProps = { cellHeight , dateRange , mode , onPressEvent , } ; if ( mode === 'month' ) { const headerProps = { style : headerContainerStyle , locale : locale , weekStartsOn : weekStartsOn , headerContentStyle : headerContentStyle , dayHeaderStyle : dayHeaderStyle , dayHeaderHighlightColor : dayHeaderHighlightColor , weekDayHeaderHighlightColor : weekDayHeaderHighlightColor , showAllDayEventCell : showAllDayEventCell , } ; return ( < React . Fragment > < HeaderComponentForMonthView { ... headerProps } / > < CalendarBodyForMonthView < T > { ... commonProps } style = { bodyContainerStyle } containerHeight = { height } events = { [ ... daytimeEvents , ... allDayEvents ] } eventCellStyle = { eventCellStyle } weekStartsOn = { weekStartsOn } hideNowIndicator = { hideNowIndicator } onPressCell = { onPressCell } onPressEvent = { onPressEvent } onSwipeHorizontal = { onSwipeHorizontal } renderEvent = { renderEvent } targetDate = { targetDate } maxVisibleEventCount = { maxVisibleEventCount } eventMinHeightForMonthView = { eventMinHeightForMonthView } / > < /React.Fragment>); } const headerProps = { ... commonProps , style : headerContainerStyle , allDayEvents : allDayEvents , onPressDateHeader : onPressDateHeader , activeDate , headerContentStyle : headerContentStyle , dayHeaderStyle : dayHeaderStyle , dayHeaderHighlightColor : dayHeaderHighlightColor , weekDayHeaderHighlightColor : weekDayHeaderHighlightColor , showAllDayEventCell : showAllDayEventCell , } ; return ( < React . Fragment > < HeaderComponent { ... headerProps } / > < CalendarBody { ... commonProps } style = { bodyContainerStyle } containerHeight = { height } events = { daytimeEvents } eventCellStyle = { eventCellStyle } hideNowIndicator = { hideNowIndicator } overlapOffset = { overlapOffset } scrollOffsetMinutes = { scrollOffsetMinutes } ampm = { ampm } showTime = { showTime } onPressCell = { onPressCell } onPressEvent = { onPressEvent } onSwipeHorizontal = { onSwipeHorizontal } renderEvent = { renderEvent } headerComponent = { headerComponent } headerComponentStyle = { headerComponentStyle } hourStyle = { hourStyle } / > < /React.Fragment>); } export const CalendarContainer = typedMemo ( _CalendarContainer ) ;