Repository: Hacker0x01/react-datepicker
Pull request #4734 (2024-04-26 20:15:40)

chore(deps): bump react from 18.3.0 to 18.3.1 in /docs-site
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) from 18.3.0 to 18.3.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/facebook/react/releases">react's releases</a>.</em></p>
<blockquote>
<h2>18.3.1 (April 26, 2024)</h2>
<ul>
<li>Export <code>act</code> from <code>react</code> <a href="https://github.com/facebook/react/commit/f1338f8080abd1386454a10bbf93d67bfe37ce85">f1338f</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/facebook/react/blob/main/CHANGELOG.md">react's changelog</a>.</em></p>
<blockquote>
<h2>18.3.1 (April 26, 2024)</h2>
<ul>
<li>Export <code>act</code> from <code>react</code> <a href="https://github.com/facebook/react/commit/f1338f8080abd1386454a10bbf93d67bfe37ce85">f1338f</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/facebook/react/commit/f1338f8080abd1386454a10bbf93d67bfe37ce85"><code>f1338f8</code></a> Export <code>React.act</code> from 18.3</li>
<li><a href="https://github.com/facebook/react/commit/d6c42f7b1134c4f033296ce4d47a7803aa0929df"><code>d6c42f7</code></a> Bump to 18.3.1</li>
<li>See full diff in <a href="https://github.com/facebook/react/commits/v18.3.1/packages/react">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react&package-manager=npm_and_yarn&previous-version=18.3.0&new-version=18.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/Hacker0x01/react-datepicker/pull/4734?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Hacker0x01) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 97.26%. Comparing base [(`0cb6f84`)](https://app.codecov.io/gh/Hacker0x01/react-datepicker/commit/0cb6f84237a5db65dc3fb0c454b3ac3a40683f0c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Hacker0x01) to head [(`2fd3e99`)](https://app.codecov.io/gh/Hacker0x01/react-datepicker/pull/4734?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Hacker0x01).


<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #4734   +/-   ##
=======================================
  Coverage   97.26%   97.26%           
=======================================
  Files          11       11           
  Lines        1462     1462           
  Branches      642      650    +8     
=======================================
  Hits         1422     1422           
  Misses         40       40           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Hacker0x01/react-datepicker/pull/4734?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Hacker0x01).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Hacker0x01).


Patch:
diff --git a/docs-site/package.json b/docs-site/package.json
index 6bbaa6c0..db08138d 100644
--- a/docs-site/package.json
+++ b/docs-site/package.json
@@ -4,7 +4,7 @@
   "private": true,
   "dependencies": {
     "highlight.js": "^11.9.0",
-    "react": "^18.3.0",
+    "react": "^18.3.1",
     "react-dom": "^18.3.0",
     "react-live": "^4.1.6"
   },
diff --git a/docs-site/yarn.lock b/docs-site/yarn.lock
index 0cbcc9ad..6f9331a2 100644
--- a/docs-site/yarn.lock
+++ b/docs-site/yarn.lock
@@ -7539,10 +7539,10 @@ react-scripts@5.0.1:
   optionalDependencies:
     fsevents "^2.3.2"
 
-react@^18.3.0:
-  version "18.3.0"
-  resolved "https://registry.yarnpkg.com/react/-/react-18.3.0.tgz#84386d0a36fdf5ef50fa5755b7812bdfb76194a5"
-  integrity sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==
+react@^18.3.1:
+  version "18.3.1"
+  resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
+  integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
   dependencies:
     loose-envify "^1.1.0"
 
