Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make header can scroll along with columns #30

Merged
merged 5 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## Props
* **`events`** _(Array)_ - Events to display
* **`onEventPress`** _(Function)_ - Callback when event item is clicked
* **`numberOfDays`** _(Number)_ - Set number of days to show in view, can be `1`, `3`, `7`.
* **`numberOfDays`** _(Number)_ - Set number of days to show in view, can be `1`, `3`, `5`, `7`.
* **`formatDateHeader`** _(String)_ - Format for dates of header, default is `MMM D`
* **`selectedDate`** _(Date)_ - Intial date to show week/days in view
* **`onSwipeNext`** _(Function)_ - Callback when calendar is swiped to next week/days
Expand Down
Binary file modified images/gif.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 4 additions & 25 deletions src/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Text, View } from 'react-native';

import { getFormattedDate, getCurrentMonth, calculateDaysArray } from '../utils';

import { getFormattedDate, calculateDaysArray } from '../utils';
import styles from './Header.styles';

const getFontSizeHeader = (numberOfDays) => {
if (numberOfDays > 1) {
return 12;
}

return 16;
};

const getDayTextStyles = (numberOfDays) => {
const fontSize = numberOfDays === 7 ? 12 : 14;
return {
Expand Down Expand Up @@ -59,37 +50,25 @@ const Columns = ({
);
};

const Title = ({ numberOfDays, selectedDate, textColor }) => { // eslint-disable-line react/prop-types
return (
<View style={styles.title}>
<Text
style={{ color: textColor, fontSize: getFontSizeHeader(numberOfDays) }}
>
{getCurrentMonth(selectedDate)}
</Text>
</View>
);
};

const WeekViewHeader = ({
numberOfDays,
selectedDate,
initialDate,
formatDate,
style,
textColor,
}) => {
const columns = calculateDaysArray(selectedDate, numberOfDays);
const columns = calculateDaysArray(initialDate, numberOfDays);
return (
<View style={[styles.container, style]}>
<Title numberOfDays={numberOfDays} selectedDate={selectedDate} textColor={textColor} />
{columns && <Columns format={formatDate} columns={columns} numberOfDays={numberOfDays} textColor={textColor} />}
</View>
);
};

WeekViewHeader.propTypes = {
numberOfDays: PropTypes.oneOf([1, 3, 5, 7]).isRequired,
selectedDate: PropTypes.instanceOf(Date).isRequired,
initialDate: PropTypes.string.isRequired,
formatDate: PropTypes.string,
style: PropTypes.object,
textColor: PropTypes.string,
Expand Down
7 changes: 0 additions & 7 deletions src/Header/Header.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'space-between',
},
title: {
justifyContent: 'center',
alignItems: 'center',
width: 60,
borderColor: '#fff',
borderTopWidth: 1,
},
columns: {
flex: 1,
flexDirection: 'row',
Expand Down
39 changes: 39 additions & 0 deletions src/Title/Title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Text, View } from 'react-native';
import PropTypes from 'prop-types';

import { getCurrentMonth } from '../utils';
import styles from './Title.styles';

const getFontSizeHeader = (numberOfDays) => {
if (numberOfDays > 1) {
return 12;
}
return 16;
};

const Title = ({
style,
numberOfDays,
selectedDate,
textColor,
}) => {
return (
<View style={[styles.title, style]}>
<Text
style={{ color: textColor, fontSize: getFontSizeHeader(numberOfDays) }}
>
{getCurrentMonth(selectedDate)}
</Text>
</View>
);
};

Title.propTypes = {
numberOfDays: PropTypes.oneOf([1, 3, 5, 7]).isRequired,
selectedDate: PropTypes.instanceOf(Date).isRequired,
style: PropTypes.object,
textColor: PropTypes.string,
};

export default React.memo(Title);
13 changes: 13 additions & 0 deletions src/Title/Title.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
title: {
justifyContent: 'center',
alignItems: 'center',
width: 60,
borderColor: '#fff',
borderTopWidth: 1,
},
});

export default styles;
68 changes: 55 additions & 13 deletions src/WeekView/WeekView.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import {
View,
ScrollView,
Dimensions,
Animated,
} from 'react-native';
import moment from 'moment';
import memoizeOne from 'memoize-one';

import Event from '../Event/Event';
import Events from '../Events/Events';
import Header from '../Header/Header';
import Title from '../Title/Title';
import Times from '../Times/Times';
import styles from './WeekView.styles';
import {
Expand All @@ -31,19 +33,24 @@ export default class WeekView extends Component {
};
this.eventsGrid = null;
this.verticalAgenda = null;
setLocale(props.locale);

this.header = null;
this.pagesLeft = 2;
this.pagesRight = 2;
this.currentPageIndex = 2;
this.totalPages = this.pagesLeft + this.pagesRight + 1;
this.eventsGridScrollX = new Animated.Value(0);

setLocale(props.locale);
}

