withKeyboardNavigation.tsx 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import React from 'react';
  2. import { Props } from './DataSourcePicker';
  3. interface State {
  4. selected: number;
  5. }
  6. const withKeyboardNavigation = WrappedComponent => {
  7. return class extends React.Component<Props, State> {
  8. constructor(props) {
  9. super(props);
  10. this.state = {
  11. selected: 0,
  12. };
  13. }
  14. goToNext = (maxSelectedIndex: number) => {
  15. const nextIndex = this.state.selected >= maxSelectedIndex ? 0 : this.state.selected + 1;
  16. this.setState({
  17. selected: nextIndex,
  18. });
  19. };
  20. goToPrev = (maxSelectedIndex: number) => {
  21. const nextIndex = this.state.selected <= 0 ? maxSelectedIndex : this.state.selected - 1;
  22. this.setState({
  23. selected: nextIndex,
  24. });
  25. };
  26. onKeyDown = (evt: KeyboardEvent, maxSelectedIndex: number, onEnterAction: any) => {
  27. if (evt.key === 'ArrowDown') {
  28. evt.preventDefault();
  29. this.goToNext(maxSelectedIndex);
  30. }
  31. if (evt.key === 'ArrowUp') {
  32. evt.preventDefault();
  33. this.goToPrev(maxSelectedIndex);
  34. }
  35. if (evt.key === 'Enter' && onEnterAction) {
  36. onEnterAction();
  37. }
  38. };
  39. onMouseEnter = (mouseEnterIndex: number) => {
  40. this.setState({
  41. selected: mouseEnterIndex,
  42. });
  43. };
  44. render() {
  45. return (
  46. <WrappedComponent
  47. selected={this.state.selected}
  48. onKeyDown={this.onKeyDown}
  49. onMouseEnter={this.onMouseEnter}
  50. {...this.props}
  51. />
  52. );
  53. }
  54. };
  55. };
  56. export default withKeyboardNavigation;