diff --git a/src/date_utils.ts b/src/date_utils.ts
index b536f50c..7f805b27 100644
--- a/src/date_utils.ts
+++ b/src/date_utils.ts
@@ -498,7 +498,7 @@ export function isSameYear(date1: Date | null, date2: Date | null): boolean {
  * @param date2 - The second date.
  * @returns - True if the dates are in the same month, false otherwise.
  */
-export function isSameMonth(date1: Date | null, date2?: Date | null): boolean {
+export function isSameMonth(date1: Date | null, date2: Date | null): boolean {
   if (date1 && date2) {
     return dfIsSameMonth(date1, date2);
   } else {
@@ -727,7 +727,7 @@ export function getMonthShortInLocale(
  */
 export function getQuarterShortInLocale(
   quarter: number,
-  locale?: string | LocaleObj,
+  locale: string,
 ): string {
   return formatDate(setQuarter(newDate(), quarter), "QQQ", locale);
 }
@@ -845,7 +845,8 @@ export function isMonthDisabled(
       minDate: minDate ? startOfMonth(minDate) : undefined,
       maxDate: maxDate ? endOfMonth(maxDate) : undefined,
     }) ||
-    excludeDates?.some((excludeDate) => isSameMonth(month, excludeDate)) ||
+    (excludeDates &&
+      excludeDates.some((excludeDate) => isSameMonth(month, excludeDate))) ||
     (includeDates &&
       !includeDates.some((includeDate) => isSameMonth(month, includeDate))) ||
     (filterDate && !filterDate(newDate(month))) ||
@@ -896,7 +897,10 @@ export function isQuarterDisabled(
 ): boolean {
   return (
     isOutOfBounds(quarter, { minDate, maxDate }) ||
-    excludeDates?.some((excludeDate) => isSameQuarter(quarter, excludeDate)) ||
+    (excludeDates &&
+      excludeDates.some((excludeDate) =>
+        isSameQuarter(quarter, excludeDate),
+      )) ||
     (includeDates &&
       !includeDates.some((includeDate) =>
         isSameQuarter(quarter, includeDate),
@@ -906,8 +910,7 @@ export function isQuarterDisabled(
   );
 }
 
-export function isYearInRange(year: number, start?: Date, end?: Date): boolean {
-  if (!start || !end) return false;
+export function isYearInRange(year: number, start: Date, end: Date): boolean {
   if (!isValidDate(start) || !isValidDate(end)) return false;
   const startYear = getYear(start);
   const endYear = getYear(end);
@@ -939,7 +942,8 @@ export function isYearDisabled(
       minDate: minDate ? startOfYear(minDate) : undefined,
       maxDate: maxDate ? endOfYear(maxDate) : undefined,
     }) ||
-    excludeDates?.some((excludeDate) => isSameYear(date, excludeDate)) ||
+    (excludeDates &&
+      excludeDates.some((excludeDate) => isSameYear(date, excludeDate))) ||
     (includeDates &&
       !includeDates.some((includeDate) => isSameYear(date, includeDate))) ||
     (filterDate && !filterDate(newDate(date))) ||
@@ -1500,9 +1504,7 @@ export function isDateBefore(date: Date, dateToCompare: Date): boolean {
  * @param event - The keyboard event.
  * @returns - Returns true if the space key was pressed down, false otherwise.
  */
-export function isSpaceKeyDown(
-  event: React.KeyboardEvent<HTMLDivElement>,
-): boolean {
+export function isSpaceKeyDown(event: KeyboardEvent): boolean {
   const SPACE_KEY = " ";
   return event.key === SPACE_KEY;
 }
diff --git a/src/day.tsx b/src/day.tsx
index e4ac67fa..75c22f2e 100644
--- a/src/day.tsx
+++ b/src/day.tsx
@@ -59,7 +59,7 @@ interface DayProps {
   excludeDates?: DayDisabledOptions["excludeDates"];
   excludeDateIntervals?: DayDisabledOptions["excludeDateIntervals"];
   calendarStartDay?: DateNumberType;
-  locale?: string | LocaleObj;
+  locale?: LocaleObj;
   monthShowsDuplicateDaysEnd?: boolean;
   monthShowsDuplicateDaysStart?: boolean;
   includeDates?: DayDisabledOptions["includeDates"];
diff --git a/src/month.tsx b/src/month.jsx
similarity index 55%
rename from src/month.tsx
rename to src/month.jsx
index e9182a99..9a6d5c83 100644
--- a/src/month.tsx
+++ b/src/month.jsx
@@ -1,13 +1,8 @@
 import React from "react";
+import PropTypes from "prop-types";
 import { clsx } from "clsx";
 import Week from "./week";
 import * as utils from "./date_utils";
-import type {
-  LocaleObj,
-  DayDisabledOptions,
-  DateNumberType,
-  HolidaysMap,
-} from "./date_utils";
 
 const FIXED_HEIGHT_STANDARD_WEEK_COUNT = 6;
 
@@ -49,227 +44,123 @@ const MONTH_COLUMNS = {
 const MONTH_NAVIGATION_HORIZONTAL_OFFSET = 1;
 
 function getMonthColumnsLayout(
-  showFourColumnMonthYearPicker?: boolean,
-  showTwoColumnMonthYearPicker?: boolean,
+  showFourColumnMonthYearPicker,
+  showTwoColumnMonthYearPicker,
 ) {
-  if (showFourColumnMonthYearPicker) {
-    return MONTH_COLUMNS_LAYOUT.FOUR_COLUMNS;
-  }
-  if (showTwoColumnMonthYearPicker) {
-    return MONTH_COLUMNS_LAYOUT.TWO_COLUMNS;
-  }
+  if (showFourColumnMonthYearPicker) return MONTH_COLUMNS_LAYOUT.FOUR_COLUMNS;
+  if (showTwoColumnMonthYearPicker) return MONTH_COLUMNS_LAYOUT.TWO_COLUMNS;
   return MONTH_COLUMNS_LAYOUT.THREE_COLUMNS;
 }
 
-interface MonthProps {
-  dayClassName?: (date: Date) => string;
-  monthClassName?: (date: Date) => string;
-  filterDate?: (date: Date) => boolean;
-  formatWeekNumber?: (date: Date) => number;
-  onDayClick?: (
-    date: Date,
-    event:
-      | React.MouseEvent<HTMLDivElement>
-      | React.KeyboardEvent<HTMLDivElement>,
-    orderInDisplay?: number,
-  ) => void;
-  onDayMouseEnter?: (date: Date) => void;
-  onMouseLeave?: () => void;
-  onWeekSelect?: (date: Date) => void;
-  setPreSelection?: (date?: Date) => void;
-  setOpen?: (open: boolean) => void;
-  renderDayContents?: (day: number, date: Date) => React.ReactNode;
-  renderMonthContent?: (
-    m: number,
-    shortMonthText: string,
-    fullMonthText: string,
-    day: Date,
-  ) => React.ReactNode;
-  renderQuarterContent?: (q: number, shortQuarter: string) => React.ReactNode;
-  handleOnKeyDown?: (event: React.KeyboardEvent) => void;
-  handleOnMonthKeyDown?: (event: React.KeyboardEvent) => void;
-  ariaLabelPrefix?: string;
-  chooseDayAriaLabelPrefix?: string;
-  disabledDayAriaLabelPrefix?: string;
-  disabledKeyboardNavigation?: boolean;
-  day: Date;
-  endDate?: Date;
-  orderInDisplay?: number;
-  excludeDates?: DayDisabledOptions["excludeDates"];
-  excludeDateIntervals?: DayDisabledOptions["excludeDateIntervals"];
-  fixedHeight?: boolean;
-  highlightDates?: Map<string, Date>;
-  holidays?: HolidaysMap;
-  includeDates?: DayDisabledOptions["includeDates"];
-  includeDateIntervals?: DayDisabledOptions["includeDateIntervals"];
-  inline?: boolean;
-  shouldFocusDayInline?: boolean;
-  locale?: string | LocaleObj;
-  maxDate?: Date;
-  minDate?: Date;
-  usePointerEvent?: boolean;
-  peekNextMonth?: boolean;
-  preSelection?: Date;
-  selected?: Date;
-  selectingDate?: Date;
-  calendarStartDay?: DateNumberType;
-  selectsEnd?: boolean;
-  selectsStart?: boolean;
-  selectsRange?: boolean;
-  selectsDisabledDaysInRange?: boolean;
-  selectsMultiple?: boolean;
-  selectedDates?: Date[];
-  showWeekNumbers?: boolean;
-  startDate?: Date;
-  shouldCloseOnSelect?: boolean;
-  showMonthYearPicker?: boolean;
-  showFullMonthYearPicker?: boolean;
-  showTwoColumnMonthYearPicker?: boolean;
-  showFourColumnMonthYearPicker?: boolean;
-  showQuarterYearPicker?: boolean;
-  showWeekPicker?: boolean;
-  isInputFocused?: boolean;
-  weekAriaLabelPrefix?: string;
-  containerRef?: React.RefObject<HTMLDivElement>;
-  monthShowsDuplicateDaysEnd?: boolean;
-  monthShowsDuplicateDaysStart?: boolean;
-}
-
-/**
- * `Month` is a React component that represents a month in a calendar.
- * It accepts a `MonthProps` object as props which provides various configurations and event handlers.
- *
- * @prop dayClassName - Function to determine the class name for a day.
- * @prop monthClassName - Function to determine the class name for a month.
- * @prop filterDate - Function to filter dates.
- * @prop formatWeekNumber - Function to format the week number.
- * @prop onDayClick - Function to handle day click events.
- * @prop onDayMouseEnter - Function to handle mouse enter events on a day.
- * @prop onMouseLeave - Function to handle mouse leave events.
- * @prop onWeekSelect - Function to handle week selection.
- * @prop setPreSelection - Function to set pre-selection.
- * @prop setOpen - Function to set open state.
- * @prop renderDayContents - Function to render day contents.
- * @prop renderMonthContent - Function to render month content.
- * @prop renderQuarterContent - Function to render quarter content.
- * @prop handleOnKeyDown - Function to handle key down events.
- * @prop handleOnMonthKeyDown - Function to handle key down events on a month.
- * @prop ariaLabelPrefix - Aria label prefix.
- * @prop chooseDayAriaLabelPrefix - Aria label prefix for choosing a day.
- * @prop disabledDayAriaLabelPrefix - Aria label prefix for disabled day.
- * @prop disabledKeyboardNavigation - Flag to disable keyboard navigation.
- * @prop day - The day.
- * @prop endDate - The end date.
- * @prop orderInDisplay - The order in display.
- * @prop excludeDates - Dates to exclude.
- * @prop excludeDateIntervals - Date intervals to exclude.
- * @prop fixedHeight - Flag to set fixed height.
- * @prop highlightDates - Dates to highlight.
- * @prop holidays - Holidays.
- * @prop includeDates - Dates to include.
- * @prop includeDateIntervals - Date intervals to include.
- * @prop inline - Flag to set inline.
- * @prop shouldFocusDayInline - Flag to set focus on day inline.
- * @prop locale - The locale.
- * @prop maxDate - The maximum date.
- * @prop minDate - The minimum date.
- * @prop usePointerEvent - Flag to use pointer event.
- * @prop peekNextMonth - Flag to peek next month.
- * @prop preSelection - The pre-selection.
- * @prop selected - The selected date.
- * @prop selectingDate - The selecting date.
- * @prop calendarStartDay - The calendar start day.
- * @prop selectsEnd - Flag to select end.
- * @prop selectsStart - Flag to select start.
- * @prop selectsRange - Flag to select range.
- * @prop selectsDisabledDaysInRange - Flag to select disabled days in range.
- * @prop selectsMultiple - Flag to select multiple.
- * @prop selectedDates - The selected dates.
- * @prop showWeekNumbers - Flag to show week numbers.
- * @prop startDate - The start date.
- * @prop shouldCloseOnSelect - Flag to close on select.
- * @prop showMonthYearPicker - Flag to show month year picker.
- * @prop showFullMonthYearPicker - Flag to show full month year picker.
- * @prop showTwoColumnMonthYearPicker - Flag to show two column month year picker.
- * @prop showFourColumnMonthYearPicker - Flag to show four column month year picker.
- * @prop showQuarterYearPicker - Flag to show quarter year picker.
- * @prop showWeekPicker - Flag to show week picker.
- * @prop isInputFocused - Flag to set input focus.
- * @prop weekAriaLabelPrefix - Aria label prefix for week.
- * @prop containerRef - The container reference.
- * @prop monthShowsDuplicateDaysEnd - Flag to show duplicate days at the end of the month.
- * @prop monthShowsDuplicateDaysStart - Flag to show duplicate days at the start of the month.
- *
- * @example
- * ```tsx
- * function App() {
- *  const handleDayClick = (date) => {
- *     console.log('Day clicked: ', date);
- *   };
- *
- *   const handleDayMouseEnter = (date) => {
- *     console.log('Mouse entered on day: ', date);
- *   };
- *
- *   return (
- *     <div>
- *       <Month
- *         day={new Date()}
- *         endDate={new Date()}
- *         onDayClick={handleDayClick}
- *         onDayMouseEnter={handleDayMouseEnter}
- *         disabledKeyboardNavigation={false}
- *         showWeekNumbers={true}
- *         showMonthYearPicker={false}
- *       />
- *     </div>
- *   );
- * }
- * ```
- */
-export default class Month extends React.Component<MonthProps> {
-  MONTH_REFS = [...Array(12)].map(() => React.createRef<HTMLDivElement>());
-  QUARTER_REFS = [...Array(4)].map(() => React.createRef<HTMLDivElement>());
-
-  isDisabled = (day: Date) =>
-    // Almost all props previously were passed as this.props w/o proper typing with prop-types
-    // after the migration to TS i made it explicit
-    utils.isDayDisabled(day, {
-      minDate: this.props.minDate,
-      maxDate: this.props.maxDate,
-      excludeDates: this.props.excludeDates,
-      excludeDateIntervals: this.props.excludeDateIntervals,
-      includeDateIntervals: this.props.includeDateIntervals,
-      includeDates: this.props.includeDates,
-      filterDate: this.props.filterDate,
-    });
-
-  isExcluded = (day: Date) =>
-    // Almost all props previously were passed as this.props w/o proper typing with prop-types
-    // after the migration to TS i made it explicit
-    utils.isDayExcluded(day, {
-      excludeDates: this.props.excludeDates,
-      excludeDateIntervals: this.props.excludeDateIntervals,
-    });
-
-  handleDayClick = (
-    day: Date,
-    event:
-      | React.MouseEvent<HTMLDivElement>
-      | React.KeyboardEvent<HTMLDivElement>,
-  ) => {
-    this.props.onDayClick?.(day, event, this.props.orderInDisplay);
+class Month extends React.Component {
+  static propTypes = {
+    ariaLabelPrefix: PropTypes.string,
+    chooseDayAriaLabelPrefix: PropTypes.string,
+    disabledDayAriaLabelPrefix: PropTypes.string,
+    disabledKeyboardNavigation: PropTypes.bool,
+    day: PropTypes.instanceOf(Date).isRequired,
+    dayClassName: PropTypes.func,
+    monthClassName: PropTypes.func,
+    endDate: PropTypes.instanceOf(Date),
+    orderInDisplay: PropTypes.number,
+    excludeDates: PropTypes.arrayOf(
+      PropTypes.oneOfType([
+        PropTypes.instanceOf(Date),
+        PropTypes.shape({
+          date: PropTypes.instanceOf(Date).isRequired,
+          message: PropTypes.string,
+        }),
+      ]),
+    ),
+    excludeDateIntervals: PropTypes.arrayOf(
+      PropTypes.shape({
+        start: PropTypes.instanceOf(Date),
+        end: PropTypes.instanceOf(Date),
+      }),
+    ),
+    filterDate: PropTypes.func,
+    fixedHeight: PropTypes.bool,
+    formatWeekNumber: PropTypes.func,
+    highlightDates: PropTypes.instanceOf(Map),
+    holidays: PropTypes.instanceOf(Map),
+    includeDates: PropTypes.array,
+    includeDateIntervals: PropTypes.array,
+    inline: PropTypes.bool,
+    shouldFocusDayInline: PropTypes.bool,
+    locale: PropTypes.oneOfType([
+      PropTypes.string,
+      PropTypes.shape({ locale: PropTypes.object }),
+    ]),
+    maxDate: PropTypes.instanceOf(Date),
+    minDate: PropTypes.instanceOf(Date),
+    onDayClick: PropTypes.func,
+    usePointerEvent: PropTypes.bool,
+    onDayMouseEnter: PropTypes.func,
+    onMouseLeave: PropTypes.func,
+    onWeekSelect: PropTypes.func,
+    peekNextMonth: PropTypes.bool,
+    preSelection: PropTypes.instanceOf(Date),
+    setPreSelection: PropTypes.func,
+    selected: PropTypes.instanceOf(Date),
+    selectingDate: PropTypes.instanceOf(Date),
+    calendarStartDay: PropTypes.number,
+    selectsEnd: PropTypes.bool,
+    selectsStart: PropTypes.bool,
+    selectsRange: PropTypes.bool,
+    selectsDisabledDaysInRange: PropTypes.bool,
+    selectsMultiple: PropTypes.bool,
+    selectedDates: PropTypes.arrayOf(PropTypes.instanceOf(Date)),
+    showWeekNumbers: PropTypes.bool,
+    startDate: PropTypes.instanceOf(Date),
+    setOpen: PropTypes.func,
+    shouldCloseOnSelect: PropTypes.bool,
+    renderDayContents: PropTypes.func,
+    renderMonthContent: PropTypes.func,
+    renderQuarterContent: PropTypes.func,
+    showMonthYearPicker: PropTypes.bool,
+    showFullMonthYearPicker: PropTypes.bool,
+    showTwoColumnMonthYearPicker: PropTypes.bool,
+    showFourColumnMonthYearPicker: PropTypes.bool,
+    showQuarterYearPicker: PropTypes.bool,
+    showWeekPicker: PropTypes.bool,
+    handleOnKeyDown: PropTypes.func,
+    handleOnMonthKeyDown: PropTypes.func,
+    isInputFocused: PropTypes.bool,
+    weekAriaLabelPrefix: PropTypes.string,
+    containerRef: PropTypes.oneOfType([
+      PropTypes.func,
+      PropTypes.shape({ current: PropTypes.object }),
+    ]),
+    monthShowsDuplicateDaysEnd: PropTypes.bool,
+    monthShowsDuplicateDaysStart: PropTypes.bool,
+  };
+
+  MONTH_REFS = [...Array(12)].map(() => React.createRef());
+  QUARTER_REFS = [...Array(4)].map(() => React.createRef());
+
+  isDisabled = (date) => utils.isDayDisabled(date, this.props);
+
+  isExcluded = (date) => utils.isDayExcluded(date, this.props);
+
+  handleDayClick = (day, event) => {
+    if (this.props.onDayClick) {
+      this.props.onDayClick(day, event, this.props.orderInDisplay);
+    }
   };
 
-  handleDayMouseEnter = (day: Date) => {
-    this.props.onDayMouseEnter?.(day);
+  handleDayMouseEnter = (day) => {
+    if (this.props.onDayMouseEnter) {
+      this.props.onDayMouseEnter(day);
+    }
   };
 
   handleMouseLeave = () => {
-    this.props.onMouseLeave?.();
+    if (this.props.onMouseLeave) {
+      this.props.onMouseLeave();
+    }
   };
 
-  isRangeStartMonth = (m: number) => {
+  isRangeStartMonth = (m) => {
     const { day, startDate, endDate } = this.props;
     if (!startDate || !endDate) {
       return false;
@@ -277,7 +168,7 @@ export default class Month extends React.Component<MonthProps> {
     return utils.isSameMonth(utils.setMonth(day, m), startDate);
   };
 
-  isRangeStartQuarter = (q: number) => {
+  isRangeStartQuarter = (q) => {
     const { day, startDate, endDate } = this.props;
     if (!startDate || !endDate) {
       return false;
@@ -285,7 +176,7 @@ export default class Month extends React.Component<MonthProps> {
     return utils.isSameQuarter(utils.setQuarter(day, q), startDate);
   };
 
-  isRangeEndMonth = (m: number) => {
+  isRangeEndMonth = (m) => {
     const { day, startDate, endDate } = this.props;
     if (!startDate || !endDate) {
       return false;
@@ -293,7 +184,7 @@ export default class Month extends React.Component<MonthProps> {
     return utils.isSameMonth(utils.setMonth(day, m), endDate);
   };
 
-  isRangeEndQuarter = (q: number) => {
+  isRangeEndQuarter = (q) => {
     const { day, startDate, endDate } = this.props;
     if (!startDate || !endDate) {
       return false;
@@ -301,7 +192,7 @@ export default class Month extends React.Component<MonthProps> {
     return utils.isSameQuarter(utils.setQuarter(day, q), endDate);
   };
 
-  isInSelectingRangeMonth = (m: number) => {
+  isInSelectingRangeMonth = (m) => {
     const { day, selectsStart, selectsEnd, selectsRange, startDate, endDate } =
       this.props;
 
@@ -326,7 +217,7 @@ export default class Month extends React.Component<MonthProps> {
     return false;
   };
 
-  isSelectingMonthRangeStart = (m: number) => {
+  isSelectingMonthRangeStart = (m) => {
     if (!this.isInSelectingRangeMonth(m)) {
       return false;
     }
@@ -342,7 +233,7 @@ export default class Month extends React.Component<MonthProps> {
     }
   };
 
-  isSelectingMonthRangeEnd = (m: number) => {
+  isSelectingMonthRangeEnd = (m) => {
     if (!this.isInSelectingRangeMonth(m)) {
       return false;
     }
@@ -358,7 +249,7 @@ export default class Month extends React.Component<MonthProps> {
     }
   };
 
-  isInSelectingRangeQuarter = (q: number) => {
+  isInSelectingRangeQuarter = (q) => {
     const { day, selectsStart, selectsEnd, selectsRange, startDate, endDate } =
       this.props;
 
@@ -383,7 +274,7 @@ export default class Month extends React.Component<MonthProps> {
     return false;
   };
 
-  isWeekInMonth = (startOfWeek: Date) => {
+  isWeekInMonth = (startOfWeek) => {
     const day = this.props.day;
     const endOfWeek = utils.addDays(startOfWeek, 6);
     return (
@@ -391,25 +282,25 @@ export default class Month extends React.Component<MonthProps> {
     );
   };
 
-  isCurrentMonth = (day: Date, m: number) =>
+  isCurrentMonth = (day, m) =>
     utils.getYear(day) === utils.getYear(utils.newDate()) &&
     m === utils.getMonth(utils.newDate());
 
-  isCurrentQuarter = (day: Date, q: number) =>
+  isCurrentQuarter = (day, q) =>
     utils.getYear(day) === utils.getYear(utils.newDate()) &&
     q === utils.getQuarter(utils.newDate());
 
-  isSelectedMonth = (day: Date, m: number, selected: Date) =>
+  isSelectedMonth = (day, m, selected) =>
     utils.getMonth(selected) === m &&
     utils.getYear(day) === utils.getYear(selected);
 
-  isSelectedQuarter = (day: Date, q: number, selected: Date) =>
+  isSelectedQuarter = (day, q, selected) =>
     utils.getQuarter(day) === q &&
     utils.getYear(day) === utils.getYear(selected);
 
   renderWeeks = () => {
     const weeks = [];
-    let isFixedHeight = this.props.fixedHeight;
+    var isFixedHeight = this.props.fixedHeight;
 
     let i = 0;
     let breakAfterNextPush = false;
@@ -419,31 +310,21 @@ export default class Month extends React.Component<MonthProps> {
       this.props.calendarStartDay,
     );
 
-    const isPreSelected = (preSelection: Date) =>
-      this.props.showWeekPicker
-        ? utils.getStartOfWeek(
-            preSelection,
-            this.props.locale,
-            this.props.calendarStartDay,
-          )
-        : this.props.preSelection;
-
-    const isSelected = (selected: Date) =>
-      this.props.showWeekPicker
-        ? utils.getStartOfWeek(
-            selected,
-            this.props.locale,
-            this.props.calendarStartDay,
-          )
-        : this.props.selected;
-
-    const selected = this.props.selected
-      ? isSelected(this.props.selected)
-      : undefined;
+    const selected = this.props.showWeekPicker
+      ? utils.getStartOfWeek(
+          this.props.selected,
+          this.props.locale,
+          this.props.calendarStartDay,
+        )
+      : this.props.selected;
 
-    const preSelection = this.props.preSelection
-      ? isPreSelected(this.props.preSelection)
-      : undefined;
+    const preSelection = this.props.showWeekPicker
+      ? utils.getStartOfWeek(
+          this.props.preSelection,
+          this.props.locale,
+          this.props.calendarStartDay,
+        )
+      : this.props.preSelection;
 
     while (true) {
       weeks.push(
@@ -522,45 +403,34 @@ export default class Month extends React.Component<MonthProps> {
     return weeks;
   };
 
-  onMonthClick = (
-    e:
-      | React.MouseEvent<HTMLDivElement, MouseEvent>
-      | React.KeyboardEvent<HTMLDivElement>,
-    m: number,
-  ) => {
-    const { isDisabled, labelDate } = this.isMonthDisabledForLabelDate(m);
+  onMonthClick = (e, m) => {
+    const labelDate = utils.setMonth(this.props.day, m);
 
-    if (isDisabled) {
+    if (utils.isMonthDisabled(labelDate, this.props)) {
       return;
     }
 
     this.handleDayClick(utils.getStartOfMonth(labelDate), e);
   };
 
-  onMonthMouseEnter = (m: number) => {
-    const { isDisabled, labelDate } = this.isMonthDisabledForLabelDate(m);
+  onMonthMouseEnter = (m) => {
+    const labelDate = utils.setMonth(this.props.day, m);
 
-    if (isDisabled) {
+    if (utils.isMonthDisabled(labelDate, this.props)) {
       return;
     }
 
     this.handleDayMouseEnter(utils.getStartOfMonth(labelDate));
   };
 
-  handleMonthNavigation = (newMonth: number, newDate: Date) => {
-    if (this.isDisabled(newDate) || this.isExcluded(newDate)) {
-      return;
-    }
-
-    this.props.setPreSelection?.(newDate);
-
-    this.MONTH_REFS[newMonth]?.current?.focus();
+  handleMonthNavigation = (newMonth, newDate) => {
+    if (this.isDisabled(newDate) || this.isExcluded(newDate)) return;
+    this.props.setPreSelection(newDate);
+    this.MONTH_REFS[newMonth].current &&
+      this.MONTH_REFS[newMonth].current.focus();
   };
 
-  onMonthKeyDown = (
-    event: React.KeyboardEvent<HTMLDivElement>,
-    month: number,
-  ) => {
+  onMonthKeyDown = (event, month) => {
     const {
       selected,
       preSelection,
@@ -580,59 +450,44 @@ export default class Month extends React.Component<MonthProps> {
         showFourColumnMonthYearPicker,
         showTwoColumnMonthYearPicker,
       );
-
       const verticalOffset =
-        MONTH_COLUMNS[monthColumnsLayout]?.verticalNavigationOffset;
-
-      const monthsGrid = MONTH_COLUMNS[monthColumnsLayout]?.grid;
-
+        MONTH_COLUMNS[monthColumnsLayout].verticalNavigationOffset;
+      const monthsGrid = MONTH_COLUMNS[monthColumnsLayout].grid;
       switch (eventKey) {
         case "Enter":
           if (!this.isMonthDisabled(month)) {
             this.onMonthClick(event, month);
-            setPreSelection?.(selected);
+            setPreSelection(selected);
           }
           break;
         case "ArrowRight":
-          if (!preSelection) {
-            break;
-          }
           this.handleMonthNavigation(
             month === 11 ? 0 : month + MONTH_NAVIGATION_HORIZONTAL_OFFSET,
             utils.addMonths(preSelection, MONTH_NAVIGATION_HORIZONTAL_OFFSET),
           );
           break;
         case "ArrowLeft":
-          if (!preSelection) {
-            break;
-          }
           this.handleMonthNavigation(
             month === 0 ? 11 : month - MONTH_NAVIGATION_HORIZONTAL_OFFSET,
             utils.subMonths(preSelection, MONTH_NAVIGATION_HORIZONTAL_OFFSET),
           );
           break;
         case "ArrowUp":
-          if (!preSelection) {
-            break;
-          }
           this.handleMonthNavigation(
             // Check if month on the first row
-            monthsGrid?.[0]?.includes(month)
-              ? month + 12 - (verticalOffset ?? 0)
-              : month - (verticalOffset ?? 0),
-            utils.subMonths(preSelection, verticalOffset ?? 0),
+            monthsGrid[0].includes(month)
+              ? month + 12 - verticalOffset
+              : month - verticalOffset,
+            utils.subMonths(preSelection, verticalOffset),
           );
           break;
         case "ArrowDown":
-          if (!preSelection) {
-            break;
-          }
           this.handleMonthNavigation(
             // Check if month on the last row
-            monthsGrid?.[monthsGrid.length - 1]?.includes(month)
-              ? month - 12 + (verticalOffset ?? 0)
-              : month + (verticalOffset ?? 0),
-            utils.addMonths(preSelection, verticalOffset ?? 0),
+            monthsGrid[monthsGrid.length - 1].includes(month)
+              ? month - 12 + verticalOffset
+              : month + verticalOffset,
+            utils.addMonths(preSelection, verticalOffset),
           );
           break;
       }
@@ -641,88 +496,48 @@ export default class Month extends React.Component<MonthProps> {
     handleOnMonthKeyDown && handleOnMonthKeyDown(event);
   };
 
-  private propsToOnDisableClick = (
-    prps: MonthProps,
-  ): {
-    minDate?: Date;
-    maxDate?: Date;
-    excludeDates?: Date[];
-    includeDates?: Date[];
-    filterDate?: (date: Date) => boolean;
-  } => ({
-    minDate: prps.minDate,
-    maxDate: prps.maxDate,
-    excludeDates: prps.excludeDates?.reduce((acc, itm) => {
-      if (itm instanceof Date) {
-        acc.push(itm);
-      } else if (itm.date) {
-        acc.push(itm.date);
-      }
-      return acc;
-    }, [] as Date[]),
-    includeDates: prps.includeDates,
-    filterDate: prps.filterDate,
-  });
-
-  onQuarterClick = (
-    e: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>,
-    q: number,
-  ) => {
+  onQuarterClick = (e, q) => {
     const labelDate = utils.setQuarter(this.props.day, q);
 
-    if (
-      utils.isQuarterDisabled(labelDate, this.propsToOnDisableClick(this.props))
-    ) {
+    if (utils.isQuarterDisabled(labelDate, this.props)) {
       return;
     }
 
     this.handleDayClick(utils.getStartOfQuarter(labelDate), e);
   };
 
-  onQuarterMouseEnter = (q: number) => {
+  onQuarterMouseEnter = (q) => {
     const labelDate = utils.setQuarter(this.props.day, q);
 
-    if (
-      utils.isQuarterDisabled(labelDate, this.propsToOnDisableClick(this.props))
-    ) {
+    if (utils.isQuarterDisabled(labelDate, this.props)) {
       return;
     }
 
     this.handleDayMouseEnter(utils.getStartOfQuarter(labelDate));
   };
 
-  handleQuarterNavigation = (newQuarter: number, newDate: Date) => {
-    if (this.isDisabled(newDate) || this.isExcluded(newDate)) {
-      return;
-    }
-    this.props.setPreSelection?.(newDate);
-    this.QUARTER_REFS[newQuarter - 1]?.current?.focus();
+  handleQuarterNavigation = (newQuarter, newDate) => {
+    if (this.isDisabled(newDate) || this.isExcluded(newDate)) return;
+    this.props.setPreSelection(newDate);
+    this.QUARTER_REFS[newQuarter - 1].current &&
+      this.QUARTER_REFS[newQuarter - 1].current.focus();
   };
 
-  onQuarterKeyDown = (
-    event: React.KeyboardEvent<HTMLDivElement>,
-    quarter: number,
-  ) => {
+  onQuarterKeyDown = (event, quarter) => {
     const eventKey = event.key;
     if (!this.props.disabledKeyboardNavigation) {
       switch (eventKey) {
         case "Enter":
           this.onQuarterClick(event, quarter);
-          this.props.setPreSelection?.(this.props.selected);
+          this.props.setPreSelection(this.props.selected);
           break;
         case "ArrowRight":
-          if (!this.props.preSelection) {
-            break;
-          }
           this.handleQuarterNavigation(
             quarter === 4 ? 1 : quarter + 1,
             utils.addQuarters(this.props.preSelection, 1),
           );
           break;
         case "ArrowLeft":
-          if (!this.props.preSelection) {
-            break;
-          }
           this.handleQuarterNavigation(
             quarter === 1 ? 4 : quarter - 1,
             utils.subQuarters(this.props.preSelection, 1),
@@ -732,32 +547,16 @@ export default class Month extends React.Component<MonthProps> {
     }
   };
 
-  isMonthDisabledForLabelDate = (
-    month: number,
-  ): {
-    isDisabled: boolean;
-    labelDate: Date;
-  } => {
+  isMonthDisabled = (month) => {
     const { day, minDate, maxDate, excludeDates, includeDates } = this.props;
     const labelDate = utils.setMonth(day, month);
-    return {
-      isDisabled:
-        ((minDate || maxDate || excludeDates || includeDates) &&
-          utils.isMonthDisabled(
-            labelDate,
-            this.propsToOnDisableClick(this.props),
-          )) ??
-        false,
-      labelDate,
-    };
-  };
-
-  isMonthDisabled = (month: number) => {
-    const { isDisabled } = this.isMonthDisabledForLabelDate(month);
-    return isDisabled;
+    return (
+      (minDate || maxDate || excludeDates || includeDates) &&
+      utils.isMonthDisabled(labelDate, this.props)
+    );
   };
 
-  getMonthClassNames = (m: number) => {
+  getMonthClassNames = (m) => {
     const { day, startDate, endDate, selected, preSelection, monthClassName } =
       this.props;
     const _monthClassName = monthClassName
@@ -769,19 +568,22 @@ export default class Month extends React.Component<MonthProps> {
       _monthClassName,
       {
         "react-datepicker__month-text--disabled": this.isMonthDisabled(m),
-        "react-datepicker__month-text--selected": selected
-          ? this.isSelectedMonth(day, m, selected)
-          : undefined,
+        "react-datepicker__month-text--selected": this.isSelectedMonth(
+          day,
+          m,
+          selected,
+        ),
         "react-datepicker__month-text--keyboard-selected":
           !this.props.disabledKeyboardNavigation &&
-          preSelection &&
           this.isSelectedMonth(day, m, preSelection),
         "react-datepicker__month-text--in-selecting-range":
           this.isInSelectingRangeMonth(m),
-        "react-datepicker__month-text--in-range":
-          startDate && endDate
-            ? utils.isMonthInRange(startDate, endDate, m, day)
-            : undefined,
+        "react-datepicker__month-text--in-range": utils.isMonthInRange(
+          startDate,
+          endDate,
+          m,
+          day,
+        ),
         "react-datepicker__month-text--range-start": this.isRangeStartMonth(m),
         "react-datepicker__month-text--range-end": this.isRangeEndMonth(m),
         "react-datepicker__month-text--selecting-range-start":
@@ -793,10 +595,7 @@ export default class Month extends React.Component<MonthProps> {
     );
   };
 
-  getTabIndex = (m: number) => {
-    if (this.props.preSelection == null) {
-      return "-1";
-    }
+  getTabIndex = (m) => {
     const preSelectedMonth = utils.getMonth(this.props.preSelection);
     const tabIndex =
       !this.props.disabledKeyboardNavigation && m === preSelectedMonth
@@ -806,10 +605,7 @@ export default class Month extends React.Component<MonthProps> {
     return tabIndex;
   };
 
-  getQuarterTabIndex = (q: number) => {
-    if (this.props.preSelection == null) {
-      return "-1";
-    }
+  getQuarterTabIndex = (q) => {
     const preSelectedQuarter = utils.getQuarter(this.props.preSelection);
     const tabIndex =
       !this.props.disabledKeyboardNavigation && q === preSelectedQuarter
@@ -819,7 +615,7 @@ export default class Month extends React.Component<MonthProps> {
     return tabIndex;
   };
 
-  getAriaLabel = (month: number) => {
+  getAriaLabel = (month) => {
     const {
       chooseDayAriaLabelPrefix = "Choose",
       disabledDayAriaLabelPrefix = "Not available",
@@ -835,7 +631,7 @@ export default class Month extends React.Component<MonthProps> {
     return `${prefix} ${utils.formatDate(labelDate, "MMMM yyyy", locale)}`;
   };
 
-  getQuarterClassNames = (q: number) => {
+  getQuarterClassNames = (q) => {
     const {
       day,
       startDate,
@@ -852,23 +648,23 @@ export default class Month extends React.Component<MonthProps> {
       {
         "react-datepicker__quarter-text--disabled":
           (minDate || maxDate) &&
-          utils.isQuarterDisabled(
-            utils.setQuarter(day, q),
-            this.propsToOnDisableClick(this.props),
-          ),
-        "react-datepicker__quarter-text--selected": selected
-          ? this.isSelectedQuarter(day, q, selected)
-          : undefined,
+          utils.isQuarterDisabled(utils.setQuarter(day, q), this.props),
+        "react-datepicker__quarter-text--selected": this.isSelectedQuarter(
+          day,
+          q,
+          selected,
+        ),
         "react-datepicker__quarter-text--keyboard-selected":
           !disabledKeyboardNavigation &&
-          preSelection &&
           this.isSelectedQuarter(day, q, preSelection),
         "react-datepicker__quarter-text--in-selecting-range":
           this.isInSelectingRangeQuarter(q),
-        "react-datepicker__quarter-text--in-range":
-          startDate && endDate
-            ? utils.isQuarterInRange(startDate, endDate, q, day)
-            : undefined,
+        "react-datepicker__quarter-text--in-range": utils.isQuarterInRange(
+          startDate,
+          endDate,
+          q,
+          day,
+        ),
         "react-datepicker__quarter-text--range-start":
           this.isRangeStartQuarter(q),
         "react-datepicker__quarter-text--range-end": this.isRangeEndQuarter(q),
@@ -876,7 +672,7 @@ export default class Month extends React.Component<MonthProps> {
     );
   };
 
-  getMonthContent = (m: number) => {
+  getMonthContent = (m) => {
     const { showFullMonthYearPicker, renderMonthContent, locale, day } =
       this.props;
     const shortMonthText = utils.getMonthShortInLocale(m, locale);
@@ -887,10 +683,12 @@ export default class Month extends React.Component<MonthProps> {
     return showFullMonthYearPicker ? fullMonthText : shortMonthText;
   };
 
-  getQuarterContent = (q: number) => {
+  getQuarterContent = (q) => {
     const { renderQuarterContent, locale } = this.props;
     const shortQuarter = utils.getQuarterShortInLocale(q, locale);
-    return renderQuarterContent?.(q, shortQuarter) ?? shortQuarter;
+    return renderQuarterContent
+      ? renderQuarterContent(q, shortQuarter)
+      : shortQuarter;
   };
 
   renderMonths = () => {
@@ -907,8 +705,8 @@ export default class Month extends React.Component<MonthProps> {
           showFourColumnMonthYearPicker,
           showTwoColumnMonthYearPicker,
         )
-      ]?.grid;
-    return monthColumns?.map((month, i) => (
+      ].grid;
+    return monthColumns.map((month, i) => (
       <div className="react-datepicker__month-wrapper" key={i}>
         {month.map((m, j) => (
           <div
@@ -935,13 +733,13 @@ export default class Month extends React.Component<MonthProps> {
                 ? () => this.onMonthMouseEnter(m)
                 : undefined
             }
-            tabIndex={Number(this.getTabIndex(m))}
+            tabIndex={this.getTabIndex(m)}
             className={this.getMonthClassNames(m)}
             aria-disabled={this.isMonthDisabled(m)}
             role="option"
             aria-label={this.getAriaLabel(m)}
             aria-current={this.isCurrentMonth(day, m) ? "date" : undefined}
-            aria-selected={selected && this.isSelectedMonth(day, m, selected)}
+            aria-selected={this.isSelectedMonth(day, m, selected)}
           >
             {this.getMonthContent(m)}
           </div>
@@ -977,8 +775,8 @@ export default class Month extends React.Component<MonthProps> {
                 : undefined
             }
             className={this.getQuarterClassNames(q)}
-            aria-selected={selected && this.isSelectedQuarter(day, q, selected)}
-            tabIndex={Number(this.getQuarterTabIndex(q))}
+            aria-selected={this.isSelectedQuarter(day, q, selected)}
+            tabIndex={this.getQuarterTabIndex(q)}
             aria-current={this.isCurrentQuarter(day, q) ? "date" : undefined}
           >
             {this.getQuarterContent(q)}
@@ -1043,3 +841,5 @@ export default class Month extends React.Component<MonthProps> {
     );
   }
 }
+
+export default Month;
diff --git a/src/year.tsx b/src/year.jsx
similarity index 56%
rename from src/year.tsx
rename to src/year.jsx
index b0419ab8..55b82efd 100644
--- a/src/year.tsx
+++ b/src/year.jsx
@@ -1,126 +1,83 @@
-import React, { Component } from "react";
+import React from "react";
+import PropTypes from "prop-types";
 import { getYear, newDate } from "./date_utils";
 import * as utils from "./date_utils";
 import { clsx } from "clsx";
 
 const VERTICAL_NAVIGATION_OFFSET = 3;
 
-interface YearProps {
-  clearSelectingDate?: () => void;
-  date?: Date;
-  disabledKeyboardNavigation?: boolean;
-  endDate?: Date;
-  onDayClick?: (
-    date: Date,
-    event:
-      | React.MouseEvent<HTMLDivElement>
-      | React.KeyboardEvent<HTMLDivElement>,
-  ) => void;
-  preSelection?: Date;
-  setPreSelection?: (date: Date) => void;
-  selected?: Date;
-  inline?: boolean;
-  maxDate?: Date;
-  minDate?: Date;
-  usePointerEvent?: boolean;
-  onYearMouseEnter: (
-    e: React.MouseEvent<HTMLDivElement, MouseEvent>,
-    year: number,
-  ) => void;
-  onYearMouseLeave: (
-    e: React.MouseEvent<HTMLDivElement, MouseEvent>,
-    year: number,
-  ) => void;
-  selectingDate?: Date;
-  renderYearContent?: (year: number) => React.ReactNode;
-  selectsEnd?: boolean;
-  selectsStart?: boolean;
-  selectsRange?: boolean;
-  startDate?: Date;
-  excludeDates?: Date[] | { date: Date; message?: string }[];
-  includeDates?: [];
-  filterDate?: (date: Date) => boolean;
-  yearItemNumber?: number;
-  handleOnKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
-  yearClassName?: (date: Date) => string;
-}
+export default class Year extends React.Component {
+  static propTypes = {
+    clearSelectingDate: PropTypes.func,
+    date: PropTypes.instanceOf(Date),
+    disabledKeyboardNavigation: PropTypes.bool,
+    endDate: PropTypes.instanceOf(Date),
+    onDayClick: PropTypes.func,
+    preSelection: PropTypes.instanceOf(Date),
+    setPreSelection: PropTypes.func,
+    selected: PropTypes.object,
+    inline: PropTypes.bool,
+    maxDate: PropTypes.instanceOf(Date),
+    minDate: PropTypes.instanceOf(Date),
+    usePointerEvent: PropTypes.bool,
+    onYearMouseEnter: PropTypes.func.isRequired,
+    onYearMouseLeave: PropTypes.func.isRequired,
+    selectingDate: PropTypes.instanceOf(Date),
+    renderYearContent: PropTypes.func,
+    selectsEnd: PropTypes.bool,
+    selectsStart: PropTypes.bool,
+    selectsRange: PropTypes.bool,
+    startDate: PropTypes.instanceOf(Date),
+    excludeDates: PropTypes.arrayOf(
+      PropTypes.oneOfType([
+        PropTypes.instanceOf(Date),
+        PropTypes.shape({
+          date: PropTypes.instanceOf(Date).isRequired,
+          message: PropTypes.string,
+        }),
+      ]),
+    ),
+    includeDates: PropTypes.array,
+    filterDate: PropTypes.func,
+    yearItemNumber: PropTypes.number,
+    handleOnKeyDown: PropTypes.func,
+    yearClassName: PropTypes.func,
+  };
 
-/**
- * `Year` is a component that represents a year in a date picker.
- *
- * @class
- * @param {YearProps} props - The properties that define the `Year` component.
- * @property {() => void} [props.clearSelectingDate] - Function to clear the selected date.
- * @property {Date} [props.date] - The currently selected date.
- * @property {boolean} [props.disabledKeyboardNavigation] - If true, keyboard navigation is disabled.
- * @property {Date} [props.endDate] - The end date in a range selection.
- * @property {(date: Date) => void} props.onDayClick - Function to handle day click events.
- * @property {Date} props.preSelection - The date that is currently in focus.
- * @property {(date: Date) => void} props.setPreSelection - Function to set the pre-selected date.
- * @property {{ [key: string]: any }} props.selected - The selected date(s).
- * @property {boolean} props.inline - If true, the date picker is displayed inline.
- * @property {Date} props.maxDate - The maximum selectable date.
- * @property {Date} props.minDate - The minimum selectable date.
- * @property {boolean} props.usePointerEvent - If true, pointer events are used instead of mouse events.
- * @property {(date: Date) => void} props.onYearMouseEnter - Function to handle mouse enter events on a year.
- * @property {(date: Date) => void} props.onYearMouseLeave - Function to handle mouse leave events on a year.
- */
-export default class Year extends Component<YearProps> {
-  constructor(props: YearProps) {
+  constructor(props) {
     super(props);
   }
 
   YEAR_REFS = [...Array(this.props.yearItemNumber)].map(() =>
-    React.createRef<HTMLDivElement>(),
+    React.createRef(),
   );
 
-  isDisabled = (date: Date) =>
-    utils.isDayDisabled(date, {
-      minDate: this.props.minDate,
-      maxDate: this.props.maxDate,
-      excludeDates: this.props.excludeDates,
-      includeDates: this.props.includeDates,
-      filterDate: this.props.filterDate,
-    });
+  isDisabled = (date) => utils.isDayDisabled(date, this.props);
 
-  isExcluded = (date: Date) =>
-    utils.isDayExcluded(date, {
-      excludeDates: this.props.excludeDates,
-    });
+  isExcluded = (date) => utils.isDayExcluded(date, this.props);
 
   selectingDate = () => this.props.selectingDate ?? this.props.preSelection;
 
-  updateFocusOnPaginate = (refIndex: number) => {
-    const waitForReRender = () => {
-      this.YEAR_REFS[refIndex]?.current?.focus();
-    };
+  updateFocusOnPaginate = (refIndex) => {
+    const waitForReRender = function () {
+      this.YEAR_REFS[refIndex].current.focus();
+    }.bind(this);
 
     window.requestAnimationFrame(waitForReRender);
   };
 
-  handleYearClick = (
-    day: Date,
-    event:
-      | React.MouseEvent<HTMLDivElement>
-      | React.KeyboardEvent<HTMLDivElement>,
-  ) => {
+  handleYearClick = (day, event) => {
     if (this.props.onDayClick) {
       this.props.onDayClick(day, event);
     }
   };
 
-  handleYearNavigation = (newYear: number, newDate: Date) => {
+  handleYearNavigation = (newYear, newDate) => {
     const { date, yearItemNumber } = this.props;
-    if (date === undefined || yearItemNumber === undefined) {
-      return;
-    }
-
     const { startPeriod } = utils.getYearsPeriod(date, yearItemNumber);
 
-    if (this.isDisabled(newDate) || this.isExcluded(newDate)) {
-      return;
-    }
-    this.props.setPreSelection?.(newDate);
+    if (this.isDisabled(newDate) || this.isExcluded(newDate)) return;
+    this.props.setPreSelection(newDate);
 
     if (newYear - startPeriod < 0) {
       this.updateFocusOnPaginate(yearItemNumber - (startPeriod - newYear));
@@ -128,27 +85,27 @@ export default class Year extends Component<YearProps> {
       this.updateFocusOnPaginate(
         Math.abs(yearItemNumber - (newYear - startPeriod)),
       );
-    } else this.YEAR_REFS[newYear - startPeriod]?.current?.focus();
+    } else this.YEAR_REFS[newYear - startPeriod].current.focus();
   };
 
-  isSameDay = (y: Date, other: Date) => utils.isSameDay(y, other);
+  isSameDay = (y, other) => utils.isSameDay(y, other);
 
-  isCurrentYear = (y: number) => y === getYear(newDate());
+  isCurrentYear = (y) => y === getYear(newDate());
 
-  isRangeStart = (y: number) =>
+  isRangeStart = (y) =>
     this.props.startDate &&
     this.props.endDate &&
     utils.isSameYear(utils.setYear(newDate(), y), this.props.startDate);
 
-  isRangeEnd = (y: number) =>
+  isRangeEnd = (y) =>
     this.props.startDate &&
     this.props.endDate &&
     utils.isSameYear(utils.setYear(newDate(), y), this.props.endDate);
 
-  isInRange = (y: number) =>
+  isInRange = (y) =>
     utils.isYearInRange(y, this.props.startDate, this.props.endDate);
 
-  isInSelectingRange = (y: number) => {
+  isInSelectingRange = (y) => {
     const { selectsStart, selectsEnd, selectsRange, startDate, endDate } =
       this.props;
 
@@ -170,7 +127,7 @@ export default class Year extends Component<YearProps> {
     return false;
   };
 
-  isSelectingRangeStart = (y: number) => {
+  isSelectingRangeStart = (y) => {
     if (!this.isInSelectingRange(y)) {
       return false;
     }
@@ -179,12 +136,12 @@ export default class Year extends Component<YearProps> {
     const _year = utils.setYear(newDate(), y);
 
     if (selectsStart) {
-      return utils.isSameYear(_year, this.selectingDate() ?? null);
+      return utils.isSameYear(_year, this.selectingDate());
     }
-    return utils.isSameYear(_year, startDate ?? null);
+    return utils.isSameYear(_year, startDate);
   };
 
-  isSelectingRangeEnd = (y: number) => {
+  isSelectingRangeEnd = (y) => {
     if (!this.isInSelectingRange(y)) {
       return false;
     }
@@ -193,19 +150,12 @@ export default class Year extends Component<YearProps> {
     const _year = utils.setYear(newDate(), y);
 
     if (selectsEnd || selectsRange) {
-      return utils.isSameYear(_year, this.selectingDate() ?? null);
+      return utils.isSameYear(_year, this.selectingDate());
     }
-    return utils.isSameYear(_year, endDate ?? null);
+    return utils.isSameYear(_year, endDate);
   };
 
-  isKeyboardSelected = (y: number) => {
-    if (
-      this.props.date === undefined ||
-      this.props.selected === undefined ||
-      this.props.preSelection === undefined
-    ) {
-      return;
-    }
+  isKeyboardSelected = (y) => {
     const date = utils.getStartOfYear(utils.setYear(this.props.date, y));
     return (
       !this.props.disabledKeyboardNavigation &&
@@ -215,20 +165,12 @@ export default class Year extends Component<YearProps> {
     );
   };
 
-  onYearClick = (
-    e:
-      | React.MouseEvent<HTMLDivElement, MouseEvent>
-      | React.KeyboardEvent<HTMLDivElement>,
-    y: number,
-  ) => {
+  onYearClick = (e, y) => {
     const { date } = this.props;
-    if (date === undefined) {
-      return;
-    }
     this.handleYearClick(utils.getStartOfYear(utils.setYear(date, y)), e);
   };
 
-  onYearKeyDown = (e: React.KeyboardEvent<HTMLDivElement>, y: number) => {
+  onYearKeyDown = (e, y) => {
     const { key } = e;
     const { date, yearItemNumber, handleOnKeyDown } = this.props;
 
@@ -240,38 +182,22 @@ export default class Year extends Component<YearProps> {
     if (!this.props.disabledKeyboardNavigation) {
       switch (key) {
         case "Enter":
-          if (this.props.selected === undefined) {
-            break;
-          }
           this.onYearClick(e, y);
-          this.props.setPreSelection?.(this.props.selected);
+          this.props.setPreSelection(this.props.selected);
           break;
         case "ArrowRight":
-          if (this.props.preSelection === undefined) {
-            break;
-          }
           this.handleYearNavigation(
             y + 1,
             utils.addYears(this.props.preSelection, 1),
           );
           break;
         case "ArrowLeft":
-          if (this.props.preSelection === undefined) {
-            break;
-          }
           this.handleYearNavigation(
             y - 1,
             utils.subYears(this.props.preSelection, 1),
           );
           break;
         case "ArrowUp": {
-          if (
-            date === undefined ||
-            yearItemNumber === undefined ||
-            this.props.preSelection === undefined
-          ) {
-            break;
-          }
           const { startPeriod } = utils.getYearsPeriod(date, yearItemNumber);
           let offset = VERTICAL_NAVIGATION_OFFSET;
           let newYear = y - offset;
@@ -295,13 +221,6 @@ export default class Year extends Component<YearProps> {
           break;
         }
         case "ArrowDown": {
-          if (
-            date === undefined ||
-            yearItemNumber === undefined ||
-            this.props.preSelection === undefined
-          ) {
-            break;
-          }
           const { endPeriod } = utils.getYearsPeriod(date, yearItemNumber);
           let offset = VERTICAL_NAVIGATION_OFFSET;
           let newYear = y + offset;
@@ -330,7 +249,7 @@ export default class Year extends Component<YearProps> {
     handleOnKeyDown && handleOnKeyDown(e);
   };
 
-  getYearClassNames = (y: number) => {
+  getYearClassNames = (y) => {
     const {
       date,
       minDate,
@@ -345,27 +264,12 @@ export default class Year extends Component<YearProps> {
     return clsx(
       "react-datepicker__year-text",
       `react-datepicker__year-${y}`,
-      date ? yearClassName?.(utils.setYear(date, y)) : undefined,
+      yearClassName ? yearClassName(utils.setYear(date, y)) : undefined,
       {
-        "react-datepicker__year-text--selected": selected
-          ? y === getYear(selected)
-          : undefined,
+        "react-datepicker__year-text--selected": y === getYear(selected),
         "react-datepicker__year-text--disabled":
           (minDate || maxDate || excludeDates || includeDates || filterDate) &&
-          utils.isYearDisabled(y, {
-            minDate: this.props.minDate,
-            maxDate: this.props.maxDate,
-            excludeDates: this.props.excludeDates?.reduce((acc, item) => {
-              if (item instanceof Date) {
-                acc.push(item);
-              } else {
-                acc.push(item.date);
-              }
-              return acc;
-            }, [] as Date[]),
-            includeDates: this.props.includeDates,
-            filterDate: this.props.filterDate,
-          }),
+          utils.isYearDisabled(y, this.props),
         "react-datepicker__year-text--keyboard-selected":
           this.isKeyboardSelected(y),
         "react-datepicker__year-text--range-start": this.isRangeStart(y),
@@ -382,13 +286,8 @@ export default class Year extends Component<YearProps> {
     );
   };
 
-  getYearTabIndex = (y: number) => {
-    if (
-      this.props.disabledKeyboardNavigation ||
-      this.props.preSelection === undefined
-    ) {
-      return "-1";
-    }
+  getYearTabIndex = (y) => {
+    if (this.props.disabledKeyboardNavigation) return "-1";
     const preSelected = utils.getYear(this.props.preSelection);
 
     return y === preSelected ? "0" : "-1";
@@ -403,7 +302,7 @@ export default class Year extends Component<YearProps> {
     });
   };
 
-  getYearContent = (y: number) => {
+  getYearContent = (y) => {
     return this.props.renderYearContent ? this.props.renderYearContent(y) : y;
   };
 
@@ -411,9 +310,6 @@ export default class Year extends Component<YearProps> {
     const yearsList = [];
     const { date, yearItemNumber, onYearMouseEnter, onYearMouseLeave } =
       this.props;
-    if (date === undefined) {
-      return null;
-    }
     const { startPeriod, endPeriod } = utils.getYearsPeriod(
       date,
       yearItemNumber,
@@ -434,7 +330,7 @@ export default class Year extends Component<YearProps> {
 
             this.onYearKeyDown(ev, y);
           }}
-          tabIndex={Number(this.getYearTabIndex(y))}
+          tabIndex={this.getYearTabIndex(y)}
           className={this.getYearClassNames(y)}
           onMouseEnter={
             !this.props.usePointerEvent


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f12a205a..d39c9203 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -44,9 +44,6 @@ jobs:
       - name: Check Code Formatter
         run: yarn prettier:check
 
-      - name: Type Check
-        run: yarn type-check
-
       - name: Lint
         run: yarn lint
 
diff --git a/test/year_picker_test.test.js b/test/year_picker_test.test.js
index 8d2bb6c3..2734b1e0 100644
--- a/test/year_picker_test.test.js
+++ b/test/year_picker_test.test.js
@@ -1,6 +1,6 @@
 import React from "react";
 import DatePicker from "../src/index.jsx";
-import Year from "../src/year.tsx";
+import Year from "../src/year.jsx";
 import { render, fireEvent } from "@testing-library/react";
 import * as utils from "../src/date_utils.ts";
 import { getKey } from "./test_utils.js";