Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(DatePicker) Address datepicker crashing when manually entering year #10134

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 38 additions & 13 deletions packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@
validators?: ((date: Date) => boolean)[];
}

// Must be numeric given current header design
const yearFormat = (date: Date) => date.getFullYear();

const buildCalendar = (year: number, month: number, weekStart: number, validators: ((date: Date) => boolean)[]) => {
const defaultDate = new Date(year, month);

Expand Down Expand Up @@ -164,6 +161,13 @@
};
const initialDate = getInitialDate();
const [focusedDate, setFocusedDate] = React.useState(initialDate);

// Must be numeric given current header design
const yearFormat = (date: Date) => date.getFullYear();
//
const yearFormatted = yearFormat(focusedDate);
const [yearInput, setYearInput] = React.useState(yearFormatted.toString());

const [hoveredDate, setHoveredDate] = React.useState(new Date(focusedDate));
const focusRef = React.useRef<HTMLButtonElement>();
const [hiddenMonthId] = React.useState(getUniqueId('hidden-month-span'));
Expand All @@ -177,20 +181,21 @@
} else if (!dateProp) {
setFocusedDate(today);
}
}, [dateProp]);

Check warning on line 184 in packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'focusedDate'. Either include it or remove the dependency array

useEffect(() => {
// Calendar month should not be focused on page load
if ((shouldFocus || isDateFocused) && focusedDateValidated && focusRef.current) {
focusRef.current.focus();
}
}, [focusedDate, isDateFocused, focusedDateValidated, focusRef]);

Check warning on line 191 in packages/react-core/src/components/CalendarMonth/CalendarMonth.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook useEffect has a missing dependency: 'shouldFocus'. Either include it or remove the dependency array

const onMonthClick = (ev: React.MouseEvent, newDate: Date) => {
setFocusedDate(newDate);
setHoveredDate(newDate);
setShouldFocus(false);
onMonthChange(ev, newDate);
setYearInput(yearFormat(newDate).toString());
};

const onKeyDown = (ev: React.KeyboardEvent<HTMLTableSectionElement>) => {
Expand All @@ -217,6 +222,34 @@
const changeMonth = (newMonth: number, newYear?: number) =>
new Date(newYear ?? focusedDate.getFullYear(), newMonth, 1);

const MIN_YEAR = 1900;
const MAX_YEAR = 2100;

const handleYearInputChange = (event: React.FormEvent<HTMLInputElement>, yearStr: string) => {
if (!/^\d{0,4}$/.test(yearStr)) {
return;
}

setYearInput(yearStr);

if (yearStr.length === 4) {
const yearNum = Number(yearStr);

if (yearNum >= MIN_YEAR && yearNum <= MAX_YEAR) {
const newDate = changeYear(yearNum);
setFocusedDate(newDate);
setHoveredDate(newDate);
setShouldFocus(false);

// We need to manually focus the year input in FireFox when the scroll buttons are clicked, as FireFox doesn't place focus automatically
(event.target as HTMLElement).focus();
onMonthChange(event, newDate);
} else {
setYearInput(yearFormatted.toString());
}
}
};

const addMonth = (toAdd: -1 | 1) => {
let newMonth = focusedDate.getMonth() + toAdd;
let newYear = focusedDate.getFullYear();
Expand Down Expand Up @@ -254,7 +287,6 @@
}
const isHoveredDateValid = isValidated(hoveredDate);
const monthFormatted = monthFormat(focusedDate);
const yearFormatted = yearFormat(focusedDate);

const calendarToRender = (
<div className={css(styles.calendarMonth, className)} {...props}>
Expand Down Expand Up @@ -321,15 +353,8 @@
<TextInput
aria-label={yearInputAriaLabel}
type="number"
value={yearFormatted}
onChange={(ev: React.FormEvent<HTMLInputElement>, year: string) => {
const newDate = changeYear(Number(year));
setFocusedDate(newDate);
setHoveredDate(newDate);
setShouldFocus(false);
focusRef.current?.blur(); // will unfocus a date when changing year via up/down arrows
onMonthChange(ev, newDate);
}}
value={yearInput}
onChange={handleYearInputChange}
/>
</div>
</InputGroupItem>
Expand Down