KeyboardNavigation.tsx 1.6 KB

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