Skip to content

Commit a408d86

Browse files
committed
Merge remote-tracking branch 'origin' into release
2 parents 4f5548c + 97c5541 commit a408d86

File tree

5 files changed

+50
-23
lines changed

5 files changed

+50
-23
lines changed

src/calendar-list/index.tsx

+15-2
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,23 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
101101
/** FlatList props */
102102
contentContainerStyle,
103103
onEndReachedThreshold,
104-
onEndReached
104+
onEndReached,
105+
onHeaderLayout
105106
} = props;
106107

107108
const calendarProps = extractCalendarProps(props);
108109
const headerProps = extractHeaderProps(props);
109110
const calendarSize = horizontal ? calendarWidth : calendarHeight;
111+
const shouldUseStaticHeader = staticHeader && horizontal;
110112

111113
const [currentMonth, setCurrentMonth] = useState(parseDate(current));
112114

113115
const shouldUseAndroidRTLFix = useMemo(() => constants.isAndroidRTL && horizontal, [horizontal]);
116+
/**
117+
* we render a lot of months in the calendar list and we need to measure the header only once
118+
* so we use this ref to limit the header measurement to the first render
119+
*/
120+
const shouldMeasureHeader = useRef(true);
114121

115122
const style = useRef(styleConstructor(theme));
116123
const list = useRef();
@@ -237,6 +244,8 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
237244
const dateString = toMarkingFormat(item);
238245
const [year, month] = dateString.split('-');
239246
const testId = `${testID}.item_${year}-${month}`;
247+
const onHeaderLayoutToPass = shouldMeasureHeader.current ? onHeaderLayout : undefined;
248+
shouldMeasureHeader.current = false;
240249
return (
241250
<CalendarListItem
242251
{...calendarProps}
@@ -250,12 +259,15 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
250259
calendarHeight={calendarHeight}
251260
scrollToMonth={scrollToMonth}
252261
visible={isDateInRange(item)}
262+
onHeaderLayout={onHeaderLayoutToPass}
253263
/>
254264
);
255265
}, [horizontal, calendarStyle, calendarWidth, testID, getMarkedDatesForItem, isDateInRange, calendarProps]);
256266

