Commit 40025c02 authored by tom's avatar tom

search settings

parent f56d412e
import { Accordion, Box, Input, useColorModeValue } from '@chakra-ui/react'; import type { ChakraProps } from '@chakra-ui/react';
import { Accordion, Box, Input, InputGroup, InputRightElement, useColorModeValue, useBoolean } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { File, Monaco, SearchResult } from './types'; import type { File, Monaco, SearchResult } from './types';
...@@ -20,6 +21,9 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -20,6 +21,9 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
const [ searchTerm, changeSearchTerm ] = React.useState(''); const [ searchTerm, changeSearchTerm ] = React.useState('');
const [ searchResults, setSearchResults ] = React.useState<Array<SearchResult>>([]); const [ searchResults, setSearchResults ] = React.useState<Array<SearchResult>>([]);
const [ expandedSections, setExpandedSections ] = React.useState<Array<number>>([]); const [ expandedSections, setExpandedSections ] = React.useState<Array<number>>([]);
const [ isMatchCase, setMatchCase ] = useBoolean();
const [ isMatchWholeWord, setMatchWholeWord ] = useBoolean();
const [ isMatchRegex, setMatchRegex ] = useBoolean();
const debouncedSearchTerm = useDebounce(searchTerm, 300); const debouncedSearchTerm = useDebounce(searchTerm, 300);
...@@ -34,7 +38,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -34,7 +38,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
const result: Array<SearchResult> = monaco.editor.getModels() const result: Array<SearchResult> = monaco.editor.getModels()
.map((model) => { .map((model) => {
const matches = model.findMatches(debouncedSearchTerm, false, false, false, null, false); const matches = model.findMatches(debouncedSearchTerm, false, isMatchRegex, isMatchCase, isMatchWholeWord ? 'true' : null, false);
return { return {
file_path: model.uri.path, file_path: model.uri.path,
matches: matches.map(({ range }) => ({ ...range, lineContent: model.getLineContent(range.startLineNumber) })), matches: matches.map(({ range }) => ({ ...range, lineContent: model.getLineContent(range.startLineNumber) })),
...@@ -43,7 +47,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -43,7 +47,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
.filter(({ matches }) => matches.length > 0); .filter(({ matches }) => matches.length > 0);
setSearchResults(result.length > 0 ? result : []); setSearchResults(result.length > 0 ? result : []);
}, [ debouncedSearchTerm, monaco ]); }, [ debouncedSearchTerm, isMatchCase, isMatchRegex, isMatchWholeWord, monaco ]);
React.useEffect(() => { React.useEffect(() => {
setExpandedSections(searchResults.map((item, index) => index)); setExpandedSections(searchResults.map((item, index) => index));
...@@ -75,7 +79,16 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -75,7 +79,16 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
const inputColor = useColorModeValue('rgb(97, 97, 97)', 'rgb(204, 204, 204)'); const inputColor = useColorModeValue('rgb(97, 97, 97)', 'rgb(204, 204, 204)');
const inputBgColor = useColorModeValue('white', 'rgb(60, 60, 60)'); const inputBgColor = useColorModeValue('white', 'rgb(60, 60, 60)');
const inputFocusBorderColor = useColorModeValue('#0090f1', '#007fd4'); const inputFocusBorderColor = useColorModeValue('#0090f1', '#007fd4');
const buttonActiveBgColor = useColorModeValue('rgba(0, 144, 241, 0.2)', 'rgba(0, 127, 212, 0.4)');
const colors = useColors(); const colors = useColors();
const buttonProps: ChakraProps = {
boxSize: '20px',
p: '1px',
cursor: 'pointer',
borderRadius: '3px',
borderWidth: '1px',
borderColor: 'transparent',
};
return ( return (
<Box> <Box>
...@@ -85,7 +98,16 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -85,7 +98,16 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
isDisabled={ searchResults.length === 0 } isDisabled={ searchResults.length === 0 }
isCollapsed={ expandedSections.length === 0 } isCollapsed={ expandedSections.length === 0 }
/> />
<Box px={ 2 } position="sticky" top="35px" left="0" zIndex="2" bgColor={ colors.panels.bgColor } pb="8px" boxShadow={ isInputStuck ? 'md' : 'none' }> <InputGroup
px="8px"
position="sticky"
top="35px"
left="0"
zIndex="2"
bgColor={ colors.panels.bgColor }
pb="8px"
boxShadow={ isInputStuck ? 'md' : 'none' }
>
<Input <Input
size="xs" size="xs"
onChange={ handleSearchTermChange } onChange={ handleSearchTermChange }
...@@ -96,7 +118,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -96,7 +118,7 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
bgColor={ inputBgColor } bgColor={ inputBgColor }
borderRadius="none" borderRadius="none"
fontSize="13px" fontSize="13px"
lineHeight="19px" lineHeight="20px"
borderWidth="1px" borderWidth="1px"
borderColor={ inputBgColor } borderColor={ inputBgColor }
py="2px" py="2px"
...@@ -106,14 +128,43 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) = ...@@ -106,14 +128,43 @@ const CodeEditorSearch = ({ monaco, data, onFileSelect, isInputStuck }: Props) =
borderColor: inputFocusBorderColor, borderColor: inputFocusBorderColor,
}} }}
/> />
</Box> <InputRightElement w="auto" h="auto" right="12px" top="3px" columnGap="2px">
<Box
{ ...buttonProps }
className="codicon codicon-case-sensitive"
onClick={ setMatchCase.toggle }
bgColor={ isMatchCase ? buttonActiveBgColor : 'transparent' }
_hover={{ bgColor: isMatchCase ? buttonActiveBgColor : colors.buttons.bgColorHover }}
title="Match Case"
aria-label="Match Case"
/>
<Box
{ ...buttonProps }
className="codicon codicon-whole-word"
bgColor={ isMatchWholeWord ? buttonActiveBgColor : 'transparent' }
onClick={ setMatchWholeWord.toggle }
_hover={{ bgColor: isMatchWholeWord ? buttonActiveBgColor : colors.buttons.bgColorHover }}
title="Match Whole Word"
aria-label="Match Whole Word"
/>
<Box
{ ...buttonProps }
className="codicon codicon-regex"
bgColor={ isMatchRegex ? buttonActiveBgColor : 'transparent' }
onClick={ setMatchRegex.toggle }
_hover={{ bgColor: isMatchRegex ? buttonActiveBgColor : colors.buttons.bgColorHover }}
title="Use Regular Expression"
aria-label="Use Regular Expression"
/>
</InputRightElement>
</InputGroup>
<Accordion <Accordion
key={ debouncedSearchTerm } key={ debouncedSearchTerm }
allowMultiple allowMultiple
index={ expandedSections } index={ expandedSections }
onChange={ handleAccordionStateChange } onChange={ handleAccordionStateChange }
reduceMotion reduceMotion
mt={ 3 } mt="4px"
> >
{ searchResults.map((item) => <CodeEditorSearchSection key={ item.file_path } data={ item } onItemClick={ handleResultItemClick }/>) } { searchResults.map((item) => <CodeEditorSearchSection key={ item.file_path } data={ item } onItemClick={ handleResultItemClick }/>) }
</Accordion> </Accordion>
......
import { Flex, IconButton, Icon, chakra, useColorModeValue } from '@chakra-ui/react'; import { Flex, Icon, chakra, useColorModeValue, Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import iconCross from 'icons/cross.svg';
import iconFile from './icons/file.svg'; import iconFile from './icons/file.svg';
import iconSolidity from './icons/solidity.svg'; import iconSolidity from './icons/solidity.svg';
import getFilePathParts from './utils/getFilePathParts'; import getFilePathParts from './utils/getFilePathParts';
...@@ -40,7 +38,7 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs ...@@ -40,7 +38,7 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
return ( return (
<Flex <Flex
pl="10px" pl="10px"
pr={ isActive ? '4px' : '28px' } pr="4px"
fontSize="13px" fontSize="13px"
lineHeight="34px" lineHeight="34px"
bgColor={ isActive ? bgColor : bgColorInactive } bgColor={ isActive ? bgColor : bgColorInactive }
...@@ -54,9 +52,8 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs ...@@ -54,9 +52,8 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
cursor="pointer" cursor="pointer"
onClick={ handleClick } onClick={ handleClick }
_hover={{ _hover={{
pr: '4px', '.codicon-close': {
svg: { visibility: 'visible',
display: 'block',
}, },
}} }}
userSelect="none" userSelect="none"
...@@ -64,19 +61,19 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs ...@@ -64,19 +61,19 @@ const CodeEditorTab = ({ isActive, path, onClick, onClose, isCloseDisabled, tabs
<Icon as={ icon } boxSize="16px" mr="4px"/> <Icon as={ icon } boxSize="16px" mr="4px"/>
<span>{ fileName }</span> <span>{ fileName }</span>
{ folderName && <chakra.span fontSize="xs" color="text_secondary" ml={ 1 }>{ folderName[0] === '.' ? '' : '...' }{ folderName }</chakra.span> } { folderName && <chakra.span fontSize="xs" color="text_secondary" ml={ 1 }>{ folderName[0] === '.' ? '' : '...' }{ folderName }</chakra.span> }
<IconButton <Box
as={ iconCross } className="codicon codicon-close"
boxSize={ 5 } boxSize="20px"
ml="4px" ml="4px"
p="2px" p="2px"
variant="unstyled" title="Close"
aria-label="close" aria-label="Close"
onClick={ handleClose } onClick={ handleClose }
isDisabled={ isCloseDisabled }
display={ isActive ? 'block' : 'none' }
borderRadius="sm" borderRadius="sm"
opacity={ isCloseDisabled ? 0.3 : 1 }
visibility={ isActive ? 'visible' : 'hidden' }
color={ colors.buttons.color } color={ colors.buttons.color }
_hover={{ bgColor: colors.buttons.bgColorHover }} _hover={{ bgColor: isCloseDisabled ? 'transparent' : colors.buttons.bgColorHover }}
/> />
</Flex> </Flex>
); );
......
import { Tooltip, Box } from '@chakra-ui/react'; import { Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useColors from './utils/useColors'; import useColors from './utils/useColors';
...@@ -13,27 +13,27 @@ interface Props { ...@@ -13,27 +13,27 @@ interface Props {
const CoderEditorCollapseButton = ({ onClick, label, isDisabled, isCollapsed }: Props) => { const CoderEditorCollapseButton = ({ onClick, label, isDisabled, isCollapsed }: Props) => {
const colors = useColors(); const colors = useColors();
return ( return (
<Tooltip label={ label } isDisabled={ isDisabled }> <Box
<Box position="absolute"
position="absolute" right="12px"
right="12px" top="8px"
top="8px" zIndex="sticky1"
zIndex="sticky1" className={ isCollapsed ? 'codicon codicon-search-expand-results' : 'codicon codicon-collapse-all' }
className={ isCollapsed ? 'codicon codicon-search-expand-results' : 'codicon codicon-collapse-all' } opacity={ isDisabled ? 0.6 : 1 }
opacity={ isDisabled ? 0.6 : 1 } boxSize="20px"
boxSize="20px" p="2px"
p="2px" borderRadius="sm"
borderRadius="sm" _before={{
_before={{ content: isCollapsed ? '"\\eb95"' : '"\\eac5"',
content: isCollapsed ? '"\\eb95"' : '"\\eac5"', }}
}} _hover={{
_hover={{ bgColor: colors.buttons.bgColorHover,
bgColor: colors.buttons.bgColorHover, }}
}} onClick={ onClick }
onClick={ onClick } cursor="pointer"
cursor="pointer" title={ label }
/> aria-label={ label }
</Tooltip> />
); );
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment