import React, { Component } from "react"; import { addMonths, addYears, subYears, formatDate, getStartOfMonth, isAfter, isSameMonth, isSameYear, newDate, getTime, type Locale, } from "./date_utils"; import MonthYearDropdownOptions from "./month_year_dropdown_options"; // Default range: 5 years before and after current date const DEFAULT_YEAR_RANGE = 5; interface MonthYearDropdownOptionsProps extends React.ComponentPropsWithoutRef< typeof MonthYearDropdownOptions > {} interface MonthYearDropdownProps extends Omit< MonthYearDropdownOptionsProps, "onChange" | "onCancel" > { dropdownMode: "scroll" | "select"; onChange: (monthYear: Date) => void; locale?: Locale; } interface MonthYearDropdownState { dropdownVisible: boolean; } export default class MonthYearDropdown extends Component< MonthYearDropdownProps, MonthYearDropdownState > { state: MonthYearDropdownState = { dropdownVisible: false, }; renderSelectOptions = (): React.ReactElement[] => { // Use defaults if minDate/maxDate not provided const minDate = this.props.minDate ?? subYears(this.props.date, DEFAULT_YEAR_RANGE); const maxDate = this.props.maxDate ?? addYears(this.props.date, DEFAULT_YEAR_RANGE); let currDate = getStartOfMonth(minDate); const lastDate = getStartOfMonth(maxDate); const options = []; while (!isAfter(currDate, lastDate)) { const timePoint = getTime(currDate); options.push( , ); currDate = addMonths(currDate, 1); } return options; }; onSelectChange = (event: React.ChangeEvent): void => { this.onChange(parseInt(event.target.value)); }; renderSelectMode = (): React.ReactElement => ( ); renderReadView = (visible: boolean): React.ReactElement => { const yearMonth = formatDate( this.props.date, this.props.dateFormat, this.props.locale, ); return (
{yearMonth}
); }; renderDropdown = (): React.ReactElement => ( ); renderScrollMode = (): React.ReactElement[] => { const { dropdownVisible } = this.state; const result = [this.renderReadView(!dropdownVisible)]; if (dropdownVisible) { result.unshift(this.renderDropdown()); } return result; }; onChange = (monthYearPoint: number): void => { this.toggleDropdown(); const changedDate = newDate(monthYearPoint); if ( isSameYear(this.props.date, changedDate) && isSameMonth(this.props.date, changedDate) ) { return; } this.props.onChange(changedDate); }; toggleDropdown = (): void => this.setState({ dropdownVisible: !this.state.dropdownVisible, }); render(): React.ReactElement { let renderedDropdown; switch (this.props.dropdownMode) { case "scroll": renderedDropdown = this.renderScrollMode(); break; case "select": renderedDropdown = this.renderSelectMode(); break; } return (
{renderedDropdown}
); } }