import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
import BackIcon from '../../../components/icons/BackIcon';
import '../../../components/search-navigator.css';
-import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
+import { isDatePicker, isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import {
}
attachShortcuts = () => {
- document.addEventListener('keydown', this.handleKeyPress);
+ document.addEventListener('keydown', this.handleKeyDown);
};
- handleKeyPress = (event: KeyboardEvent) => {
+ handleKeyDown = (event: KeyboardEvent) => {
if (isInput(event) || isShortcut(event)) {
- return true;
+ return;
}
+
+ // Ignore if date picker is open (to be removed when upgrading to React 17+)
+ if (isDatePicker(event)) {
+ return;
+ }
+
switch (event.key) {
case KeyboardKeys.LeftArrow:
event.preventDefault();
};
detachShortcuts = () => {
- document.removeEventListener('keydown', this.handleKeyPress);
+ document.removeEventListener('keydown', this.handleKeyDown);
};
getOpenRule = (rules: Rule[]) => {
} from '../../../helpers/branch-like';
import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication';
import { parseIssueFromResponse } from '../../../helpers/issues';
-import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
+import { isDatePicker, isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import {
}
if (isInput(event) || isShortcut(event)) {
- return true;
+ return;
+ }
+
+ // Ignore if date picker is open (to be removed when upgrading to React 17+)
+ if (isDatePicker(event)) {
+ return;
}
if (event.key === KeyboardKeys.Alt) {
export function isShortcut(event: KeyboardEvent): boolean {
return event.ctrlKey || event.metaKey;
}
-export function isTextarea(event: KeyboardEvent): boolean {
- const { tagName } = event.target as HTMLElement;
- return ['TEXTAREA'].includes(tagName);
+
+export function isTextarea(
+ event: KeyboardEvent
+): event is KeyboardEvent & { target: HTMLTextAreaElement } {
+ return event.target instanceof HTMLTextAreaElement;
+}
+
+export function isInput(
+ event: KeyboardEvent
+): event is KeyboardEvent & { target: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement } {
+ return (
+ event.target instanceof HTMLInputElement ||
+ event.target instanceof HTMLSelectElement ||
+ event.target instanceof HTMLTextAreaElement
+ );
}
-export function isInput(event: KeyboardEvent): boolean {
- const { tagName } = event.target as HTMLElement;
- return ['INPUT', 'SELECT', 'TEXTAREA'].includes(tagName);
+/*
+ * Due to React 16 event delegation, stopPropagation called within react-day-picker is NOT preventing other event handlers from being called.
+ * As a temporary workaround, we detect this special case using this utility function.
+ * This utility function can be removed once we upgrade to React 17, since although there is still event delegation,
+ * it is delegated up to the React root, which will stop propagation before it reaches document event handlers.
+ */
+export function isDatePicker(event: KeyboardEvent): boolean {
+ return event.target instanceof Element && event.target.matches('.rdp-day');
}