Skip to content

Commit f357f3c

Browse files
committed
Merge branch 'master' of github.com:wix/react-native-calendars into release
2 parents 86f4389 + 9b52caf commit f357f3c

File tree

30 files changed

+684
-827
lines changed

30 files changed

+684
-827
lines changed

CHANGELOG.md

Lines changed: 156 additions & 9 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,8 @@ An advanced `Agenda` component that can display interactive listings for calenda
558558
return <View />;
559559
}}
560560
// Override inner list with a custom implemented component
561-
renderList={(listProps) => {
562-
return <MyCustomList {...listProps} />
561+
renderList={listProps => {
562+
return <MyCustomList {...listProps} />;
563563
}}
564564
// Specify what should be rendered instead of ActivityIndicator
565565
renderEmptyData={() => {

docsRNC/docs/Calendar.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,9 @@ Whether to hide the arrows
132132

133133
### arrowsHitSlop
134134

135-
Left & Right arrows. Additional distance outside of the buttons in which a press is detected, default: 20
135+
Left & Right arrows. Additional distance outside of the buttons in which a press is detected, default: 20
136136
<span style={{color: 'grey'}}>null | Insets | number</span>
137+
137138
### disableArrowLeft
138139

139140
Whether to disable the left arrow

docsRNC/docs/testing.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## Testing Calendars
2+
3+
Each component receives a testID as a prop and pass to internal elements by concatenating the testID with the element type/data.
4+
5+
For instance, The `Calendar` component will concatenate a given testID to each `Day` element it renders with its date.
6+
So each Day element's testID will be in the following format `${testID}.day_${date_string}`.
7+
8+
For example, if you'll pass to `Calendar` a testID called `myCalendar`, the day element representing the 2022-08-21 will have `myCalendar.day_2022-08-21` as testID.
9+
10+
Follow the components testIDs guidelines to learn how to query them in your tests
11+
12+
### Calendar
13+
14+
| Element | Format | Example |
15+
| -------------- | ------------------------------------- | -------------------------------------------------------- |
16+
| Main Container | `${testID}` | `myCalendar` |
17+
| Day | `${testID}.day_${date_string}` | `myCalendar.day_2022-08-21`, `myCalendar.day_2022-07-15` |
18+
| Header | `${testID}.header` | `myCalendar.header` |
19+
| Week Numbers | `${testID}.weekNumber_${weekNumber}`} | `myCalendar.weekNumber_27` |
20+
21+
### CalendarList
22+
23+
| Element | Format | Example |
24+
| -------------- | --------------------------------- | ----------------------------- |
25+
| Main Container | `${testID}` | `myCalendarList` |
26+
| Calendar Item | `${testID}.item_${year}-{month}`} | `myCalendarList.item_2022-07` |
27+
| Static Header | `${testID}.staticHeader`} | `myCalendarList.staticHeader` |
28+
29+
### Header
30+
31+
| Element | Format | Example |
32+
| -------------- | ---------------------- | ----------------------------- |
33+
| Main Container | `${testID}` | `myCalendarHeader` |
34+
| Header Title | `${testID}.title` | `myCalendarHeader.title` |
35+
| Day Names | `${testID}.dayNames` | `myCalendarHeader.dayNames` |
36+
| Left Arrow | `${testID}.leftArrow` | `myCalendarHeader.leftArrow` |
37+
| Right Arrow | `${testID}.rightArrow` | `myCalendarHeader.rightArrow` |
38+
| Loader | `${testID}.loader` | `myCalendarHeader.loader` |
39+
40+
### ExpandableCalendar
41+
42+
| Element | Format | Example |
43+
| -------------------- | ------------------------------- | ------------------------------------------ |
44+
| Main Container | `${testID}` | `myExpandableCalendar` |
45+
| Left Arrow | `${testID}.leftArrow` | `myExpandableCalendar.leftArrow` |
46+
| Right Arrow | `${testID}.rightArrow` | `myExpandableCalendar.rightArrow` |
47+
| Knob | `${testID}.knob` | `myExpandableCalendar.knob` |
48+
| Expandable Container | `${testID}.expandableContainer` | `myExpandableCalendar.expandableContainer` |
49+
| Week Calendar | `${testID}.weekCalendar` | `myExpandableCalendar.weekCalendar` |
50+
| Calendar List | `${testID}.calendarList` | `myExpandableCalendar.calendarList` |
51+
52+
### WeekCalendar
53+
54+
| Element | Format | Example |
55+
| -------------- | ------------------------------ | ------------------------------- |
56+
| Main Container | `${testID}` | `myWeekCalendar` |
57+
| Day | `${testID}.day_${date_string}` | `myWeekCalendar.day_2022-08-21` |
58+
59+
## Notes
60+
61+
Some components render others as internal components and their testIDs are based on the main parent id.
62+
For instance, if you'll pass `myExpandableCalendar` to ExpandableCalendar testID.
63+
In order to query a Day element, you'll need to go though all the render hierarchy's testIDs.
64+
65+
In this case. ExpandableCalendar -> CalendarList -> Calendar -> Day.
66+
And the testID for the Day element will be `myExpandableCalendar.calendarList.item_${year}-${month}.day_${date_string}`.

example/src/screens/calendarListScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const CalendarListScreen = (props: Props) => {
3535
}
3636
};
3737
}, [selected]);
38-
38+
3939
const onDayPress = useCallback((day: DateData) => {
4040
setSelected(day.dateString);
4141
}, []);

