Skip to content

Commit dcdb115

Browse files
Calendar - add 'disabledByWeekDays' prop (#2557)
* Calendar - add 'disabledByWeekDays' prop + cleaning props * Update src/calendar/header/index.tsx Co-authored-by: Nitzan Yizhar <[email protected]> * remove prop description fix --------- Co-authored-by: Nitzan Yizhar <[email protected]>
1 parent 8d924e7 commit dcdb115

File tree

6 files changed

+68
-57
lines changed

6 files changed

+68
-57
lines changed

example/src/screens/calendarScreen.tsx

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const CalendarScreen = () => {
3737
const renderCalendarWithSelectableDate = () => {
3838
return (
3939
<Fragment>
40-
<Text style={styles.text}>Calendar with selectable date</Text>
40+
<Text style={styles.text}>Selectable date</Text>
4141
<Calendar
4242
testID={testIDs.calendars.FIRST}
4343
enableSwipeMonths
@@ -50,19 +50,19 @@ const CalendarScreen = () => {
5050
);
5151
};
5252

53-
const renderCalendarWithWeekNumbers = () => {
53+
const renderCalendarWithWeekNumbersAndSpinner = () => {
5454
return (
5555
<Fragment>
56-
<Text style={styles.text}>Calendar with week numbers</Text>
57-
<Calendar style={styles.calendar} hideExtraDays showWeekNumbers/>
56+
<Text style={styles.text}>Week numbers and spinner</Text>
57+
<Calendar style={styles.calendar} hideExtraDays showWeekNumbers displayLoadingIndicator/>
5858
</Fragment>
5959
);
6060
};
6161

6262
const renderCalendarWithMinAndMaxDates = () => {
6363
return (
6464
<Fragment>
65-
<Text style={styles.text}>Calendar with min and max dates</Text>
65+
<Text style={styles.text}>Min and max dates</Text>
6666
<Calendar
6767
style={styles.calendar}
6868
hideExtraDays
@@ -78,7 +78,7 @@ const CalendarScreen = () => {
7878
const renderCalendarWithMarkedDatesAndHiddenArrows = () => {
7979
return (
8080
<Fragment>
81-
<Text style={styles.text}>Calendar with marked dates and hidden arrows</Text>
81+
<Text style={styles.text}>Marked dates and hidden arrows</Text>
8282
<Calendar
8383
style={styles.calendar}
8484
current={INITIAL_DATE}
@@ -92,7 +92,6 @@ const CalendarScreen = () => {
9292
[getDate(10)]: {disabled: true, activeOpacity: 0, disableTouchEvent: false}
9393
}}
9494
hideArrows={true}
95-
// disabledByDefault={true}
9695
/>
9796
</Fragment>
9897
);
@@ -101,7 +100,7 @@ const CalendarScreen = () => {
101100
const renderCalendarWithMultiDotMarking = () => {
102101
return (
103102
<Fragment>
104-
<Text style={styles.text}>Calendar with multi-dot marking</Text>
103+
<Text style={styles.text}>Multi-dot marking</Text>
105104
<Calendar
106105
style={styles.calendar}
107106
current={INITIAL_DATE}
@@ -127,10 +126,10 @@ const CalendarScreen = () => {
127126
);
128127
};
129128

130-
const renderCalendarWithPeriodMarkingAndSpinner = () => {
129+
const renderCalendarWithThemeAndDisabledDays = () => {
131130
return (
132131
<Fragment>
133-
<Text style={styles.text}>Calendar with period marking and spinner</Text>
132+
<Text style={styles.text}>Custom theme and disabled Wednesdays</Text>
134133
<Calendar
135134
// style={styles.calendar}
136135
current={INITIAL_DATE}
@@ -173,6 +172,9 @@ const CalendarScreen = () => {
173172
[getDate(26)]: {color: 'gray'},
174173
[getDate(27)]: {endingDay: true, color: 'gray'}
175174
}}
175+
disabledDaysIndexes={[3]}
176+
disabledByWeekDays={[3]}
177+
disableAllTouchEventsForDisabledDays
176178
/>
177179
</Fragment>
178180
);
@@ -181,7 +183,7 @@ const CalendarScreen = () => {
181183
const renderCalendarWithPeriodMarkingAndDotMarking = () => {
182184
return (
183185
<Fragment>
184-
<Text style={styles.text}>Calendar with period marking and dot marking</Text>
186+
<Text style={styles.text}>Marking and dot marking</Text>
185187
<Calendar
186188
current={INITIAL_DATE}
187189
minDate={getDate(-14)}
@@ -211,7 +213,6 @@ const CalendarScreen = () => {
211213
},
212214
[getDate(25)]: {inactive: true, disableTouchEvent: true}
213215
}}
214-
disabledDaysIndexes={[0, 6]}
215216
theme={{
216217
textInactiveColor: '#a68a9f',
217218
textSectionTitleDisabledColor: 'grey',
@@ -227,7 +228,7 @@ const CalendarScreen = () => {
227228
const renderCalendarWithMultiPeriodMarking = () => {
228229
return (
229230
<Fragment>
230-
<Text style={styles.text}>Calendar with multi-period marking</Text>
231+
<Text style={styles.text}>Multi-period marking</Text>
231232
<Calendar
232233
style={styles.calendar}
233234
current={INITIAL_DATE}
@@ -262,7 +263,7 @@ const CalendarScreen = () => {
262263
const renderCalendarWithCustomMarkingType = () => {
263264
return (
264265
<Fragment>
265-
<Text style={styles.text}>Custom calendar with custom marking type</Text>
266+
<Text style={styles.text}>Custom marking type</Text>
266267
<Calendar
267268
style={styles.calendar}
268269
hideExtraDays
@@ -360,7 +361,7 @@ const CalendarScreen = () => {
360361
const renderCalendarWithCustomDay = () => {
361362
return (
362363
<Fragment>
363-
<Text style={styles.text}>Calendar with custom day component</Text>
364+
<Text style={styles.text}>Custom day component</Text>
364365
<Calendar
365366
style={[styles.calendar, styles.customCalendar]}
366367
dayComponent={({date, state}) => {
@@ -416,7 +417,7 @@ const CalendarScreen = () => {
416417

417418
return (
418419
<Fragment>
419-
<Text style={styles.text}>Calendar with custom header title</Text>
420+
<Text style={styles.text}>Custom header title</Text>
420421
<Calendar
421422
style={styles.calendar}
422423
customHeaderTitle={CustomHeaderTitle}
@@ -464,7 +465,7 @@ const CalendarScreen = () => {
464465

465466
return (
466467
<Fragment>
467-
<Text style={styles.text}>Calendar with custom header component</Text>
468+
<Text style={styles.text}>Custom header component</Text>
468469
<Calendar
469470
initialDate={INITIAL_DATE}
470471
testID={testIDs.calendars.LAST}
@@ -478,7 +479,7 @@ const CalendarScreen = () => {
478479
const renderCalendarWithInactiveDays = () => {
479480
return (
480481
<Fragment>
481-
<Text style={styles.text}>Calendar with inactive days</Text>
482+
<Text style={styles.text}>Inactive days</Text>
482483
<Calendar
483484
style={styles.calendar}
484485
disableAllTouchEventsForInactiveDays
@@ -500,15 +501,15 @@ const CalendarScreen = () => {
500501
return (
501502
<Fragment>
502503
{renderCalendarWithSelectableDate()}
503-
{renderCalendarWithWeekNumbers()}
504+
{renderCalendarWithWeekNumbersAndSpinner()}
504505
{renderCalendarWithMinAndMaxDates()}
505506
{renderCalendarWithCustomDay()}
506507
{renderCalendarWithInactiveDays()}
507508
{renderCalendarWithCustomHeaderTitle()}
508509
{renderCalendarWithCustomHeader()}
509510
{renderCalendarWithMarkedDatesAndHiddenArrows()}
510511
{renderCalendarWithMultiDotMarking()}
511-
{renderCalendarWithPeriodMarkingAndSpinner()}
512+
{renderCalendarWithThemeAndDisabledDays()}
512513
{renderCalendarWithPeriodMarkingAndDotMarking()}
513514
{renderCalendarWithMultiPeriodMarking()}
514515
{renderCalendarWithCustomMarkingType()}

src/calendar/calendar.api.json

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
],
1212
"example": "https://github.com/wix/react-native-calendars/blob/master/example/src/screens/calendars.tsx",
1313
"props": [
14+
{
15+
"name": "testID",
16+
"type": "string",
17+
"description": "Test ID"
18+
},
1419
{
1520
"name": "theme",
1621
"type": "Theme",
@@ -46,6 +51,11 @@
4651
"type": "string",
4752
"description": "Maximum date that can be selected, dates after maxDate will be grayed out"
4853
},
54+
{
55+
"name": "allowSelectionOutOfRange",
56+
"type": "boolean",
57+
"description": "Whether to allow selection of dates before minDate or after maxDate"
58+
},
4959
{
5060
"name": "firstDay",
5161
"type": "number",
@@ -79,7 +89,7 @@
7989
{
8090
"name": "disableMonthChange",
8191
"type": "boolean",
82-
"description": "Whether to disable changing month when click on days of other months (when hideExtraDays is false)"
92+
"description": "Whether to disable changing month when click on days of other months (when hideExtraDays = false)"
8393
},
8494
{
8595
"name": "enableSwipeMonths",
@@ -92,9 +102,9 @@
92102
"description": "Whether to disable days by default"
93103
},
94104
{
95-
"name": "allowSelectionOutOfRange",
96-
"type": "boolean",
97-
"description": "Whether to allow selection of dates before minDate or after maxDate"
105+
"name": "disabledByWeekDays",
106+
"type": "number[]",
107+
"description": "Disable dates by days of the week (Sunday=0)"
98108
},
99109
{
100110
"name": "onDayPress",

src/calendar/day/basic/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,24 @@ import Marking, {MarkingProps} from '../marking';
88

99

1010
export interface BasicDayProps extends ViewProps {
11+
/** Theme object */
12+
theme?: Theme;
13+
/** The Day's state ('selected' | 'disabled' | 'inactive' | 'today' | '') */
1114
state?: DayState;
1215
/** The marking object */
1316
marking?: MarkingProps;
14-
/** Date marking style [dot/multi-dot/period/multi-period]. Default = 'dot' */
17+
/** Date marking style ('dot' | 'multi-dot' | 'period' | 'multi-period' | 'custom'). Default = 'dot' */
1518
markingType?: MarkingTypes;
16-
/** Theme object */
17-
theme?: Theme;
1819
/** onPress callback */
1920
onPress?: (date?: DateData) => void;
2021
/** onLongPress callback */
2122
onLongPress?: (date?: DateData) => void;
2223
/** The date to return from press callbacks */
2324
date?: string;
24-
25-
/** Disable all touch events for disabled days. can be override with disableTouchEvent in markedDates*/
25+
/** Disable all touch events for disabled days (can be override with disableTouchEvent in markedDates) */
2626
disableAllTouchEventsForDisabledDays?: boolean;
27-
/** Disable all touch events for inactive days. can be override with disableTouchEvent in markedDates*/
27+
/** Disable all touch events for inactive days (can be override with disableTouchEvent in markedDates) */
2828
disableAllTouchEventsForInactiveDays?: boolean;
29-
3029
/** Test ID */
3130
testID?: string;
3231
/** Accessibility label */

src/calendar/header/index.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ import styleConstructor from './style';
2020
import {Theme, Direction} from '../../types';
2121

2222
export interface CalendarHeaderProps {
23+
/** The current month presented in the calendar */
2324
month?: XDate;
25+
/** A callback for when a month is changed from the headers arrows */
2426
addMonth?: (num: number) => void;
25-
27+
28+
/** The current date presented */
29+
current?: string;
2630
/** Specify theme properties to override specific styles for calendar parts */
2731
theme?: Theme;
2832
/** If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday */
@@ -37,13 +41,13 @@ export interface CalendarHeaderProps {
3741
hideDayNames?: boolean;
3842
/** Hide month navigation arrows */
3943
hideArrows?: boolean;
40-
/** Replace default arrows with custom ones (direction can be 'left' or 'right') */
44+
/** Replace default arrows with custom ones (direction = 'left' | 'right') */
4145
renderArrow?: (direction: Direction) => ReactNode;
4246
/** Handler which gets executed when press arrow icon left. It receive a callback can go back month */
4347
onPressArrowLeft?: (method: () => void, month?: XDate) => void; //TODO: replace with string
4448
/** Handler which gets executed when press arrow icon right. It receive a callback can go next month */
4549
onPressArrowRight?: (method: () => void, month?: XDate) => void; //TODO: replace with string
46-
/** Left & Right arrows. Additional distance outside of the buttons in which a press is detected, default: 20 */
50+
/** Left & Right arrows. Additional distance outside of the buttons in which a press is detected. Default = 20 */
4751
arrowsHitSlop?: Insets | number;
4852
/** Disable left arrow */
4953
disableArrowLeft?: boolean;
@@ -55,18 +59,19 @@ export interface CalendarHeaderProps {
5559
renderHeader?: (date?: XDate) => ReactNode; //TODO: replace with string
5660
/** Replace default title with custom element */
5761
customHeaderTitle?: JSX.Element;
58-
59-
/** Provide aria-level for calendar heading for proper accessibility when used with web (react-native-web) */
60-
webAriaLevel?: number;
62+
/** Test ID */
6163
testID?: string;
64+
/** Specify style for header container element */
6265
style?: StyleProp<ViewStyle>;
66+
/** Provide aria-level for calendar heading for proper accessibility when used with web (react-native-web) */
67+
webAriaLevel?: number;
68+
/** whether the accessibility elements contained within this accessibility element are hidden (iOS only) */
6369
accessibilityElementsHidden?: boolean;
70+
/** controlling if a view fires accessibility events and if it is reported to accessibility services (Android only) */
6471
importantForAccessibility?: 'auto' | 'yes' | 'no' | 'no-hide-descendants';
65-
/** The number of days to present in the header */
72+
/** The number of days to present in the header (for example for Timeline display) */
6673
numberOfDays?: number;
67-
/** The current date presented */
68-
current?: string;
69-
/** Left inset for the timeline calendar header, default is 72 */
74+
/** Left inset for the timeline calendar header. Default = 72 */
7075
timelineLeftInset?: number;
7176
}
7277

src/calendar/index.tsx

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import React, {useRef, useState, useEffect, useCallback, useMemo} from 'react';
55
import {View, ViewStyle, StyleProp} from 'react-native';
66
// @ts-expect-error
77
import GestureRecognizer, {swipeDirections} from 'react-native-swipe-gestures';
8-
98
import constants from '../commons/constants';
109
import {page, isGTE, isLTE, sameMonth} from '../dateutils';
1110
import {xdateToData, parseDate, toMarkingFormat} from '../interface';
@@ -21,12 +20,6 @@ import BasicDay from './day/basic';
2120
export interface CalendarProps extends CalendarHeaderProps, DayProps {
2221
/** Specify theme properties to override specific styles for calendar parts */
2322
theme?: Theme;
24-
/** If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday */
25-
firstDay?: number;
26-
/** Display loading indicator */
27-
displayLoadingIndicator?: boolean;
28-
/** Show week numbers */
29-
showWeekNumbers?: boolean;
3023
/** Specify style for calendar container element */
3124
style?: StyleProp<ViewStyle>;
3225
/** Initially visible month */
@@ -37,6 +30,8 @@ export interface CalendarProps extends CalendarHeaderProps, DayProps {
3730
minDate?: string;
3831
/** Maximum date that can be selected, dates after maxDate will be grayed out */
3932
maxDate?: string;
33+
/** Allow selection of dates before minDate or after maxDate */
34+
allowSelectionOutOfRange?: boolean;
4035
/** Collection of dates that have to be marked */
4136
markedDates?: MarkedDates;
4237
/** Do not show days of other months in month page */
@@ -51,18 +46,20 @@ export interface CalendarProps extends CalendarHeaderProps, DayProps {
5146
onMonthChange?: (date: DateData) => void;
5247
/** Handler which gets executed when visible month changes in calendar */
5348
onVisibleMonthsChange?: (months: DateData[]) => void;
54-
/** Disables changing month when click on days of other months (when hideExtraDays is false) */
49+
/** Disables changing month when click on days of other months (when hideExtraDays = false) */
5550
disableMonthChange?: boolean;
5651
/** Enable the option to swipe between months */
5752
enableSwipeMonths?: boolean;
58-
/** Disable days by default */
59-
disabledByDefault?: boolean;
6053
/** Style passed to the header */
6154
headerStyle?: StyleProp<ViewStyle>;
6255
/** Allow rendering a totally custom header */
6356
customHeader?: any;
64-
/** Allow selection of dates before minDate or after maxDate */
65-
allowSelectionOutOfRange?: boolean;
57+
/** Disable days by default */
58+
disabledByDefault?: boolean;
59+
/** Disable dates by days of the week (Sunday=0) */
60+
disabledByWeekDays?: number[]
61+
/** Test ID */
62+
testID?: string;
6663
}
6764

6865
/**
@@ -301,9 +298,6 @@ Calendar.propTypes = {
301298
...CalendarHeader.propTypes,
302299
...Day.propTypes,
303300
theme: PropTypes.object,
304-
firstDay: PropTypes.number,
305-
displayLoadingIndicator: PropTypes.bool,
306-
showWeekNumbers: PropTypes.bool,
307301
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.number]),
308302
current: PropTypes.string,
309303
initialDate: PropTypes.string,

src/day-state-manager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const {toMarkingFormat} = require('./interface');
33

44

55
export function getState(day: XDate, current: XDate, props: any, disableDaySelection?: boolean) {
6-
const {minDate, maxDate, disabledByDefault, context} = props;
6+
const {minDate, maxDate, disabledByDefault, disabledByWeekDays, context} = props;
77
let state = '';
88

99
if (!disableDaySelection && ((context?.date ?? toMarkingFormat(current)) === toMarkingFormat(day))) {
@@ -16,6 +16,8 @@ export function getState(day: XDate, current: XDate, props: any, disableDaySelec
1616
state = 'disabled';
1717
} else if (!sameMonth(day, current)) {
1818
state = 'disabled';
19+
} else if (disabledByWeekDays && disabledByWeekDays.indexOf(day.getDay()) !== -1) {
20+
state = 'disabled';
1921
}
2022

2123
return state;

0 commit comments

Comments
 (0)