257267
const renderStaticHeader = () => {
258-
if (staticHeader && horizontal) {
268+
if (shouldUseStaticHeader) {
269+
const onHeaderLayoutToPass = shouldMeasureHeader.current ? onHeaderLayout : undefined;
270+
shouldMeasureHeader.current = false;
259271
return (
260272
<CalendarHeader
261273
{...headerProps}
@@ -265,6 +277,7 @@ const CalendarList = (props: CalendarListProps & ContextProp, ref: any) => {
265277
addMonth={addMonth}
266278
accessibilityElementsHidden={true} // iOS
267279
importantForAccessibility={'no-hide-descendants'} // Android
280+
onHeaderLayout={onHeaderLayoutToPass}
268281
/>
269282
);
270283
}

src/calendar/header/index.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
ViewStyle,
1414
AccessibilityActionEvent,
1515
ColorValue,
16-
Insets
16+
Insets,
17+
ViewProps
1718
} from 'react-native';
1819
import {formatNumbers, weekDayNames} from '../../dateutils';
1920
import styleConstructor from './style';
@@ -73,6 +74,8 @@ export interface CalendarHeaderProps {
7374
numberOfDays?: number;
7475
/** Left inset for the timeline calendar header. Default = 72 */
7576
timelineLeftInset?: number;
77+
/** Callback for header onLayout */
78+
onHeaderLayout?: ViewProps['onLayout'];
7679
}
7780

7881
const accessibilityActions = [
@@ -107,7 +110,8 @@ const CalendarHeader = forwardRef((props: CalendarHeaderProps, ref) => {
107110
importantForAccessibility,
108111
numberOfDays,
109112
current = '',
110-
timelineLeftInset
113+
timelineLeftInset,
114+
onHeaderLayout
111115
} = props;
112116

113117
const numberOfDaysCondition = useMemo(() => {
@@ -289,6 +293,7 @@ const CalendarHeader = forwardRef((props: CalendarHeaderProps, ref) => {
289293
onAccessibilityAction={onAccessibilityAction}
290294
accessibilityElementsHidden={accessibilityElementsHidden} // iOS
291295
importantForAccessibility={importantForAccessibility} // Android
296+
onLayout={onHeaderLayout}
292297
>
293298
<View style={headerStyle}>
294299
{_renderArrow('left')}

src/componentUpdater.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ export function extractHeaderProps(props: CalendarProps) {
114114
numberOfDays,
115115
current,
116116
timelineLeftInset,
117-
testID
117+
testID,
118+
onHeaderLayout
118119
} = props;
119120

120121
const headerProps = {
@@ -139,7 +140,8 @@ export function extractHeaderProps(props: CalendarProps) {
139140
numberOfDays,
140141
current,
141142
timelineLeftInset,
142-
testID
143+
testID,
144+
onHeaderLayout
143145
};
144146

145147
return headerProps;

src/expandableCalendar/index.tsx

+24-15
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ import {
1616
ImageSourcePropType,
1717
GestureResponderEvent,
1818
PanResponderGestureState,
19-
TouchableOpacity
19+
TouchableOpacity,
20+
type LayoutChangeEvent
2021
} from 'react-native';
2122

2223
import {page} from '../dateutils';
2324
import {parseDate, toMarkingFormat} from '../interface';
2425
import {DateData, Direction} from '../types';
25-
import styleConstructor, {HEADER_HEIGHT, KNOB_CONTAINER_HEIGHT} from './style';
26+
import styleConstructor, {KNOB_CONTAINER_HEIGHT} from './style';
2627
import WeekDaysNames from '../commons/WeekDaysNames';
2728
import Calendar from '../calendar';
2829
import CalendarList, {CalendarListProps} from '../calendar-list';
@@ -38,7 +39,6 @@ export enum Positions {
3839
}
3940
const SPEED = 20;
4041
const BOUNCINESS = 6;
41-
const CLOSED_HEIGHT = 120; // header + 1 week
4242
const WEEK_HEIGHT = 46;
4343
const DAY_NAMES_PADDING = 24;
4444
const PAN_GESTURE_THRESHOLD = 30;
@@ -126,6 +126,10 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
126126
} = props;
127127

128128
const [screenReaderEnabled, setScreenReaderEnabled] = useState(false);
129+
const [headerHeight, setHeaderHeight] = useState(0);
130+
const onHeaderLayout = useCallback(({nativeEvent: {layout: {height}}}: LayoutChangeEvent) => {
131+
setHeaderHeight(height);
132+
}, []);
129133

130134
/** Date */
131135

@@ -175,20 +179,24 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
175179
if (!horizontal) {
176180
return Math.max(constants.screenHeight, constants.screenWidth);
177181
}
178-
return CLOSED_HEIGHT + (WEEK_HEIGHT * (numberOfWeeks.current - 1)) + (hideKnob ? 12 : KNOB_CONTAINER_HEIGHT) + (constants.isAndroid ? 3 : 0);
182+
return headerHeight + (WEEK_HEIGHT * (numberOfWeeks.current)) + (hideKnob ? 0 : KNOB_CONTAINER_HEIGHT);
179183
};
180184
const openHeight = useRef(getOpenHeight());
181-
const closedHeight = useMemo(() => CLOSED_HEIGHT + (hideKnob || Number(numberOfDays) > 1 ? 0 : KNOB_CONTAINER_HEIGHT), [numberOfDays, hideKnob]);
185+
const closedHeight = useMemo(() => headerHeight + WEEK_HEIGHT + (hideKnob || Number(numberOfDays) > 1 ? 0 : KNOB_CONTAINER_HEIGHT), [numberOfDays, hideKnob, headerHeight]);
182186
const startHeight = useMemo(() => isOpen ? openHeight.current : closedHeight, [closedHeight, isOpen]);
183187
const _height = useRef(startHeight);
184188
const deltaY = useMemo(() => new Animated.Value(startHeight), [startHeight]);
185-
const headerDeltaY = useRef(new Animated.Value(isOpen ? -HEADER_HEIGHT : 0));
189+
const headerDeltaY = useRef(new Animated.Value(isOpen ? -headerHeight : 0));
186190

187191
useEffect(() => {
188192
_height.current = startHeight;
189193
deltaY.setValue(startHeight);
190194
}, [startHeight]);
191195

196+
useEffect(() => {
197+
openHeight.current = getOpenHeight();
198+
} ,[headerHeight]);
199+
192200

193201
useEffect(() => {
194202
if (numberOfDays) {
@@ -209,7 +217,7 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
209217
const themeObject = Object.assign(headerStyleOverride, theme);
210218

211219
const _wrapperStyles = useRef({style: {height: startHeight}});
212-
const _headerStyles = {style: {top: isOpen ? -HEADER_HEIGHT : 0}};
220+
const _headerStyles = {style: {top: isOpen ? -headerHeight : 0}};
213221
const _weekCalendarStyles = {style: {opacity: isOpen ? 0 : 1}};
214222

215223
const shouldHideArrows = !horizontal ? true : hideArrows || false;
@@ -238,16 +246,16 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
238246
}, [calendarStyle]);
239247

240248
const animatedHeaderStyle = useMemo(() => {
241-
return [style.current.header, {height: HEADER_HEIGHT + 10, top: headerDeltaY.current}];
242-
}, [headerDeltaY.current]);
249+
return [style.current.header, {height: headerHeight, top: headerDeltaY.current}];
250+
}, [headerDeltaY.current, headerHeight]);
243251

244252
const weekCalendarStyle = useMemo(() => {
245-
return [style.current.weekContainer, isOpen ? style.current.hidden : style.current.visible];
246-
}, [isOpen]);
253+
return [style.current.weekContainer, isOpen ? style.current.hidden : style.current.visible, {top: headerHeight}];
254+
}, [isOpen, headerHeight]);
247255

248256
const containerStyle = useMemo(() => {
249-
return [allowShadow && style.current.containerShadow, propsStyle];
250-
}, [allowShadow, propsStyle]);
257+
return [allowShadow && style.current.containerShadow, propsStyle, headerHeight === 0 && style.current.hidden];
258+
}, [allowShadow, propsStyle, headerHeight]);
251259

252260
const wrapperStyle = useMemo(() => {
253261
return {height: deltaY};
@@ -343,7 +351,7 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
343351

344352
if (!horizontal) {
345353
// vertical CalenderList header
346-
_headerStyles.style.top = Math.min(Math.max(-gestureState.dy, -HEADER_HEIGHT), 0);
354+
_headerStyles.style.top = Math.min(Math.max(-gestureState.dy, -headerHeight), 0);
347355
} else {
348356
// horizontal Week view
349357
if (!isOpen) {
@@ -370,7 +378,7 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
370378
onPanResponderMove: handlePanResponderMove,
371379
onPanResponderRelease: handlePanResponderEnd,
372380
onPanResponderTerminate: handlePanResponderEnd
373-
}) : PanResponder.create({}), [numberOfDays, position]);
381+
}) : PanResponder.create({}), [numberOfDays, position, headerHeight]); // All the functions here rely on headerHeight directly or indirectly through refs that are updated in useEffect
374382

375383
/** Animated */
376384

@@ -572,6 +580,7 @@ const ExpandableCalendar = (props: ExpandableCalendarProps) => {
572580
horizontal={horizontal}
573581
firstDay={firstDay}
574582
calendarStyle={calendarStyle}
583+
onHeaderLayout={onHeaderLayout}
575584
{...others}
576585
current={date}
577586
theme={themeObject}

src/expandableCalendar/style.ts

-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {Theme} from '../types';
44
import constants from '../commons/constants';
55

66

7-
export const HEADER_HEIGHT = 68;
87
export const KNOB_CONTAINER_HEIGHT = 24;
98

109

@@ -96,7 +95,6 @@ export default function styleConstructor(theme: Theme = {}) {
9695
position: 'absolute',
9796
left: 0,
9897
right: 0,
99-
top: HEADER_HEIGHT + (constants.isAndroid ? 8 : 9), // align row on top of calendar's first row
10098
},
10199
hidden: {
102100
opacity: 0

0 commit comments

Comments
 (0)