github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/OverviewTableKeyboardShortcuts.tsx (about) 1 import React, { Component } from "react" 2 import { RowValues } from "./OverviewTableColumns" 3 import { 4 ResourceSelectionContext, 5 useResourceSelection, 6 } from "./ResourceSelectionContext" 7 import { isTargetEditable } from "./shortcut" 8 9 type Props = { 10 rows: RowValues[] 11 focused: string 12 setFocused: (focused: string) => void 13 selection: ResourceSelectionContext 14 } 15 16 /** 17 * Sets up keyboard shortcuts that depend on the state of the sidebar. 18 */ 19 class Shortcuts extends Component<Props> { 20 constructor(props: Props) { 21 super(props) 22 this.onKeydown = this.onKeydown.bind(this) 23 } 24 25 componentDidMount() { 26 document.body.addEventListener("keydown", this.onKeydown) 27 } 28 29 componentWillUnmount() { 30 document.body.removeEventListener("keydown", this.onKeydown) 31 } 32 33 onKeydown(e: KeyboardEvent) { 34 if (isTargetEditable(e) || e.shiftKey || e.altKey || e.isComposing) { 35 return 36 } 37 38 let items = this.props.rows 39 let focused = this.props.focused 40 let dir = 0 41 switch (e.key) { 42 case "Down": 43 case "ArrowDown": 44 case "j": 45 dir = 1 46 break 47 48 case "Up": 49 case "ArrowUp": 50 case "k": 51 dir = -1 52 break 53 54 case "x": 55 if (e.metaKey || e.ctrlKey) { 56 return 57 } 58 let item = items.find((item) => item.name == focused) 59 if (item && item.selectable) { 60 let selection = this.props.selection 61 if (selection.isSelected(item.name)) { 62 this.props.selection.deselect(item.name) 63 } else { 64 this.props.selection.select(item.name) 65 } 66 e.preventDefault() 67 } 68 break 69 } 70 71 if (dir != 0) { 72 // Select up and down the list. 73 let names = items.map((item) => item.name) 74 let index = names.indexOf(focused) 75 let targetIndex = 0 76 if (index != -1) { 77 let dir = e.key === "j" ? 1 : -1 78 targetIndex = index + dir 79 } 80 81 if (targetIndex < 0 || targetIndex >= names.length) { 82 return 83 } 84 85 let name = names[targetIndex] 86 this.props.setFocused(name) 87 e.preventDefault() 88 return 89 } 90 } 91 92 render() { 93 return <span></span> 94 } 95 } 96 97 type PublicProps = { 98 rows: RowValues[] 99 focused: string 100 setFocused: (focused: string) => void 101 } 102 103 export function OverviewTableKeyboardShortcuts(props: PublicProps) { 104 let selection = useResourceSelection() 105 return <Shortcuts {...props} selection={selection} /> 106 }