From 0a8e02a5aacb71afe0255f43aed71a303e0e3d7a Mon Sep 17 00:00:00 2001 From: "benjamin.berthelemy" Date: Mon, 5 Jun 2017 15:35:04 +0200 Subject: [PATCH 1/2] added handlers for prev/next + customizable view for selected days --- components/Calendar.js | 717 +++++++++++++++++++++-------------------- components/Day.js | 202 ++++++------ components/styles.js | 197 ++++++----- 3 files changed, 575 insertions(+), 541 deletions(-) diff --git a/components/Calendar.js b/components/Calendar.js index e7daff5..87372f3 100644 --- a/components/Calendar.js +++ b/components/Calendar.js @@ -1,379 +1,406 @@ -import React, { Component, PropTypes } from 'react'; -import { - Dimensions, - ScrollView, - Text, - TouchableOpacity, - View, -} from 'react-native'; - -import Day from './Day'; - -import moment from 'moment'; -import styles from './styles'; +import React, {Component, PropTypes} from "react"; +import {Dimensions, ScrollView, Text, TouchableOpacity, View} from "react-native"; +import Day from "./Day"; +import moment from "moment"; +import styles from "./styles"; const DEVICE_WIDTH = Dimensions.get('window').width; const VIEW_INDEX = 2; function getNumberOfWeeks(month, weekStart) { - const firstDay = moment(month).startOf('month').day(); - const offset = (firstDay - weekStart + 7) % 7; - const days = moment(month).daysInMonth(); - return Math.ceil((offset + days) / 7); + const firstDay = moment(month).startOf('month').day(); + const offset = (firstDay - weekStart + 7) % 7; + const days = moment(month).daysInMonth(); + return Math.ceil((offset + days) / 7); } export default class Calendar extends Component { + state = { + currentMoment: moment(this.props.startDate), + selectedMoment: moment(this.props.selectedDate), + rowHeight: null, + width: DEVICE_WIDTH + }; + + static propTypes = { + viewForDay: PropTypes.func, + currentMonth: PropTypes.any, + customStyle: PropTypes.object, + dayHeadings: PropTypes.array, + eventDates: PropTypes.array, + monthNames: PropTypes.array, + nextButtonText: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object + ]), + onDateSelect: PropTypes.func, + onSwipeNext: PropTypes.func, + onSwipePrev: PropTypes.func, + onTouchNext: PropTypes.func, + onTouchPrev: PropTypes.func, + onTitlePress: PropTypes.func, + prevButtonText: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object + ]), + removeClippedSubviews: PropTypes.bool, + scrollEnabled: PropTypes.bool, + selectedDate: PropTypes.any, + showControls: PropTypes.bool, + showEventIndicators: PropTypes.bool, + startDate: PropTypes.any, + titleFormat: PropTypes.string, + today: PropTypes.any, + weekStart: PropTypes.number, + calendarFormat: PropTypes.string + }; + + static defaultProps = { + prevEnabled: true, + nextEnabled: true, + viewForDay: null, + customStyle: {}, + dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], + eventDates: [], + monthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + nextButtonText: 'Next', + prevButtonText: 'Prev', + removeClippedSubviews: true, + scrollEnabled: false, + showControls: false, + showEventIndicators: false, + startDate: moment().format('YYYY-MM-DD'), + titleFormat: 'MMMM YYYY', + weekStart: 1, + calendarFormat: 'monthly' // weekly or monthly + }; + + componentDidMount() { + // fixes initial scrolling bug on Android + setTimeout(() => this.scrollToItem(VIEW_INDEX), 0); + } - state = { - currentMoment: moment(this.props.startDate), - selectedMoment: moment(this.props.selectedDate), - rowHeight: null, - }; - - static propTypes = { - currentMonth: PropTypes.any, - customStyle: PropTypes.object, - dayHeadings: PropTypes.array, - eventDates: PropTypes.array, - monthNames: PropTypes.array, - nextButtonText: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.object - ]), - onDateSelect: PropTypes.func, - onSwipeNext: PropTypes.func, - onSwipePrev: PropTypes.func, - onTouchNext: PropTypes.func, - onTouchPrev: PropTypes.func, - onTitlePress: PropTypes.func, - prevButtonText: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.object - ]), - removeClippedSubviews: PropTypes.bool, - scrollEnabled: PropTypes.bool, - selectedDate: PropTypes.any, - showControls: PropTypes.bool, - showEventIndicators: PropTypes.bool, - startDate: PropTypes.any, - titleFormat: PropTypes.string, - today: PropTypes.any, - weekStart: PropTypes.number, - calendarFormat: PropTypes.string - }; - - static defaultProps = { - customStyle: {}, - width: DEVICE_WIDTH, - dayHeadings: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], - eventDates: [], - monthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], - nextButtonText: 'Next', - prevButtonText: 'Prev', - removeClippedSubviews: true, - scrollEnabled: false, - showControls: false, - showEventIndicators: false, - startDate: moment().format('YYYY-MM-DD'), - titleFormat: 'MMMM YYYY', - weekStart: 1, - calendarFormat: 'monthly' // weekly or monthly - }; - - componentDidMount() { - // fixes initial scrolling bug on Android - setTimeout(() => this.scrollToItem(VIEW_INDEX), 0); - } - - componentDidUpdate() { - this.scrollToItem(VIEW_INDEX); - } - - componentWillReceiveProps(nextProps) { - if (nextProps.selectedDate && this.props.selectedDate !== nextProps.selectedDate) { - this.setState({selectedMoment: nextProps.selectedDate}); + componentDidUpdate() { + this.scrollToItem(VIEW_INDEX); } - if (nextProps.currentMonth) { - this.setState({currentMoment: moment(nextProps.currentMonth)}); + + componentWillReceiveProps(nextProps) { + if (nextProps.selectedDate && this.props.selectedDate !== nextProps.selectedDate) { + this.setState({selectedMoment: nextProps.selectedDate}); + } + if (nextProps.currentMonth) { + this.setState({currentMoment: moment(nextProps.currentMonth)}); + } } - } - - getStack(currentMoment) { - if (this.props.scrollEnabled) { - let i = -VIEW_INDEX; - const res = []; - - for (i; i <= VIEW_INDEX; i++) { - if (this.props.calendarFormat === 'monthly') { - res.push(moment(currentMoment).add(i, 'month')); - } else { - res.push(moment(currentMoment).add(i, 'week')); + + getStack(currentMoment) { + if (this.props.scrollEnabled) { + let i = -VIEW_INDEX; + const res = []; + + for (i; i <= VIEW_INDEX; i++) { + if (this.props.calendarFormat === 'monthly') { + res.push(moment(currentMoment).add(i, 'month')); + } + else { + res.push(moment(currentMoment).add(i, 'week')); + } + } + return res; } - } - return res; + return [moment(currentMoment)]; } - return [moment(currentMoment)]; - } - prepareEventDates(eventDates, events) { - const parsedDates = {}; + prepareEventDates(eventDates, events) { + const parsedDates = {}; + + if (events) { + events.forEach(event => { + if (event.date) { + parsedDates[event.date] = event; + } + }); + } + else { + eventDates.forEach(event => { + parsedDates[event] = {}; + }); + } + + return parsedDates; + } - if (events) { - events.forEach(event => { - if (event.date) { - parsedDates[event.date] = event; + selectDate(date) { + if (typeof this.props.selectedDate === "undefined") { + this.setState({ + selectedMoment: date, + currentMoment: date + }); } - }); - } else { - eventDates.forEach(event => { - parsedDates[event] = {}; - }); } - return parsedDates; - } + selectAndJumpToToday() { + const today = new Date(); + const newMoment = moment(this.state.currentMonthMoment).set('month', today.getMonth()); - selectDate(date) { - if (this.props.selectedDate === undefined) { - this.setState({ selectedMoment: date, - currentMoment: date}); + this.setState({ + selectedMoment: today, + currentMonthMoment: newMoment + }); } - } - - selectAndJumpToToday() { - const today = new Date(); - const newMoment = moment(this.state.currentMonthMoment).set('month', today.getMonth()); - this.setState({ - selectedMoment: today, - currentMonthMoment: newMoment - }); - } - - onPrev = () => { - const newMoment = this.props.calendarFormat === 'monthly' ? - moment(this.state.currentMoment).subtract(1, 'month'): + + onPrev = () => { + const newMoment = this.props.calendarFormat === 'monthly' ? + moment(this.state.currentMoment).subtract(1, 'month') : moment(this.state.currentMoment).subtract(1, 'week'); - this.setState({ currentMoment: newMoment }); - this.props.onTouchPrev && this.props.onTouchPrev(newMoment); - } - - onNext = () => { - const newMoment = this.props.calendarFormat === 'monthly' ? - moment(this.state.currentMoment).add(1, 'month'): - moment(this.state.currentMoment).add(1, 'week'); - this.setState({ currentMoment: newMoment }); - this.props.onTouchNext && this.props.onTouchNext(newMoment); - } - - scrollToItem(itemIndex) { - const scrollToX = itemIndex * this.props.width; - if (this.props.scrollEnabled && this._calendar) { - this._calendar.scrollTo({ y: 0, x: scrollToX, animated: false }); + + if (this.props.onTouchPrev) { + this.props.onTouchPrev(newMoment) && this.setState({currentMoment: newMoment}); + } + else { + this.setState({currentMoment: newMoment}) + } } - } - scrollEnded(event) { - const position = event.nativeEvent.contentOffset.x; - const currentPage = position / this.props.width; - const newMoment = this.props.calendarFormat === 'monthly' ? - moment(this.state.currentMoment).add(currentPage - VIEW_INDEX, 'month') : - moment(this.state.currentMoment).add(currentPage - VIEW_INDEX, 'week'); + onNext = () => { + const newMoment = this.props.calendarFormat === 'monthly' + ? moment(this.state.currentMoment).add(1, 'month') + : moment(this.state.currentMoment).add(1, 'week'); + + if (this.props.onTouchNext) { + this.props.onTouchNext(newMoment) && this.setState({currentMoment: newMoment}); + } + else { + this.setState({currentMoment: newMoment}) + } + } - this.setState({ currentMoment: newMoment }); + scrollToItem(itemIndex) { + const scrollToX = itemIndex * this.state.width; - if (currentPage < VIEW_INDEX) { - this.props.onSwipePrev && this.props.onSwipePrev(newMoment); - } else if (currentPage > VIEW_INDEX) { - this.props.onSwipeNext && this.props.onSwipeNext(newMoment); + if (this.props.scrollEnabled && this._calendar) { + this._calendar.scrollTo({y: 0, x: scrollToX, animated: false}); + } } - } - onWeekRowLayout = (event) => { - if (this.state.rowHeight !== event.nativeEvent.layout.height) { - this.setState({ rowHeight: event.nativeEvent.layout.height }); + scrollEnded(event) { + const position = event.nativeEvent.contentOffset.x; + const currentPage = position / this.state.width; + const newMoment = this.props.calendarFormat === 'monthly' + ? moment(this.state.currentMoment).add(currentPage - VIEW_INDEX, 'month') + : moment(this.state.currentMoment).add(currentPage - VIEW_INDEX, 'week'); + + this.setState({currentMoment: newMoment}); + + if (currentPage < VIEW_INDEX) { + this.props.onSwipePrev && this.props.onSwipePrev(newMoment); + } + else if (currentPage > VIEW_INDEX) { + this.props.onSwipeNext && this.props.onSwipeNext(newMoment); + } } - } - - getStartMoment(calFormat, currMoment) { - const weekStart = this.props.weekStart; - - let res; - if (calFormat === 'monthly') { - res = moment(currMoment).startOf('month'); - } else { - // weekly - let sundayMoment = moment(currMoment).startOf('week'); - if (weekStart > 0) { - res = moment(currMoment).isoWeekday(weekStart); - if (res.diff(currMoment) > 0) { - res = moment(currMoment).subtract(7, 'day').isoWeekday(weekStart); + + onWeekRowLayout = (event) => { + if (this.state.rowHeight !== event.nativeEvent.layout.height) { + this.setState({rowHeight: event.nativeEvent.layout.height}); } - } else { - res = sundayMoment; - } } - return res; - } - - renderCalendarView(calFormat, argMoment, eventsMap) { - let renderIndex = 0, - weekRows = [], - days = []; - - const - startOfArgMoment = this.getStartMoment(calFormat, argMoment), - selectedMoment = moment(this.state.selectedMoment), - weekStart = this.props.weekStart, - todayMoment = moment(this.props.today), - todayIndex = todayMoment.date() - 1, - argDaysCount = calFormat === 'monthly' ? argMoment.daysInMonth(): 7, - offset = calFormat === 'monthly' ? - (startOfArgMoment.isoWeekday() - weekStart + 7) % 7: 0, - selectedIndex = moment(selectedMoment).date() - 1; - - do { - const dayIndex = renderIndex - offset; - const isoWeekday = (renderIndex + weekStart) % 7; - const thisMoment = moment(startOfArgMoment).add(dayIndex, 'day'); - - if (dayIndex >= 0 && dayIndex < argDaysCount) { - days.push(( - { - this.selectDate(thisMoment); - this.props.onDateSelect && this.props.onDateSelect(thisMoment ? thisMoment.format(): null ); - }} - caption={`${thisMoment.format('D')}`} - isToday={todayMoment.format('YYYY-MM-DD') == thisMoment.format('YYYY-MM-DD')} - isSelected={selectedMoment.isSame(thisMoment)} - event={eventsMap[thisMoment.format('YYYY-MM-DD')] || - eventsMap[thisMoment.format('YYYYMMDD')]} - showEventIndicators={this.props.showEventIndicators} - customStyle={this.props.customStyle} - /> - )); - } else { - days.push(); - } - if (renderIndex % 7 === 6) { - weekRows.push( - - {days} - ); - days = []; - if (dayIndex + 1 >= argDaysCount) { - break; + + getStartMoment(calFormat, currMoment) { + const weekStart = this.props.weekStart; + let res; + + if (calFormat === 'monthly') { + res = moment(currMoment).startOf('month'); } - } - renderIndex += 1; - } while (true) - const containerStyle = [styles.monthContainer, this.props.customStyle.monthContainer]; - return {weekRows}; - } - - renderHeading() { - let headings = []; - let i = 0; - - for (i; i < 7; ++i) { - const j = (i + this.props.weekStart) % 7; - headings.push( - - {this.props.dayHeadings[j]} - - ); + else { + // weekly + let sundayMoment = moment(currMoment).startOf('week'); + + if (weekStart > 0) { + res = moment(currMoment).isoWeekday(weekStart); + if (res.diff(currMoment) > 0) { + res = moment(currMoment).subtract(7, 'day').isoWeekday(weekStart); + } + } + else { + res = sundayMoment; + } + } + return res; } - return ( - - {headings} - - ); - } - - renderTopBar() { - let localizedMonth = this.props.monthNames[this.state.currentMoment.month()]; - return this.props.showControls - ? ( - - - - {this.props.prevButtonText} - - - this.props.onTitlePress && this.props.onTitlePress()}> - - {localizedMonth} {this.state.currentMoment.year()} - - - - - {this.props.nextButtonText} - - - - ) - : ( - - - {this.state.currentMoment.format(this.props.titleFormat)} - - - ); - } - - render() { - const calendarDates = this.getStack(this.state.currentMoment); - const eventDatesMap = this.prepareEventDates(this.props.eventDates, this.props.events); - const numOfWeeks = this.props.calendarFormat === 'weekly' ? 1 : - getNumberOfWeeks(this.state.currentMonthMoment, this.props.weekStart); - - return ( - - {this.renderTopBar()} - {this.renderHeading(this.props.titleFormat)} - {this.props.scrollEnabled ? - this._calendar = calendar} - horizontal - scrollEnabled - pagingEnabled - removeClippedSubviews={this.props.removeClippedSubviews} - scrollEventThrottle={1000} - showsHorizontalScrollIndicator={false} - automaticallyAdjustContentInsets={false} - onMomentumScrollEnd={(event) => this.scrollEnded(event)} - style={{ - height: this.state.rowHeight ? this.state.rowHeight * numOfWeeks : null, - }} - > - {calendarDates.map((date) => this.renderCalendarView(this.props.calendarFormat, moment(date), eventDatesMap))} - - : - this._calendar = calendar}> - {calendarDates.map((date) => this.renderCalendarView(this.props.calendarFormat, moment(date), eventDatesMap))} - - } - - ); - } + renderCalendarView(calFormat, argMoment, eventsMap) { + let renderIndex = 0, + weekRows = [], + days = []; + + const startOfArgMoment = this.getStartMoment(calFormat, argMoment); + const selectedMoment = moment(this.state.selectedMoment); + const weekStart = this.props.weekStart; + const todayMoment = moment(this.props.today); + const todayIndex = todayMoment.date() - 1; + const argDaysCount = calFormat === 'monthly' ? argMoment.daysInMonth() : 7; + const offset = (calFormat === 'monthly') ? (startOfArgMoment.isoWeekday() - weekStart + 7) % 7 : 0; + const selectedIndex = moment(selectedMoment).date() - 1; + + do { + const dayIndex = renderIndex - offset; + const isoWeekday = (renderIndex + weekStart) % 7; + const thisMoment = moment(startOfArgMoment).add(dayIndex, 'day'); + + if (dayIndex >= 0 && dayIndex < argDaysCount) { + days.push(( + { + this.selectDate(thisMoment); + this.props.onDateSelect && this.props.onDateSelect(thisMoment ? thisMoment : null, thisMoment ? thisMoment.format(): null); + }} + caption={`${thisMoment.format('D')}`} + current={thisMoment} + isToday={todayMoment.format('YYYY-MM-DD') == thisMoment.format('YYYY-MM-DD')} + isSelected={selectedMoment.isSame(thisMoment)} + event={eventsMap[thisMoment.format('YYYY-MM-DD')] || eventsMap[thisMoment.format('YYYYMMDD')]} + showEventIndicators={this.props.showEventIndicators} + customStyle={this.props.customStyle} + /> + )); + } + else { + days.push( + + ); + } + if (renderIndex % 7 === 6) { + weekRows.push( + + {days} + ); + days = []; + if (dayIndex + 1 >= argDaysCount) { + break; + } + } + renderIndex += 1; + } while (true) + const containerStyle = [{width: this.state.width}, this.props.customStyle.monthContainer]; + return ( + + {weekRows} + ); + } + + renderHeading() { + let headings = []; + let i = 0; + + for (i; i < 7; ++i) { + const j = (i + this.props.weekStart) % 7; + const style = j === 0 || j === 6 + ? [styles.weekendHeading, this.props.customStyle.weekendHeading] + : [styles.dayHeading, this.props.customStyle.dayHeading]; + headings.push({this.props.dayHeadings[j]}); + } + + return ( + + {headings} + + ); + } + + renderTopBar() { + let localizedMonth = this.props.monthNames[this.state.currentMoment.month()]; + + return this.props.showControls + ? ( + + + + {this.props.prevButtonText} + + + this.props.onTitlePress && this.props.onTitlePress()} + > + + {localizedMonth} {this.state.currentMoment.year()} + + + + + {this.props.nextButtonText} + + + + ) + : ( + + + {this.state.currentMoment.format(this.props.titleFormat)} + + + ); + } + + render() { + const calendarDates = this.getStack(this.state.currentMoment); + const eventDatesMap = this.prepareEventDates(this.props.eventDates, this.props.events); + const numOfWeeks = this.props.calendarFormat === 'weekly' ? 1 : + getNumberOfWeeks(this.state.currentMonthMoment, this.props.weekStart); + + const content = this.props.scrollEnabled + ? ( + this._calendar = calendar} + onLayout={(e) => this.setState({width: e.nativeEvent.layout.width})} + horizontal + scrollEnabled + pagingEnabled + removeClippedSubviews={this.props.removeClippedSubviews} + scrollEventThrottle={1000} + showsHorizontalScrollIndicator={false} + automaticallyAdjustContentInsets={false} + onMomentumScrollEnd={(event) => this.scrollEnded(event)} + style={{height: this.state.rowHeight ? this.state.rowHeight * numOfWeeks : null}} + > + {calendarDates.map((date) => this.renderCalendarView(this.props.calendarFormat, moment(date), eventDatesMap))} + + ) + : ( + this._calendar = calendar} onLayout={(e) => this.setState({width: e.nativeEvent.layout.width})}> + {calendarDates.map((date) => this.renderCalendarView(this.props.calendarFormat, moment(date), eventDatesMap))} + + ); + + return ( + + {this.renderTopBar()} + {this.renderHeading(this.props.titleFormat)} + {content} + + ); + } } diff --git a/components/Day.js b/components/Day.js index 494d0e0..e588f5a 100644 --- a/components/Day.js +++ b/components/Day.js @@ -1,106 +1,124 @@ -import React, { Component, PropTypes } from 'react'; -import { - Text, - TouchableOpacity, - TouchableWithoutFeedback, - View, -} from 'react-native'; - -import styles from './styles'; +import React, {Component, PropTypes} from "react"; +import {Text, TouchableOpacity, TouchableWithoutFeedback, View} from "react-native"; +import styles from "./styles"; export default class Day extends Component { - static defaultProps = { - customStyle: {}, - } + static defaultProps = { + customStyle: {}, + } - static propTypes = { - caption: PropTypes.any, - customStyle: PropTypes.object, - filler: PropTypes.bool, - event: PropTypes.object, - isSelected: PropTypes.bool, - isToday: PropTypes.bool, - isWeekend: PropTypes.bool, - onPress: PropTypes.func, - showEventIndicators: PropTypes.bool, - } + static propTypes = { + viewForDay: PropTypes.func, + current: PropTypes.any, + caption: PropTypes.any, + customStyle: PropTypes.object, + filler: PropTypes.bool, + event: PropTypes.object, + isSelected: PropTypes.bool, + isToday: PropTypes.bool, + isWeekend: PropTypes.bool, + containerWidth: PropTypes.number, + onPress: PropTypes.func, + showEventIndicators: PropTypes.bool, + } - dayCircleStyle = (isWeekend, isSelected, isToday, event) => { - const { customStyle } = this.props; - const dayCircleStyle = [styles.dayCircleFiller, customStyle.dayCircleFiller]; + dayCircleStyle = (isWeekend, isSelected, isToday, event) => { + const {customStyle} = this.props; + const dayCircleStyle = [styles.dayCircleFiller, customStyle.dayCircleFiller]; - if (isSelected) { - if (isToday) { - dayCircleStyle.push(styles.currentDayCircle, customStyle.currentDayCircle); - } else { - dayCircleStyle.push(styles.selectedDayCircle, customStyle.selectedDayCircle); - } - } + if (isSelected) { + if (isToday) { + dayCircleStyle.push(styles.currentDayCircle, customStyle.currentDayCircle); + } + else { + dayCircleStyle.push(styles.selectedDayCircle, customStyle.selectedDayCircle); + } + } - if (event) { - if (isSelected) { - dayCircleStyle.push(styles.hasEventDaySelectedCircle, customStyle.hasEventDaySelectedCircle, event.hasEventDaySelectedCircle); - } else { - dayCircleStyle.push(styles.hasEventCircle, customStyle.hasEventCircle, event.hasEventCircle); - } + if (event) { + if (isSelected) { + dayCircleStyle.push(styles.hasEventDaySelectedCircle, customStyle.hasEventDaySelectedCircle, event.hasEventDaySelectedCircle); + } + else { + dayCircleStyle.push(styles.hasEventCircle, customStyle.hasEventCircle, event.hasEventCircle); + } + } + return dayCircleStyle; } - return dayCircleStyle; - } - dayTextStyle = (isWeekend, isSelected, isToday, event) => { - const { customStyle } = this.props; - const dayTextStyle = [styles.day, customStyle.day]; + dayTextStyle = (isWeekend, isSelected, isToday, event) => { + const {customStyle} = this.props; + const dayTextStyle = [styles.day, customStyle.day]; - if (isToday && !isSelected) { - dayTextStyle.push(styles.currentDayText, customStyle.currentDayText); - } else if (isToday || isSelected) { - dayTextStyle.push(styles.selectedDayText, customStyle.selectedDayText); - } else if (isWeekend) { - dayTextStyle.push(styles.weekendDayText, customStyle.weekendDayText); - } + if (isToday && !isSelected) { + dayTextStyle.push(styles.currentDayText, customStyle.currentDayText); + } + else if (isToday || isSelected) { + dayTextStyle.push(styles.selectedDayText, customStyle.selectedDayText); + } + else if (isWeekend) { + dayTextStyle.push(styles.weekendDayText, customStyle.weekendDayText); + } - if (event) { - dayTextStyle.push(styles.hasEventText, customStyle.hasEventText, event.hasEventText) + if (event) { + dayTextStyle.push(styles.hasEventText, customStyle.hasEventText, event.hasEventText) + } + + return dayTextStyle; } - return dayTextStyle; - } - render() { - let { caption, customStyle } = this.props; - const { - filler, - event, - isWeekend, - isSelected, - isToday, - showEventIndicators, - } = this.props; + render() { + let {caption, customStyle, viewForDay} = this.props; + const { + current, + filler, + event, + isSelected, + isWeekend, + containerWidth, + isToday, + showEventIndicators, + } = this.props; + + const text = viewForDay + ? ( + viewForDay(current, isWeekend, isSelected, isToday, event, caption) + ) + : ( + + {caption} + + ); - return filler - ? ( - - - - - - ) - : ( - - - - {caption} - - {showEventIndicators && - - } - - - ); - } + const weekendStyles = isWeekend ? [styles.weekendDayButton, customStyle.weekendDayButton] : []; + const indicators = showEventIndicators + ? ( + + ) + : null; + + return filler + ? ( + + + + + + ) + : ( + + + {text} + {indicators} + + + ); + } } diff --git a/components/styles.js b/components/styles.js index 9a6fade..36c913d 100644 --- a/components/styles.js +++ b/components/styles.js @@ -1,109 +1,98 @@ -import { Dimensions, StyleSheet } from 'react-native'; - -const DEVICE_WIDTH = Dimensions.get('window').width; +import {StyleSheet} from "react-native"; const styles = StyleSheet.create({ - calendarContainer: { - backgroundColor: '#f7f7f7', - }, - monthContainer: { - width: DEVICE_WIDTH, - }, - calendarControls: { - flexDirection: 'row', - }, - controlButton: { - }, - controlButtonText: { - margin: 10, - fontSize: 15, - }, - title: { - flex: 1, - margin: 10, - }, - titleText: { - textAlign: 'center', - fontSize: 15, - }, - calendarHeading: { - flexDirection: 'row', - borderTopWidth: 1, - borderBottomWidth: 1, - }, - dayHeading: { - flex: 1, - fontSize: 15, - textAlign: 'center', - marginVertical: 5, - }, - weekendHeading: { - flex: 1, - fontSize: 15, - textAlign: 'center', - marginVertical: 5, - color: '#cccccc', - }, - weekRow: { - flexDirection: 'row', - }, - weekendDayButton: { - backgroundColor: '#fafafa', - }, - dayButton: { - alignItems: 'center', - padding: 5, - width: DEVICE_WIDTH / 7, - borderTopWidth: 1, - borderTopColor: '#e9e9e9', - }, - dayButtonFiller: { - padding: 5, - width: DEVICE_WIDTH / 7, - }, - day: { - fontSize: 16, - alignSelf: 'center', - }, - eventIndicatorFiller: { - marginTop: 3, - borderColor: 'transparent', - width: 4, - height: 4, - borderRadius: 2, - }, - eventIndicator: { - backgroundColor: '#cccccc', - }, - dayCircleFiller: { - justifyContent: 'center', - backgroundColor: 'transparent', - width: 28, - height: 28, - borderRadius: 14, - }, - currentDayCircle: { - backgroundColor: 'red', - }, - currentDayText: { - color: 'red', - }, - selectedDayCircle: { - backgroundColor: 'black', - }, - hasEventCircle: { - }, - hasEventDaySelectedCircle: { - }, - hasEventText: { - }, - selectedDayText: { - color: 'white', - fontWeight: 'bold', - }, - weekendDayText: { - color: '#cccccc', - }, + calendarContainer: { + backgroundColor: '#f7f7f7', + }, + calendarControls: { + flexDirection: 'row', + }, + controlButton: {}, + controlButtonText: { + margin: 10, + fontSize: 15, + }, + title: { + flex: 1, + margin: 10, + }, + titleText: { + textAlign: 'center', + fontSize: 15, + }, + calendarHeading: { + flexDirection: 'row', + borderTopWidth: 1, + borderBottomWidth: 1, + }, + dayHeading: { + flex: 1, + fontSize: 15, + textAlign: 'center', + marginVertical: 5, + }, + weekendHeading: { + flex: 1, + fontSize: 15, + textAlign: 'center', + marginVertical: 5, + color: '#cccccc', + }, + weekRow: { + flexDirection: 'row', + }, + weekendDayButton: { + backgroundColor: '#fafafa', + }, + dayButton: { + alignItems: 'center', + padding: 5, + borderTopWidth: 1, + borderTopColor: '#e9e9e9', + }, + dayButtonFiller: { + padding: 5 + }, + day: { + fontSize: 16, + alignSelf: 'center', + }, + eventIndicatorFiller: { + marginTop: 3, + borderColor: 'transparent', + width: 4, + height: 4, + borderRadius: 2, + }, + eventIndicator: { + backgroundColor: '#cccccc', + }, + dayCircleFiller: { + justifyContent: 'center', + backgroundColor: 'transparent', + width: 28, + height: 28, + borderRadius: 14, + }, + currentDayCircle: { + backgroundColor: 'red', + }, + currentDayText: { + color: 'red', + }, + selectedDayCircle: { + backgroundColor: 'black', + }, + hasEventCircle: {}, + hasEventDaySelectedCircle: {}, + hasEventText: {}, + selectedDayText: { + color: 'white', + fontWeight: 'bold', + }, + weekendDayText: { + color: '#cccccc', + }, }); export default styles; From 8668ba088dbc9d3a84aa80a1812d365a3967f526 Mon Sep 17 00:00:00 2001 From: "benjamin.berthelemy" Date: Tue, 6 Jun 2017 09:57:11 +0200 Subject: [PATCH 2/2] using view instead of text for buttons to make it work on Android too --- components/Calendar.js | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/components/Calendar.js b/components/Calendar.js index 87372f3..97f027d 100644 --- a/components/Calendar.js +++ b/components/Calendar.js @@ -328,6 +328,26 @@ export default class Calendar extends Component { renderTopBar() { let localizedMonth = this.props.monthNames[this.state.currentMoment.month()]; + const left = typeof prevButtonText === "string" + ? ( + + {this.props.prevButtonText} + + ) : ( + + {this.props.prevButtonText} + + ); + const right = typeof nextButtonText === "string" + ? ( + + {this.props.nextButtonText} + + ) : ( + + {this.props.nextButtonText} + + ); return this.props.showControls ? ( @@ -336,9 +356,7 @@ export default class Calendar extends Component { style={[styles.controlButton, this.props.customStyle.controlButton]} onPress={this.onPrev} > - - {this.props.prevButtonText} - + {left} this.props.onTitlePress && this.props.onTitlePress()} @@ -351,9 +369,7 @@ export default class Calendar extends Component { style={[styles.controlButton, this.props.customStyle.controlButton]} onPress={this.onNext} > - - {this.props.nextButtonText} - + {right} ) @@ -390,7 +406,8 @@ export default class Calendar extends Component { ) : ( - this._calendar = calendar} onLayout={(e) => this.setState({width: e.nativeEvent.layout.width})}> + this._calendar = calendar} + onLayout={(e) => this.setState({width: e.nativeEvent.layout.width})}> {calendarDates.map((date) => this.renderCalendarView(this.props.calendarFormat, moment(date), eventDatesMap))} );