github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/SharedQueryInput.tsx (about) 1 /* eslint-disable no-unused-expressions */ 2 import React, { useEffect, useMemo, ChangeEvent, useRef } from 'react'; 3 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 4 import { faLink } from '@fortawesome/free-solid-svg-icons/faLink'; 5 import Input from '@pyroscope/webapp/javascript/ui/Input'; 6 import { Tooltip } from '@pyroscope/webapp/javascript/ui/Tooltip'; 7 import styles from './SharedQueryInput.module.scss'; 8 import type { ProfileHeaderProps } from './Toolbar'; 9 10 interface SharedQueryProps { 11 onHighlightChange: ProfileHeaderProps['handleSearchChange']; 12 highlightQuery: ProfileHeaderProps['highlightQuery']; 13 sharedQuery: ProfileHeaderProps['sharedQuery']; 14 width: number; 15 } 16 17 const usePreviousSyncEnabled = (syncEnabled?: string | boolean) => { 18 const ref = useRef(); 19 20 useEffect(() => { 21 (ref.current as string | boolean | undefined) = syncEnabled; 22 }); 23 24 return ref.current; 25 }; 26 27 const SharedQueryInput = ({ 28 onHighlightChange, 29 highlightQuery, 30 sharedQuery, 31 width, 32 }: SharedQueryProps) => { 33 const prevSyncEnabled = usePreviousSyncEnabled(sharedQuery?.syncEnabled); 34 35 const onQueryChange = (e: ChangeEvent<HTMLInputElement>) => { 36 onHighlightChange(e.target.value); 37 38 if (sharedQuery && sharedQuery.syncEnabled) { 39 sharedQuery.onQueryChange(e.target.value); 40 } 41 }; 42 43 useEffect(() => { 44 if (typeof sharedQuery?.searchQuery === 'string') { 45 if (sharedQuery.syncEnabled) { 46 onHighlightChange(sharedQuery.searchQuery); 47 } 48 49 if ( 50 !sharedQuery.syncEnabled && 51 prevSyncEnabled && 52 prevSyncEnabled !== sharedQuery?.id 53 ) { 54 onHighlightChange(''); 55 } 56 } 57 }, [sharedQuery?.searchQuery, sharedQuery?.syncEnabled]); 58 59 const onToggleSync = () => { 60 const newValue = sharedQuery?.syncEnabled ? false : sharedQuery?.id; 61 sharedQuery?.toggleSync(newValue as string | false); 62 63 if (newValue) { 64 sharedQuery?.onQueryChange(highlightQuery); 65 } else { 66 onHighlightChange(highlightQuery); 67 sharedQuery?.onQueryChange(''); 68 } 69 }; 70 71 const inputValue = useMemo( 72 () => 73 sharedQuery && sharedQuery.syncEnabled 74 ? sharedQuery.searchQuery || '' 75 : highlightQuery, 76 [sharedQuery, highlightQuery] 77 ); 78 79 const inputClassName = useMemo( 80 () => 81 `${sharedQuery ? styles.searchWithSync : styles.search} ${ 82 sharedQuery?.syncEnabled ? styles['search-synced'] : '' 83 }`, 84 [sharedQuery] 85 ); 86 87 return ( 88 <div className={styles.wrapper} style={{ width }}> 89 <Input 90 testId="flamegraph-search" 91 className={inputClassName} 92 type="search" 93 name="flamegraph-search" 94 placeholder="Search…" 95 minLength={2} 96 debounceTimeout={100} 97 onChange={onQueryChange} 98 value={inputValue} 99 /> 100 {sharedQuery ? ( 101 <Tooltip 102 placement="top" 103 title={ 104 sharedQuery.syncEnabled ? 'Unsync search bars' : 'Sync search bars' 105 } 106 > 107 <button 108 className={ 109 sharedQuery.syncEnabled ? styles.syncSelected : styles.sync 110 } 111 onClick={onToggleSync} 112 > 113 <FontAwesomeIcon 114 className={`${ 115 sharedQuery.syncEnabled ? styles.checked : styles.icon 116 }`} 117 icon={faLink} 118 /> 119 </button> 120 </Tooltip> 121 ) : null} 122 </div> 123 ); 124 }; 125 126 export default SharedQueryInput;