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  }