* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import key from 'keymaster';
import { debounce, keyBy, uniqBy } from 'lodash';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import ClockIcon from '../../../components/icons/ClockIcon';
import { lazyLoadComponent } from '../../../components/lazyLoadComponent';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
-import { KeyboardCodes } from '../../../helpers/keycodes';
+import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { scrollToElement } from '../../../helpers/scrolling';
import { getComponentOverviewUrl } from '../../../helpers/urls';
componentDidMount() {
this.mounted = true;
- key('s', () => {
- this.focusInput();
- this.openSearch();
- return false;
- });
+ document.addEventListener('keydown', this.handleSKeyDown);
}
componentDidUpdate(_prevProps: WithRouterProps, prevState: State) {
componentWillUnmount() {
this.mounted = false;
- key.unbind('s');
+ document.removeEventListener('keydown', this.handleSKeyDown);
}
focusInput = () => {
const list = this.getPlainComponentsList(results, more);
const index = list.indexOf(selected);
return index > 0 ? { selected: list[index - 1] } : null;
- } else {
- return null;
}
+ return null;
});
};
const list = this.getPlainComponentsList(results, more);
const index = list.indexOf(selected);
return index >= 0 && index < list.length - 1 ? { selected: list[index + 1] } : null;
- } else {
- return null;
}
+ return null;
});
};
}
};
+ handleSKeyDown = (event: KeyboardEvent) => {
+ const { tagName } = event.target as HTMLElement;
+ const isInput = tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
+ if (event.key === KeyboardKeys.KeyS && !isInput) {
+ event.preventDefault();
+ this.focusInput();
+ this.openSearch();
+ }
+ };
+
handleKeyDown = (event: React.KeyboardEvent) => {
- switch (event.nativeEvent.code) {
- case KeyboardCodes.Enter:
+ switch (event.nativeEvent.key) {
+ case KeyboardKeys.Enter:
event.preventDefault();
+ event.nativeEvent.stopImmediatePropagation();
this.openSelected();
- return;
- case KeyboardCodes.UpArrow:
+ break;
+ case KeyboardKeys.UpArrow:
event.preventDefault();
+ event.nativeEvent.stopImmediatePropagation();
this.selectPrevious();
- return;
- case KeyboardCodes.DownArrow:
+ break;
+ case KeyboardKeys.Escape:
+ event.preventDefault();
+ event.nativeEvent.stopImmediatePropagation();
+ this.closeSearch();
+ break;
+ case KeyboardKeys.DownArrow:
event.preventDefault();
+ event.nativeEvent.stopImmediatePropagation();
this.selectNext();
- // keep this return to prevent fall-through in case more cases will be adder later
- // eslint-disable-next-line no-useless-return
- return;
+ break;
}
};
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
-import { KeyboardCodes } from '../../../../helpers/keycodes';
+import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockRouter } from '../../../../helpers/testMocks';
-import { elementKeydown } from '../../../../helpers/testUtils';
+import { elementKeydown, keydown } from '../../../../helpers/testUtils';
import { ComponentQualifier } from '../../../../types/component';
import { Search } from '../Search';
selected: selectedKey
});
- elementKeydown(form.find('SearchBox'), KeyboardCodes.Enter);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.Enter);
expect(router.push).toBeCalledWith({ pathname: '/dashboard', query: { id: selectedKey } });
});
selected: selectedKey
});
- elementKeydown(form.find('SearchBox'), KeyboardCodes.Enter);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.Enter);
expect(router.push).toBeCalledWith({ pathname: '/portfolio', query: { id: selectedKey } });
});
selected: selectedKey
});
- elementKeydown(form.find('SearchBox'), KeyboardCodes.Enter);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.Enter);
expect(router.push).toBeCalledWith({ pathname: '/portfolio', query: { id: selectedKey } });
});
expect(form.find('.navbar-search-input-hint')).toMatchSnapshot();
});
+it('should open the results when pressing key S and close it when pressing Escape', () => {
+ const router = mockRouter();
+ const form = shallowRender({ router });
+ keydown({ key: KeyboardKeys.KeyS });
+ expect(form.state().open).toBe(true);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.Escape);
+ expect(form.state().open).toBe(false);
+});
+
function shallowRender(props: Partial<Search['props']> = {}) {
return shallow<Search>(
// @ts-ignore
}
function next(form: ShallowWrapper<Search['props'], Search['state']>, expected: string) {
- elementKeydown(form.find('SearchBox'), KeyboardCodes.DownArrow);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.DownArrow);
expect(form.state().selected).toBe(expected);
}
function prev(form: ShallowWrapper<Search['props'], Search['state']>, expected: string) {
- elementKeydown(form.find('SearchBox'), KeyboardCodes.UpArrow);
+ elementKeydown(form.find('SearchBox'), KeyboardKeys.UpArrow);
expect(form.state().selected).toBe(expected);
}