mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-12 20:18:41 -09:00
search box overhaul
This commit is contained in:
parent
502cdbb3b2
commit
9ab2ba9f08
7 changed files with 351 additions and 93 deletions
|
|
@ -1,29 +0,0 @@
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<defs>
|
|
||||||
<symbol id="left-arrow" viewBox="0 0 10 10">
|
|
||||||
<title>left arrow</title>
|
|
||||||
<g stroke-linecap="round">
|
|
||||||
<line x1="0.5" y1="5" x2="8.5" y2="5" stroke="#000" />
|
|
||||||
<line x1="0.5" y1="5" x2="3.5" y2="2" stroke="#000" />
|
|
||||||
<line x1="0.5" y1="5" x2="3.5" y2="8" stroke="#000" />
|
|
||||||
</g>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="right-arrow" viewBox="0 0 10 10">
|
|
||||||
<title>right arrow</title>
|
|
||||||
<g stroke-linecap="round">
|
|
||||||
<line x1="1.5" y1="5" x2="9.5" y2="5" stroke="#000" />
|
|
||||||
<line x1="9.5" y1="5" x2="6.5" y2="2" stroke="#000" />
|
|
||||||
<line x1="9.5" y1="5" x2="6.5" y2="8" stroke="#000" />
|
|
||||||
</g>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="cancel" viewBox="0 0 10 10">
|
|
||||||
<title>cancel</title>
|
|
||||||
<g stroke-linecap="round">
|
|
||||||
<line x1="5" y1="5" x2="8" y2="8" stroke="#000" />
|
|
||||||
<line x1="5" y1="5" x2="8" y2="2" stroke="#000" />
|
|
||||||
<line x1="5" y1="5" x2="2" y2="2" stroke="#000" />
|
|
||||||
<line x1="5" y1="5" x2="2" y2="8" stroke="#000" />
|
|
||||||
</g>
|
|
||||||
</symbol>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,76 +1,254 @@
|
||||||
import React from 'react';
|
import React, {useCallback} from 'react';
|
||||||
import {SearchBoxProps} from '../hyper';
|
import {SearchBoxProps} from '../hyper';
|
||||||
|
import {VscArrowUp} from '@react-icons/all-files/vsc/VscArrowUp';
|
||||||
|
import {VscArrowDown} from '@react-icons/all-files/vsc/VscArrowDown';
|
||||||
|
import {VscClose} from '@react-icons/all-files/vsc/VscClose';
|
||||||
|
import {VscCaseSensitive} from '@react-icons/all-files/vsc/VscCaseSensitive';
|
||||||
|
import {VscRegex} from '@react-icons/all-files/vsc/VscRegex';
|
||||||
|
import {VscWholeWord} from '@react-icons/all-files/vsc/VscWholeWord';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
const searchBoxStyling: React.CSSProperties = {
|
type SearchButtonColors = {
|
||||||
float: 'right',
|
foregroundColor: string;
|
||||||
height: '28px',
|
selectionColor: string;
|
||||||
backgroundColor: 'white',
|
backgroundColor: string;
|
||||||
position: 'absolute',
|
|
||||||
right: '10px',
|
|
||||||
top: '0px',
|
|
||||||
width: '224px',
|
|
||||||
zIndex: 9999
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const enterKey = 13;
|
type SearchButtonProps = React.PropsWithChildren<
|
||||||
|
{
|
||||||
|
onClick: () => void;
|
||||||
|
active: boolean;
|
||||||
|
title: string;
|
||||||
|
} & SearchButtonColors
|
||||||
|
>;
|
||||||
|
|
||||||
export default class SearchBox extends React.PureComponent<SearchBoxProps> {
|
const SearchButton = ({
|
||||||
|
onClick,
|
||||||
|
active,
|
||||||
|
title,
|
||||||
|
foregroundColor,
|
||||||
|
backgroundColor,
|
||||||
|
selectionColor,
|
||||||
|
children
|
||||||
|
}: SearchButtonProps) => {
|
||||||
|
const handleKeyUp = useCallback(
|
||||||
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
if (event.key === 'Enter' || event.key === ' ') {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onClick]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={onClick}
|
||||||
|
className={clsx('search-button', {'search-button-active': active})}
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<style jsx>
|
||||||
|
{`
|
||||||
|
.search-button {
|
||||||
|
cursor: pointer;
|
||||||
|
color: ${foregroundColor};
|
||||||
|
padding: 2px;
|
||||||
|
margin: 4px 0px;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button:focus {
|
||||||
|
outline: ${selectionColor} solid 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button:hover {
|
||||||
|
background-color: ${backgroundColor};
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-active {
|
||||||
|
background-color: ${selectionColor};
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button-active:hover {
|
||||||
|
background-color: ${selectionColor};
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SearchBox extends React.PureComponent<SearchBoxProps> {
|
||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
|
input: HTMLInputElement | null = null;
|
||||||
|
searchButtonColors: SearchButtonColors;
|
||||||
|
|
||||||
constructor(props: SearchBoxProps) {
|
constructor(props: SearchBoxProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.searchTerm = '';
|
this.searchTerm = '';
|
||||||
|
this.searchButtonColors = {
|
||||||
|
backgroundColor: this.props.borderColor,
|
||||||
|
selectionColor: this.props.selectionColor,
|
||||||
|
foregroundColor: this.props.foregroundColor
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
handleChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
this.searchTerm = event.currentTarget.value;
|
this.searchTerm = event.currentTarget.value;
|
||||||
if (event.keyCode === enterKey) {
|
if (event.shiftKey && event.key === 'Enter') {
|
||||||
this.props.search(event.currentTarget.value);
|
this.props.prev(this.searchTerm);
|
||||||
|
} else if (event.key === 'Enter') {
|
||||||
|
this.props.next(this.searchTerm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
this.input?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
caseSensitive,
|
||||||
|
wholeWord,
|
||||||
|
regex,
|
||||||
|
results,
|
||||||
|
toggleCaseSensitive,
|
||||||
|
toggleWholeWord,
|
||||||
|
toggleRegex,
|
||||||
|
next,
|
||||||
|
prev,
|
||||||
|
close,
|
||||||
|
backgroundColor,
|
||||||
|
foregroundColor,
|
||||||
|
borderColor,
|
||||||
|
selectionColor,
|
||||||
|
font
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={searchBoxStyling}>
|
<div className="flex-row search-container">
|
||||||
<input type="text" className="search-box" onKeyUp={this.handleChange} ref={(input) => input?.focus()} />
|
<div className="flex-row search-box">
|
||||||
<svg className="search-button" onClick={() => this.props.prev(this.searchTerm)}>
|
<input
|
||||||
<use xlinkHref="./renderer/assets/search-icons.svg#left-arrow" />
|
className="search-input"
|
||||||
</svg>
|
type="text"
|
||||||
<svg className="search-button" onClick={() => this.props.next(this.searchTerm)}>
|
onKeyDown={this.handleChange}
|
||||||
<use xlinkHref="./renderer/assets/search-icons.svg#right-arrow" />
|
ref={(input) => {
|
||||||
</svg>
|
this.input = input;
|
||||||
<svg className="search-button" onClick={() => this.props.close()}>
|
}}
|
||||||
<use xlinkHref="./renderer/assets/search-icons.svg#cancel" />
|
placeholder="Search"
|
||||||
</svg>
|
></input>
|
||||||
|
|
||||||
|
<SearchButton
|
||||||
|
onClick={toggleCaseSensitive}
|
||||||
|
active={caseSensitive}
|
||||||
|
title="Match Case"
|
||||||
|
{...this.searchButtonColors}
|
||||||
|
>
|
||||||
|
<VscCaseSensitive size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
|
||||||
|
<SearchButton
|
||||||
|
onClick={toggleWholeWord}
|
||||||
|
active={wholeWord}
|
||||||
|
title="Match Whole Word"
|
||||||
|
{...this.searchButtonColors}
|
||||||
|
>
|
||||||
|
<VscWholeWord size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
|
||||||
|
<SearchButton
|
||||||
|
onClick={toggleRegex}
|
||||||
|
active={regex}
|
||||||
|
title="Use Regular Expression"
|
||||||
|
{...this.searchButtonColors}
|
||||||
|
>
|
||||||
|
<VscRegex size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span style={{minWidth: '60px', marginLeft: '4px'}}>
|
||||||
|
{results === undefined
|
||||||
|
? ''
|
||||||
|
: results.resultCount === 0
|
||||||
|
? 'No results'
|
||||||
|
: `${results.resultIndex + 1} of ${results.resultCount}`}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div className="flex-row">
|
||||||
|
<SearchButton
|
||||||
|
onClick={() => prev(this.searchTerm)}
|
||||||
|
active={false}
|
||||||
|
title="Previous Match"
|
||||||
|
{...this.searchButtonColors}
|
||||||
|
>
|
||||||
|
<VscArrowUp size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
|
||||||
|
<SearchButton
|
||||||
|
onClick={() => next(this.searchTerm)}
|
||||||
|
active={false}
|
||||||
|
title="Next Match"
|
||||||
|
{...this.searchButtonColors}
|
||||||
|
>
|
||||||
|
<VscArrowDown size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
|
||||||
|
<SearchButton onClick={() => close()} active={false} title="Close" {...this.searchButtonColors}>
|
||||||
|
<VscClose size="14px" />
|
||||||
|
</SearchButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style jsx>
|
<style jsx>
|
||||||
{`
|
{`
|
||||||
.search-box {
|
.search-container {
|
||||||
font-size: 18px;
|
background-color: ${backgroundColor};
|
||||||
padding: 3px 6px;
|
border: 1px solid ${borderColor};
|
||||||
width: 152px;
|
border-radius: 2px;
|
||||||
border: none;
|
position: absolute;
|
||||||
float: left;
|
right: 13px;
|
||||||
|
top: 4px;
|
||||||
|
z-index: 10;
|
||||||
|
padding: 4px;
|
||||||
|
font-family: ${font};
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-box:focus {
|
.search-input {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: ${foregroundColor};
|
||||||
|
align-self: stretch;
|
||||||
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-button {
|
.flex-row {
|
||||||
background-color: #ffffff;
|
display: flex;
|
||||||
color: black;
|
flex-direction: row;
|
||||||
padding: 7px 5.5px;
|
justify-content: space-between;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
text-decoration: none;
|
gap: 4px;
|
||||||
display: inline-block;
|
|
||||||
font-size: 16px;
|
|
||||||
transition-duration: 0.4s;
|
|
||||||
cursor: pointer;
|
|
||||||
height: 27px;
|
|
||||||
width: 24px;
|
|
||||||
float: left;
|
|
||||||
}
|
}
|
||||||
.search-button:hover {
|
|
||||||
background-color: #e7e7e7;
|
.search-box {
|
||||||
|
border: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
outline: ${borderColor} solid 1px;
|
||||||
|
background-color: ${backgroundColor};
|
||||||
|
color: ${foregroundColor};
|
||||||
|
padding: 0px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input::placeholder {
|
||||||
|
color: ${foregroundColor};
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box:focus-within {
|
||||||
|
outline: ${selectionColor} solid 2px;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -78,3 +256,5 @@ export default class SearchBox extends React.PureComponent<SearchBoxProps> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default SearchBox;
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,15 @@ export default class StyleSheet extends React.PureComponent<StyleSheetProps> {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.xterm .xterm-decoration-overview-ruler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
right: 0px;
|
||||||
|
top: unset;
|
||||||
|
left: unset;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import {Terminal, ITerminalOptions, IDisposable} from 'xterm';
|
import {Terminal, ITerminalOptions, IDisposable} from 'xterm';
|
||||||
import {FitAddon} from 'xterm-addon-fit';
|
import {FitAddon} from 'xterm-addon-fit';
|
||||||
import {WebLinksAddon} from 'xterm-addon-web-links';
|
import {WebLinksAddon} from 'xterm-addon-web-links';
|
||||||
import {SearchAddon} from 'xterm-addon-search';
|
import {SearchAddon, ISearchDecorationOptions} from 'xterm-addon-search';
|
||||||
import {WebglAddon} from 'xterm-addon-webgl';
|
import {WebglAddon} from 'xterm-addon-webgl';
|
||||||
import {LigaturesAddon} from 'xterm-addon-ligatures';
|
import {LigaturesAddon} from 'xterm-addon-ligatures';
|
||||||
import {Unicode11Addon} from 'xterm-addon-unicode11';
|
import {Unicode11Addon} from 'xterm-addon-unicode11';
|
||||||
|
|
@ -10,9 +10,12 @@ import {clipboard, shell} from 'electron';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
import terms from '../terms';
|
import terms from '../terms';
|
||||||
import processClipboard from '../utils/paste';
|
import processClipboard from '../utils/paste';
|
||||||
import SearchBox from './searchBox';
|
import _SearchBox from './searchBox';
|
||||||
import {TermProps} from '../hyper';
|
import {TermProps} from '../hyper';
|
||||||
import {ObjectTypedKeys} from '../utils/object';
|
import {ObjectTypedKeys} from '../utils/object';
|
||||||
|
import {decorate} from '../utils/plugins';
|
||||||
|
|
||||||
|
const SearchBox = decorate(_SearchBox, 'SearchBox');
|
||||||
|
|
||||||
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform);
|
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform);
|
||||||
|
|
||||||
|
|
@ -78,11 +81,27 @@ const getTermOptions = (props: TermProps): ITerminalOptions => {
|
||||||
brightCyan: props.colors.lightCyan,
|
brightCyan: props.colors.lightCyan,
|
||||||
brightWhite: props.colors.lightWhite
|
brightWhite: props.colors.lightWhite
|
||||||
},
|
},
|
||||||
screenReaderMode: props.screenReaderMode
|
screenReaderMode: props.screenReaderMode,
|
||||||
|
overviewRulerWidth: 20
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Term extends React.PureComponent<TermProps> {
|
export default class Term extends React.PureComponent<
|
||||||
|
TermProps,
|
||||||
|
{
|
||||||
|
searchOptions: {
|
||||||
|
caseSensitive: boolean;
|
||||||
|
wholeWord: boolean;
|
||||||
|
regex: boolean;
|
||||||
|
};
|
||||||
|
searchResults:
|
||||||
|
| {
|
||||||
|
resultIndex: number;
|
||||||
|
resultCount: number;
|
||||||
|
}
|
||||||
|
| undefined;
|
||||||
|
}
|
||||||
|
> {
|
||||||
termRef: HTMLElement | null;
|
termRef: HTMLElement | null;
|
||||||
termWrapperRef: HTMLElement | null;
|
termWrapperRef: HTMLElement | null;
|
||||||
termOptions: ITerminalOptions;
|
termOptions: ITerminalOptions;
|
||||||
|
|
@ -94,6 +113,16 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
term!: Terminal;
|
term!: Terminal;
|
||||||
resizeObserver!: ResizeObserver;
|
resizeObserver!: ResizeObserver;
|
||||||
resizeTimeout!: NodeJS.Timeout;
|
resizeTimeout!: NodeJS.Timeout;
|
||||||
|
searchDecorations: ISearchDecorationOptions;
|
||||||
|
state = {
|
||||||
|
searchOptions: {
|
||||||
|
caseSensitive: false,
|
||||||
|
wholeWord: false,
|
||||||
|
regex: false
|
||||||
|
},
|
||||||
|
searchResults: undefined
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props: TermProps) {
|
constructor(props: TermProps) {
|
||||||
super(props);
|
super(props);
|
||||||
props.ref_(props.uid, this);
|
props.ref_(props.uid, this);
|
||||||
|
|
@ -104,6 +133,11 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
this.termDefaultBellSound = null;
|
this.termDefaultBellSound = null;
|
||||||
this.fitAddon = new FitAddon();
|
this.fitAddon = new FitAddon();
|
||||||
this.searchAddon = new SearchAddon();
|
this.searchAddon = new SearchAddon();
|
||||||
|
this.searchDecorations = {
|
||||||
|
activeMatchColorOverviewRuler: Color(this.props.cursorColor).hex(),
|
||||||
|
matchOverviewRuler: Color(this.props.borderColor).hex(),
|
||||||
|
activeMatchBackground: Color(this.props.cursorColor).hex()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// The main process shows this in the About dialog
|
// The main process shows this in the About dialog
|
||||||
|
|
@ -242,6 +276,15 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.disposableListeners.push(
|
||||||
|
this.searchAddon.onDidChangeResults((results) => {
|
||||||
|
this.setState((state) => ({
|
||||||
|
...state,
|
||||||
|
searchResults: results
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
window.addEventListener('paste', this.onWindowPaste, {
|
window.addEventListener('paste', this.onWindowPaste, {
|
||||||
capture: true
|
capture: true
|
||||||
});
|
});
|
||||||
|
|
@ -302,20 +345,28 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
this.term.reset();
|
this.term.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
search = (searchTerm = '') => {
|
|
||||||
this.searchAddon.findNext(searchTerm);
|
|
||||||
};
|
|
||||||
|
|
||||||
searchNext = (searchTerm: string) => {
|
searchNext = (searchTerm: string) => {
|
||||||
this.searchAddon.findNext(searchTerm);
|
this.searchAddon.findNext(searchTerm, {
|
||||||
|
...this.state.searchOptions,
|
||||||
|
decorations: this.searchDecorations
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
searchPrevious = (searchTerm: string) => {
|
searchPrevious = (searchTerm: string) => {
|
||||||
this.searchAddon.findPrevious(searchTerm);
|
this.searchAddon.findPrevious(searchTerm, {
|
||||||
|
...this.state.searchOptions,
|
||||||
|
decorations: this.searchDecorations
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
closeSearchBox = () => {
|
closeSearchBox = () => {
|
||||||
this.props.onCloseSearch();
|
this.props.onCloseSearch();
|
||||||
|
this.searchAddon.clearDecorations();
|
||||||
|
this.searchAddon.clearActiveDecoration();
|
||||||
|
this.setState((state) => ({
|
||||||
|
...state,
|
||||||
|
searchResults: undefined
|
||||||
|
}));
|
||||||
this.term.focus();
|
this.term.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -350,8 +401,8 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
// otherwise use the default sound found in xterm.
|
// otherwise use the default sound found in xterm.
|
||||||
nextTermOptions.bellSound = this.props.bellSound || this.termDefaultBellSound!;
|
nextTermOptions.bellSound = this.props.bellSound || this.termDefaultBellSound!;
|
||||||
|
|
||||||
if (!prevProps.search && this.props.search) {
|
if (prevProps.search && !this.props.search) {
|
||||||
this.search();
|
this.closeSearchBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update only options that have changed.
|
// Update only options that have changed.
|
||||||
|
|
@ -445,14 +496,38 @@ export default class Term extends React.PureComponent<TermProps> {
|
||||||
{this.props.customChildren}
|
{this.props.customChildren}
|
||||||
{this.props.search ? (
|
{this.props.search ? (
|
||||||
<SearchBox
|
<SearchBox
|
||||||
search={this.search}
|
|
||||||
next={this.searchNext}
|
next={this.searchNext}
|
||||||
prev={this.searchPrevious}
|
prev={this.searchPrevious}
|
||||||
close={this.closeSearchBox}
|
close={this.closeSearchBox}
|
||||||
|
caseSensitive={this.state.searchOptions.caseSensitive}
|
||||||
|
wholeWord={this.state.searchOptions.wholeWord}
|
||||||
|
regex={this.state.searchOptions.regex}
|
||||||
|
results={this.state.searchResults}
|
||||||
|
toggleCaseSensitive={() =>
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
searchOptions: {...this.state.searchOptions, caseSensitive: !this.state.searchOptions.caseSensitive}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
toggleWholeWord={() =>
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
searchOptions: {...this.state.searchOptions, wholeWord: !this.state.searchOptions.wholeWord}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
toggleRegex={() =>
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
searchOptions: {...this.state.searchOptions, regex: !this.state.searchOptions.regex}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
selectionColor={this.props.selectionColor}
|
||||||
|
backgroundColor={this.props.backgroundColor}
|
||||||
|
foregroundColor={this.props.foregroundColor}
|
||||||
|
borderColor={this.props.borderColor}
|
||||||
|
font={this.props.uiFontFamily}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : null}
|
||||||
''
|
|
||||||
)}
|
|
||||||
|
|
||||||
<style jsx global>{`
|
<style jsx global>{`
|
||||||
.term_fit {
|
.term_fit {
|
||||||
|
|
|
||||||
13
lib/hyper.d.ts
vendored
13
lib/hyper.d.ts
vendored
|
|
@ -314,10 +314,21 @@ import {TermGroupConnectedProps} from './components/term-group';
|
||||||
export type TermGroupProps = TermGroupConnectedProps & TermGroupOwnProps;
|
export type TermGroupProps = TermGroupConnectedProps & TermGroupOwnProps;
|
||||||
|
|
||||||
export type SearchBoxProps = {
|
export type SearchBoxProps = {
|
||||||
search: (searchTerm: string) => void;
|
caseSensitive: boolean;
|
||||||
|
wholeWord: boolean;
|
||||||
|
regex: boolean;
|
||||||
|
results: {resultIndex: number; resultCount: number} | undefined;
|
||||||
|
toggleCaseSensitive: () => void;
|
||||||
|
toggleWholeWord: () => void;
|
||||||
|
toggleRegex: () => void;
|
||||||
next: (searchTerm: string) => void;
|
next: (searchTerm: string) => void;
|
||||||
prev: (searchTerm: string) => void;
|
prev: (searchTerm: string) => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
|
backgroundColor: string;
|
||||||
|
foregroundColor: string;
|
||||||
|
borderColor: string;
|
||||||
|
selectionColor: string;
|
||||||
|
font: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
import {FitAddon} from 'xterm-addon-fit';
|
import {FitAddon} from 'xterm-addon-fit';
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,10 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron/remote": "2.0.9",
|
"@electron/remote": "2.0.9",
|
||||||
|
"@react-icons/all-files": "4.1.0",
|
||||||
"args": "5.0.3",
|
"args": "5.0.3",
|
||||||
"chalk": "5.2.0",
|
"chalk": "5.2.0",
|
||||||
|
"clsx": "1.2.1",
|
||||||
"color": "4.2.3",
|
"color": "4.2.3",
|
||||||
"columnify": "1.6.0",
|
"columnify": "1.6.0",
|
||||||
"css-loader": "6.7.3",
|
"css-loader": "6.7.3",
|
||||||
|
|
|
||||||
10
yarn.lock
10
yarn.lock
|
|
@ -797,6 +797,11 @@
|
||||||
tiny-glob "^0.2.9"
|
tiny-glob "^0.2.9"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@react-icons/all-files@4.1.0":
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.npmjs.org/@react-icons/all-files/-/all-files-4.1.0.tgz#477284873a0821928224b6fc84c62d2534d6650b"
|
||||||
|
integrity sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==
|
||||||
|
|
||||||
"@sindresorhus/is@^0.14.0":
|
"@sindresorhus/is@^0.14.0":
|
||||||
version "0.14.0"
|
version "0.14.0"
|
||||||
resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||||
|
|
@ -2411,6 +2416,11 @@ clone@^1.0.2:
|
||||||
resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||||
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
||||||
|
|
||||||
|
clsx@1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||||
|
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
||||||
|
|
||||||
code-excerpt@^4.0.0:
|
code-excerpt@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz#2de7d46e98514385cb01f7b3b741320115f4c95e"
|
resolved "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz#2de7d46e98514385cb01f7b3b741320115f4c95e"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue