/* * SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. * * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ import React from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import FocusTrap from "focus-trap-react"; import { ScreenReaderOnly } from "./screen_reader_only"; function generateYears(year, noOfYear, minDate, maxDate) { var list = []; for (var i = 0; i < 2 * noOfYear + 1; i++) { const newYear = year + noOfYear - i; let isInRange = true; if (minDate) { isInRange = minDate.year() <= newYear; } if (maxDate && isInRange) { isInRange = maxDate.year() >= newYear; } if (isInRange) { list.push(newYear); } } return list; } export default class YearDropdownOptions extends React.Component { static propTypes = { minDate: PropTypes.object, maxDate: PropTypes.object, onCancel: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired, scrollableYearDropdown: PropTypes.bool, year: PropTypes.number.isRequired, yearDropdownItemNumber: PropTypes.number, accessibleMode: PropTypes.bool }; constructor(props) { super(props); const { yearDropdownItemNumber, scrollableYearDropdown } = props; const noOfYear = yearDropdownItemNumber || (scrollableYearDropdown ? 10 : 5); this.state = { yearsList: generateYears( this.props.year, noOfYear, this.props.minDate, this.props.maxDate ), preSelection: this.props.year, readInstructions: false }; } componentDidMount() { if (this.preSelectionDiv) { this.preSelectionDiv.scrollIntoView({ behavior: "instant", block: "nearest", inline: "nearest" }); } } componentDidUpdate(prevProps, prevState) { if ( this.preSelectionDiv && prevState.preSelection !== this.state.preSelection ) { this.preSelectionDiv.scrollIntoView({ behavior: "instant", block: "nearest", inline: "nearest" }); } } renderOptions = () => { var selectedYear = this.props.year; var options = this.state.yearsList.map(year => (
{ if (this.props.accessibleMode && this.state.preSelection === year) { this.preSelectionDiv = div; } }} onClick={this.onChange.bind(this, year)} > {selectedYear === year ? ( ) : ( "" )} {year}
)); const minYear = this.props.minDate ? this.props.minDate.year() : null; const maxYear = this.props.maxDate ? this.props.maxDate.year() : null; if (!maxYear || !this.state.yearsList.find(year => year === maxYear)) { options.unshift(
); } if (!minYear || !this.state.yearsList.find(year => year === minYear)) { options.push(
); } return options; }; onFocus = () => { if (this.props.accessibleMode) { this.setState({ readInstructions: true }); } }; onChange = year => { this.props.onChange(year); }; handleClickOutside = () => { this.props.onCancel(); }; shiftYears = amount => { var years = this.state.yearsList.map(function(year) { return year + amount; }); this.setState({ yearsList: years }); }; incrementYears = () => { return this.shiftYears(1); }; decrementYears = () => { return this.shiftYears(-1); }; onInputKeyDown = event => { const eventKey = event.key; let selectionChange = 0; switch (eventKey) { case "ArrowUp": event.preventDefault(); event.stopPropagation(); selectionChange = -1; break; case "ArrowDown": event.preventDefault(); event.stopPropagation(); selectionChange = 1; break; case "Escape": event.preventDefault(); event.stopPropagation(); this.props.onCancel(); break; case " ": case "Enter": event.preventDefault(); event.stopPropagation(); this.props.onChange(this.state.preSelection); break; } if (selectionChange) { this.setState(({ preSelection }) => { const maxYear = this.state.yearsList[0]; const minYear = this.state.yearsList[this.state.yearsList.length - 1]; let nextSelection = preSelection + selectionChange; if (nextSelection < minYear) nextSelection = maxYear; if (nextSelection > maxYear) nextSelection = minYear; return { preSelection: nextSelection }; }); } }; render() { let dropdownClass = classNames({ "react-datepicker__year-dropdown": true, "react-datepicker__year-dropdown--scrollable": this.props .scrollableYearDropdown }); let screenReaderInstructions; if (this.state.readInstructions) { screenReaderInstructions = (

You are focused on a year selector menu. Use the up and down arrows to select a year, then hit enter to confirm your selection. {this.state.preSelection} is the currently focused year.

); } return this.props.accessibleMode ? (
{screenReaderInstructions} {this.renderOptions()}
) : (
{this.renderOptions()}
); } }