example/src/screens/calendarPlaygroundScreen.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ const NewCalendarScreen = () => {
139139

140140
const periodWithDotsMarks = useMemo(() => {
141141
return {
142+
[getDate(-3)]: {marked: true, dotColor: 'white', startingDay: true, endingDay: true, color: '#50cebb', textColor: 'white'},
142143
[INITIAL_DATE]: {marked: true, dotColor: '#50cebb'},
143144
[getDate(1)]: {disabled: true, marked: true, dotColor: '#50cebb'},
144145
[getDate(2)]: {startingDay: true, color: '#50cebb', textColor: 'white'},

example/src/screens/calendarScreen.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ const CalendarScreen = () => {
397397
},
398398
[getNewSelectedDate]
399399
);
400-
400+
401401
const onPressArrowRight = useCallback(
402402
(add, month) => {
403403
const newDate = getNewSelectedDate(month, true);
@@ -445,7 +445,7 @@ const CalendarScreen = () => {
445445
const renderCalendarWithCustomHeader = () => {
446446
const CustomHeader = React.forwardRef((props, ref) => {
447447
customHeaderProps.current = props;
448-
448+
449449
return (
450450
// @ts-expect-error
451451
<View ref={ref} {...props} style={styles.customHeader}>
@@ -565,8 +565,8 @@ const styles = StyleSheet.create({
565565
padding: 8
566566
},
567567
customTitleContainer: {
568-
flexDirection: 'row',
569-
alignItems: 'center',
568+
flexDirection: 'row',
569+
alignItems: 'center',
570570
padding: 10
571571
},
572572
customTitle: {

src/agenda/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export default class Agenda extends Component<AgendaProps, State> {
140140

141141
componentDidUpdate(prevProps: AgendaProps, prevState: State) {
142142
const newSelectedDate = this.getSelectedDate(this.props.selected);
143-
143+
144144
if (!sameDate(newSelectedDate, prevState.selectedDay)) {
145145
const prevSelectedDate = this.getSelectedDate(prevProps.selected);
146146
if (!sameDate(newSelectedDate, prevSelectedDate)) {
@@ -188,7 +188,7 @@ export default class Agenda extends Component<AgendaProps, State> {
188188

189189
enableCalendarScrolling(enable = true) {
190190
this.setState({calendarScrollable: enable});
191-
191+
192192
this.props.onCalendarToggled?.(enable);
193193

194194
// Enlarge calendarOffset here as a workaround on iOS to force repaint.
@@ -325,7 +325,7 @@ export default class Agenda extends Component<AgendaProps, State> {
325325
onDayChange = (day: XDate) => {
326326
const withAnimation = sameMonth(day, this.state.selectedDay);
327327
this.calendar?.current?.scrollToDay(day, this.calendarOffset(), withAnimation);
328-
328+
329329
this.setState({selectedDay: day});
330330

331331
this.props.onDayChange?.(xdateToData(day));
@@ -391,9 +391,9 @@ export default class Agenda extends Component<AgendaProps, State> {
391391

392392
renderWeekDaysNames = () => {
393393
return (
394-
<WeekDaysNames
395-
firstDay={this.props.firstDay}
396-
style={this.style.dayHeader}
394+
<WeekDaysNames
395+
firstDay={this.props.firstDay}
396+
style={this.style.dayHeader}
397397
/>
398398
);
399399
};

src/agenda/reservation-list/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ class ReservationList extends Component<ReservationListProps, State> {
123123
}
124124

125125
updateReservations(props: ReservationListProps) {
126-
const {selectedDay} = props;
126+
const {selectedDay, showOnlySelectedDayItems} = props;
127127
const reservations = this.getReservations(props);
128128

129-
if (this.list && !sameDate(selectedDay, this.selectedDay)) {
129+
if (!showOnlySelectedDayItems && this.list && !sameDate(selectedDay, this.selectedDay)) {
130130
let scrollPosition = 0;
131131
for (let i = 0; i < reservations.scrollPosition; i++) {
132132
scrollPosition += this.heights[i] || 0;

src/calendar-list/index.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ import React, {forwardRef, useImperativeHandle, useRef, useEffect, useState, use
66
import {FlatList, View, ViewStyle, FlatListProps} from 'react-native';
77

88
import {extractHeaderProps, extractCalendarProps} from '../componentUpdater';
9-
import {xdateToData, parseDate} from '../interface';
9+
import {xdateToData, parseDate, toMarkingFormat} from '../interface';
1010
import {page, sameDate, sameMonth} from '../dateutils';
1111
import constants from '../commons/constants';
1212
import {useDidUpdate} from '../hooks';
13-
// @ts-expect-error
14-
import {STATIC_HEADER} from '../testIDs';
1513
import styleConstructor from './style';
1614
import Calendar, {CalendarProps} from '../calendar';
1715
import CalendarListItem from './item';
@@ -102,7 +100,7 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
102100
onEndReachedThreshold,
103101
onEndReached
104102
} = props;
105-
103+
106104
const calendarProps = extractCalendarProps(props);
107105
const headerProps = extractHeaderProps(props);
108106
const calendarSize = horizontal ? calendarWidth : calendarHeight;
@@ -133,8 +131,8 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
133131
}, [propsStyle]);
134132

135133
const initialDateIndex = useMemo(() => {
136-
return findIndex(items, function(item) {
137-
return item.toString() === initialDate.current?.toString();
134+
return findIndex(items, function(item) {
135+
return item.toString() === initialDate.current?.toString();
138136
});
139137
}, [items]);
140138

@@ -180,7 +178,7 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
180178
const scrollTo = parseDate(date);
181179
const diffMonths = Math.round(initialDate?.current?.clone().setDate(1).diffMonths(scrollTo?.clone().setDate(1)));
182180
const scrollAmount = calendarSize * pastScrollRange + diffMonths * calendarSize;
183-
181+
184182
if (scrollAmount !== 0) {
185183
// @ts-expect-error
186184
list?.current?.scrollToOffset({offset: scrollAmount, animated: animateScroll});
@@ -196,8 +194,8 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
196194
setCurrentMonth(day);
197195
}, [currentMonth, scrollToMonth]);
198196

199-
const getMarkedDatesForItem = useCallback((item?: XDate) => {
200-
if (markedDates && item) {
197+
const getMarkedDatesForItem = useCallback((item?: XDate) => {
198+
if (markedDates && item) {
201199
for (const [key, _] of Object.entries(markedDates)) {
202200
if (sameMonth(new XDate(key), new XDate(item))) {
203201
return markedDates;
@@ -224,13 +222,16 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
224222
return false;
225223
}, [currentMonth]);
226224

227-
const renderItem = useCallback(({item}: any) => {
225+
const renderItem = useCallback(({item}: {item: XDate}) => {
226+
const dateString = toMarkingFormat(item);
227+
const [year, month] = dateString.split('-');
228+
const testId = `${testID}.item_${year}-${month}`;
228229
return (
229230
<CalendarListItem
230231
{...calendarProps}
232+
testID={testId}
231233
markedDates={getMarkedDatesForItem(item)}
232234
item={item}
233-
testID={`${testID}_${item}`}
234235
style={calendarStyle}
235236
// @ts-expect-error - type mismatch - ScrollView's 'horizontal' is nullable
236237
horizontal={horizontal}
@@ -247,7 +248,7 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
247248
return (
248249
<CalendarHeader
249250
{...headerProps}
250-
testID={STATIC_HEADER}
251+
testID={`${testID}.staticHeader`}
251252
style={staticHeaderStyle}
252253
month={currentMonth}
253254
addMonth={addMonth}
@@ -273,7 +274,7 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
273274
}, []);
274275

275276
const viewabilityConfigCallbackPairs = useRef([
276-
{
277+
{
277278
viewabilityConfig: viewabilityConfig.current,
278279
onViewableItemsChanged
279280
},
@@ -291,7 +292,7 @@ const CalendarList = (props: CalendarListProps, ref: any) => {
291292
renderItem={renderItem}
292293
getItemLayout={getItemLayout}
293294
initialNumToRender={range.current}
294-
initialScrollIndex={initialDateIndex}
295+
initialScrollIndex={initialDateIndex}
295296
viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current}
296297
testID={testID}
297298
onLayout={onLayout}

0 commit comments

Comments
 (0)