Skip to content

Commit

Permalink
🐛 Address datepicker crashing when manually entering year (patternfly…
Browse files Browse the repository at this point in the history
  • Loading branch information
ibolton336 authored and tlabaj committed Mar 15, 2024
1 parent 193cb22 commit d7f1121
Showing 1 changed file with 38 additions and 13 deletions.
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 @@ export interface CalendarProps extends CalendarFormat, Omit<React.HTMLProps<HTML
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 @@ export const CalendarMonth = ({
};
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 Down Expand Up @@ -191,6 +195,7 @@ export const CalendarMonth = ({
setHoveredDate(newDate);
setShouldFocus(false);
onMonthChange(ev, newDate);
setYearInput(yearFormat(newDate).toString());
};

const onKeyDown = (ev: React.KeyboardEvent<HTMLTableSectionElement>) => {
Expand All @@ -217,6 +222,34 @@ export const CalendarMonth = ({
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 @@ export const CalendarMonth = ({
}
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 @@ export const CalendarMonth = ({
<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

0 comments on commit d7f1121

Please sign in to comment.