componentDidMount() {
requestAnimationFrame(() => {
this.eventsGrid.scrollTo({ y: 0, x: 2 * (SCREEN_WIDTH - 60), animated: false });
this.scrollToAgendaStart();
});
this.eventsGridScrollX.addListener((position) => {
this.header.scrollTo({ x: position.value, animated: false });
});
}

componentDidUpdate(prevprops) {
Expand All @@ -57,12 +64,8 @@ export default class WeekView extends Component {
this.eventsGrid.scrollTo({ y: 0, x: 2 * (SCREEN_WIDTH - 60), animated: false });
}

scrollToAgendaStart = () => {
if (this.verticalAgenda) {
const { startHour, hoursInDisplay } = this.props;
const startHeight = startHour * CONTAINER_HEIGHT / hoursInDisplay;
this.verticalAgenda.scrollTo({ y: startHeight, x: 0, animated: false });
}
componentWillUnmount() {
this.eventsGridScrollX.removeAllListeners();
}

calculateTimes = memoizeOne((hoursInDisplay) => {
Expand All @@ -79,6 +82,14 @@ export default class WeekView extends Component {
return times;
});

scrollToAgendaStart = () => {
if (this.verticalAgenda) {
const { startHour, hoursInDisplay } = this.props;
const startHeight = startHour * CONTAINER_HEIGHT / hoursInDisplay;
this.verticalAgenda.scrollTo({ y: startHeight, x: 0, animated: false });
}
}

scrollEnded = (event) => {
const { nativeEvent: { contentOffset, contentSize } } = event;
const { x: position } = contentOffset;
Expand Down Expand Up @@ -113,6 +124,10 @@ export default class WeekView extends Component {
this.verticalAgenda = ref;
}

headerRef = (ref) => {
this.header = ref;
};

calculatePagesDates = memoizeOne((currentMoment, numberOfDays) => {
const initialDates = [];
for (let i = -this.pagesLeft; i <= this.pagesRight; i += 1) {
Expand Down Expand Up @@ -176,14 +191,32 @@ export default class WeekView extends Component {
const eventsByDate = this.sortEventsByDate(events);
return (
<View style={styles.container}>
<View style={styles.header}>
<Header
<View style={styles.headerContainer}>
<Title
style={headerStyle}
textColor={headerTextColor}
formatDate={formatDateHeader}
selectedDate={currentMoment}
numberOfDays={numberOfDays}
selectedDate={currentMoment}
textColor={headerTextColor}
/>
<ScrollView
horizontal
pagingEnabled
scrollEnabled={false}
automaticallyAdjustContentInsets={false}
ref={this.headerRef}
>
{initialDates.map(date => (
<View key={date} style={styles.header}>
<Header
style={headerStyle}
textColor={headerTextColor}
formatDate={formatDateHeader}
initialDate={date}
numberOfDays={numberOfDays}
/>
</View>
))}
</ScrollView>
</View>
<ScrollView
ref={this.verticalAgendaRef}
Expand All @@ -195,6 +228,15 @@ export default class WeekView extends Component {
pagingEnabled
automaticallyAdjustContentInsets={false}
onMomentumScrollEnd={this.scrollEnded}
scrollEventThrottle={32}
onScroll={Animated.event([{
nativeEvent: {
contentOffset: {
x: this.eventsGridScrollX,
},
},
},
], { useNativeDriver: false })}
ref={this.eventsGridRef}
>
{initialDates.map(date => (
Expand Down
9 changes: 8 additions & 1 deletion src/WeekView/WeekView.styles.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { StyleSheet } from 'react-native';
import { StyleSheet, Dimensions } from 'react-native';

const { width: SCREEN_WIDTH } = Dimensions.get('window');

const styles = StyleSheet.create({
container: {
Expand All @@ -7,10 +9,15 @@ const styles = StyleSheet.create({
scrollViewContent: {
flexDirection: 'row',
},
headerContainer: {
flexDirection: 'row',
},
header: {
flex: 1,
height: 50,
justifyContent: 'center',
alignItems: 'center',
width: SCREEN_WIDTH - 60,
},
});

Expand Down
3 changes: 1 addition & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,5 @@ export const calculateDaysArray = (date, numberOfDays) => {
const currentDate = moment(date).add(i, 'd');
dates.push(currentDate);
}

return dates;
}
};