Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions docs-site/src/components/Examples/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import MonthDropdownShort from "../../examples/monthDropdownShort?raw";
import MonthYearDropdown from "../../examples/monthYearDropdown?raw";
import YearSelectDropdown from "../../examples/yearSelectDropdown?raw";
import Inline from "../../examples/inline?raw";
import InlineDisabled from "../../examples/disabledInline?raw";
import InlineVisible from "../../examples/inlineVisible?raw";
import OpenToDate from "../../examples/openToDate?raw";
import FixedCalendar from "../../examples/fixedCalendar?raw";
Expand Down Expand Up @@ -360,6 +361,10 @@ export default class exampleComponents extends React.Component {
title: "Inline version",
component: Inline,
},
{
title: "Disabled Inline version",
component: InlineDisabled,
},
{
title: "Button to show Inline version",
component: InlineVisible,
Expand Down
11 changes: 11 additions & 0 deletions docs-site/src/examples/disabledInline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
() => {
const [selectedDate, setSelectedDate] = useState(new Date());
return (
<DatePicker
selected={selectedDate}
onChange={(date) => setSelectedDate(date)}
inline
disabled
/>
);
};
19 changes: 17 additions & 2 deletions src/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
};

header = (date: Date = this.state.date): React.ReactElement[] => {
const disabled = this.props.disabled;
const startOfWeek = getStartOfWeek(
date,
this.props.locale,
Expand All @@ -477,7 +478,11 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
const dayNames: React.ReactElement[] = [];
if (this.props.showWeekNumbers) {
dayNames.push(
<div key="W" className="react-datepicker__day-name" role="columnheader">
<div
key="W"
className={`react-datepicker__day-name ${disabled ? "react-datepicker__day-name--disabled" : ""}`}
role="columnheader"
>
<span className="react-datepicker__sr-only">Week number</span>
<span aria-hidden="true">{this.props.weekLabel || "#"}</span>
</div>,
Expand All @@ -496,7 +501,11 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
<div
key={offset}
role="columnheader"
className={clsx("react-datepicker__day-name", weekDayClassName)}
className={clsx(
"react-datepicker__day-name",
weekDayClassName,
disabled ? "react-datepicker__day-name--disabled" : "",
)}
>
<span className="react-datepicker__sr-only">
{formatDate(day, "EEEE", this.props.locale)}
Expand Down Expand Up @@ -551,6 +560,9 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {

let allPrevDaysDisabled;
switch (true) {
case this.props.disabled:
allPrevDaysDisabled = true;
break;
case this.props.showMonthYearPicker:
allPrevDaysDisabled = yearDisabledBefore(this.state.date, this.props);
break;
Expand Down Expand Up @@ -662,6 +674,9 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {

let allNextDaysDisabled: boolean;
switch (true) {
case this.props.disabled:
allNextDaysDisabled = true;
break;
case this.props.showMonthYearPicker:
allNextDaysDisabled = yearDisabledAfter(this.state.date, this.props);
break;
Expand Down
39 changes: 34 additions & 5 deletions src/date_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,10 @@ export interface DateFilterOptions {
yearItemNumber?: number;
}

export type DateFilterOptionsWithDisabled = DateFilterOptions & {
disabled?: boolean;
};

/**
* Checks if a day is disabled.
*
Expand All @@ -745,8 +749,13 @@ export function isDayDisabled(
includeDates,
includeDateIntervals,
filterDate,
}: DateFilterOptions = {},
disabled,
}: DateFilterOptionsWithDisabled = {},
): boolean {
if (disabled) {
return true;
}

return (
isOutOfBounds(day, { minDate, maxDate }) ||
(excludeDates &&
Expand Down Expand Up @@ -898,11 +907,21 @@ export function isQuarterDisabled(
excludeDates,
includeDates,
filterDate,
disabled,
}: Pick<
DateFilterOptions,
"minDate" | "maxDate" | "excludeDates" | "includeDates" | "filterDate"
DateFilterOptionsWithDisabled,
| "minDate"
| "maxDate"
| "excludeDates"
| "includeDates"
| "filterDate"
| "disabled"
> = {},
): boolean {
if (disabled) {
return true;
}

return (
isOutOfBounds(quarter, { minDate, maxDate }) ||
excludeDates?.some((excludeDate) =>
Expand Down Expand Up @@ -941,11 +960,21 @@ export function isYearDisabled(
excludeDates,
includeDates,
filterDate,
disabled,
}: Pick<
DateFilterOptions,
"minDate" | "maxDate" | "excludeDates" | "includeDates" | "filterDate"
DateFilterOptionsWithDisabled,
| "minDate"
| "maxDate"
| "excludeDates"
| "includeDates"
| "filterDate"
| "disabled"
> = {},
): boolean {
if (disabled) {
return true;
}

const date = new Date(year, 0, 1);
return (
isOutOfBounds(date, {
Expand Down
6 changes: 4 additions & 2 deletions src/day.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
getDayOfWeekCode,
getStartOfWeek,
formatDate,
type DateFilterOptions,
type DateFilterOptionsWithDisabled,
type DateNumberType,
type Locale,
type HolidaysMap,
Expand All @@ -25,14 +25,15 @@ import {

interface DayProps
extends Pick<
DateFilterOptions,
DateFilterOptionsWithDisabled,
| "minDate"
| "maxDate"
| "excludeDates"
| "excludeDateIntervals"
| "includeDateIntervals"
| "includeDates"
| "filterDate"
| "disabled"
> {
ariaLabelPrefixWhenEnabled?: string;
ariaLabelPrefixWhenDisabled?: string;
Expand Down Expand Up @@ -210,6 +211,7 @@ export default class Day extends Component<DayProps> {
includeDateIntervals: this.props.includeDateIntervals,
includeDates: this.props.includeDates,
filterDate: this.props.filterDate,
disabled: this.props.disabled,
});

isExcluded = () =>
Expand Down
20 changes: 18 additions & 2 deletions src/month.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ export default class Month extends Component<MonthProps> {
includeDateIntervals: this.props.includeDateIntervals,
includeDates: this.props.includeDates,
filterDate: this.props.filterDate,
disabled: this.props.disabled,
});

isExcluded = (day: Date) =>
Expand Down Expand Up @@ -783,8 +784,17 @@ export default class Month extends Component<MonthProps> {
isDisabled: boolean;
labelDate: Date;
} => {
const { day, minDate, maxDate, excludeDates, includeDates } = this.props;
const { day, disabled, minDate, maxDate, excludeDates, includeDates } =
this.props;
const labelDate = setMonth(day, month);

if (disabled) {
return {
isDisabled: true,
labelDate: setMonth(day, month),
};
}

return {
isDisabled:
((minDate || maxDate || excludeDates || includeDates) &&
Expand Down Expand Up @@ -919,10 +929,16 @@ export default class Month extends Component<MonthProps> {
filterDate,
preSelection,
disabledKeyboardNavigation,
disabled,
} = this.props;

const isDisabled =
(minDate || maxDate || excludeDates || includeDates || filterDate) &&
(minDate ||
maxDate ||
excludeDates ||
includeDates ||
filterDate ||
disabled) &&
isQuarterDisabled(setQuarter(day, q), this.props);

return clsx(
Expand Down
5 changes: 5 additions & 0 deletions src/stylesheets/datepicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ h2.react-datepicker__current-month {
line-height: $datepicker__item-size;
text-align: center;
margin: $datepicker__day-margin;

&--disabled {
cursor: default;
color: $datepicker__muted-color;
}
}

.react-datepicker__day,
Expand Down
72 changes: 72 additions & 0 deletions src/test/datepicker_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4883,4 +4883,76 @@ describe("DatePicker", () => {
expect(eventObject.target?.value).toBe(inputValue);
});
});

describe("disabled", () => {
const validateAllDisabled = (container: HTMLElement, className: string) => {
const allDays = Array.from(container.querySelectorAll(`.${className}`));
expect(allDays.length).toBeGreaterThan(0);
expect(
allDays.every((day) =>
day.classList.contains(`${className}--disabled`),
),
).toBe(true);
};

const validateNonExistence = (
container: HTMLElement,
querySelector: string,
) => {
const element = container.querySelector(querySelector);
expect(element).toBeFalsy();
};

it("should disable all days and headers in DatePicker when disabled prop is true", () => {
const { container } = render(<DatePicker inline disabled />);

validateAllDisabled(container, "react-datepicker__day");
validateAllDisabled(container, "react-datepicker__day-name");
validateNonExistence(container, "react-datepicker__navigation");
});

it("should disable all days and headers in DatePicker Range Selector when disabled prop is true", () => {
const { container } = render(<DatePicker selectsRange inline disabled />);

validateAllDisabled(container, "react-datepicker__day");
validateAllDisabled(container, "react-datepicker__day-name");
validateNonExistence(container, "react-datepicker__navigation");
});

it("should disable all days and headers in MonthPicker when disabled prop is true", () => {
const { container } = render(
<DatePicker showMonthYearPicker inline disabled />,
);

validateAllDisabled(container, "react-datepicker__month-text");
validateNonExistence(container, "react-datepicker__navigation");
});

it("should disable all days and headers in YearPicker when disabled prop is true", () => {
const { container } = render(
<DatePicker showYearPicker inline disabled />,
);

validateAllDisabled(container, "react-datepicker__year-text");
validateNonExistence(container, "react-datepicker__navigation");
});

it("should disable all days and headers in WeekPicker when disabled prop is true", () => {
const { container } = render(
<DatePicker showWeekNumbers showWeekPicker inline disabled />,
);

validateAllDisabled(container, "react-datepicker__day");
validateNonExistence(container, "react-datepicker__navigation");
});

it("should disable all days and headers in QuarterPicker when disabled prop is true", () => {
const { container } = render(
<DatePicker showQuarterYearPicker inline disabled />,
);

validateAllDisabled(container, "react-datepicker__quarter-text");
validateNonExistence(container, "react-datepicker__navigation");
});
});
});
19 changes: 15 additions & 4 deletions src/year.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { clsx } from "clsx";
import React, { Component, createRef } from "react";

import {
type DateFilterOptions,
type DateFilterOptionsWithDisabled,
addYears,
getStartOfYear,
getYear,
Expand All @@ -24,8 +24,13 @@ const VERTICAL_NAVIGATION_OFFSET = 3;

interface YearProps
extends Pick<
DateFilterOptions,
"minDate" | "maxDate" | "excludeDates" | "includeDates" | "filterDate"
DateFilterOptionsWithDisabled,
| "minDate"
| "maxDate"
| "excludeDates"
| "includeDates"
| "filterDate"
| "disabled"
> {
clearSelectingDate?: VoidFunction;
date?: Date;
Expand Down Expand Up @@ -381,6 +386,7 @@ export default class Year extends Component<YearProps> {
getYearClassNames = (y: number) => {
const {
date,
disabled,
minDate,
maxDate,
excludeDates,
Expand All @@ -396,7 +402,12 @@ export default class Year extends Component<YearProps> {
{
"react-datepicker__year-text--selected": this.isSelectedYear(y),
"react-datepicker__year-text--disabled":
(minDate || maxDate || excludeDates || includeDates || filterDate) &&
(minDate ||
maxDate ||
excludeDates ||
includeDates ||
filterDate ||
disabled) &&
isYearDisabled(y, this.props),
"react-datepicker__year-text--keyboard-selected":
this.isKeyboardSelected(y),
Expand Down
Loading