github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/components/QueryInput/QueryInput.tsx (about) 1 import React, { useState, useEffect, useRef } from 'react'; 2 import { useWindowWidth } from '@react-hook/window-size'; 3 import TextareaAutosize from 'react-textarea-autosize'; 4 import cx from 'classnames'; 5 6 import { Query, brandQuery } from '@webapp/models/query'; 7 import { Prism } from '@webapp/util/prism'; 8 import Button from '@webapp/ui/Button'; 9 10 import styles from './QueryInput.module.scss'; 11 12 interface QueryInputProps { 13 initialQuery: Query; 14 onSubmit: (query: string) => void; 15 } 16 17 /** 18 * QueryInput refers to the input box used for queries 19 */ 20 export default function QueryInput({ 21 initialQuery, 22 onSubmit, 23 }: QueryInputProps) { 24 const windowWidth = useWindowWidth(); 25 const [query, setQuery] = useState(initialQuery); 26 const codeRef = useRef<HTMLElement>(null); 27 const textareaRef = useRef<ShamefulAny>(null); 28 const [textAreaSize, setTextAreaSize] = useState({ width: 0, height: 0 }); 29 30 // If query updated upstream, most likely the application changed 31 // So we prefer to use it 32 useEffect(() => { 33 setQuery(initialQuery); 34 }, [initialQuery]); 35 36 useEffect(() => { 37 if (Prism && codeRef.current) { 38 Prism.highlightElement(codeRef.current); 39 } 40 }, [query]); 41 42 useEffect(() => { 43 setTextAreaSize({ 44 width: textareaRef?.current?.['offsetWidth'] || 0, 45 height: textareaRef?.current?.['offsetHeight'] || 0, 46 }); 47 }, [query, windowWidth, onSubmit]); 48 49 const onFormSubmit = ( 50 e: 51 | React.FormEvent<HTMLFormElement> 52 | React.KeyboardEvent<HTMLTextAreaElement> 53 ) => { 54 e.preventDefault(); 55 onSubmit(query); 56 }; 57 58 const handleTextareaKeyDown = ( 59 e: React.KeyboardEvent<HTMLTextAreaElement> 60 ) => { 61 if (e.key === 'Enter' || e.keyCode === 13 || e.keyCode === 10) { 62 onFormSubmit(e); 63 } 64 }; 65 66 return ( 67 <form 68 aria-label="query-input" 69 className={styles.wrapper} 70 onSubmit={onFormSubmit} 71 > 72 <pre 73 className={cx(styles.highlight, 'language-promql')} 74 aria-hidden="true" 75 > 76 <code 77 className="language-promql" 78 id="highlighting-content" 79 ref={codeRef} 80 style={textAreaSize} 81 > 82 {query} 83 </code> 84 </pre> 85 <TextareaAutosize 86 className={styles.input} 87 ref={textareaRef} 88 value={query} 89 spellCheck="false" 90 onChange={(e) => setQuery(brandQuery(e.target.value))} 91 onKeyDown={handleTextareaKeyDown} 92 /> 93 <Button 94 type="submit" 95 kind="secondary" 96 grouped 97 className={styles.executeButton} 98 > 99 Execute 100 </Button> 101 </form> 102 ); 103 }