From 2ee37c46d3fd170ddc3a7c6d0a10fd74cc08eee5 Mon Sep 17 00:00:00 2001 From: Keith Daulton Date: Thu, 22 Sep 2022 11:37:45 -0400 Subject: [PATCH] Adds matching options to graph search --- src/webviews/apps/plus/graph/GraphWrapper.tsx | 29 +-- src/webviews/apps/plus/graph/graph.scss | 35 ---- .../apps/shared/components/search/react.tsx | 19 ++ .../shared/components/search/search-field.ts | 181 ++++++++++++++++++ .../components/search/search-nav-react.tsx | 10 - 5 files changed, 210 insertions(+), 64 deletions(-) create mode 100644 src/webviews/apps/shared/components/search/react.tsx create mode 100644 src/webviews/apps/shared/components/search/search-field.ts delete mode 100644 src/webviews/apps/shared/components/search/search-nav-react.tsx diff --git a/src/webviews/apps/plus/graph/GraphWrapper.tsx b/src/webviews/apps/plus/graph/GraphWrapper.tsx index d36fc11d16d19..2d2f4fb59e145 100644 --- a/src/webviews/apps/plus/graph/GraphWrapper.tsx +++ b/src/webviews/apps/plus/graph/GraphWrapper.tsx @@ -26,7 +26,7 @@ import type { import type { Subscription } from '../../../../subscription'; import { getSubscriptionTimeRemaining, SubscriptionState } from '../../../../subscription'; import { pluralize } from '../../../../system/string'; -import { SearchNav } from '../../shared/components/search/search-nav-react'; +import { SearchField, SearchNav } from '../../shared/components/search/react'; import type { DateTimeFormat } from '../../shared/date'; import { formatDate, fromNow } from '../../shared/date'; @@ -314,16 +314,16 @@ export function GraphWrapper({ } }; - const handleSearchInput = (e: FormEvent) => { - const currentValue = e.currentTarget.value; - setSearchValue(currentValue); + const handleSearchInput = (e: CustomEvent) => { + const detail = e.detail; + setSearchValue(detail.pattern); - if (currentValue.length < 3) { + if (detail.pattern.length < 3) { setSearchResultKey(undefined); setSearchIds(undefined); return; } - onSearchCommits?.({ pattern: currentValue }); + onSearchCommits?.(detail); }; useLayoutEffect(() => { @@ -584,19 +584,10 @@ export function GraphWrapper({
-
- - handleSearchInput(e)} - /> -
+ handleSearchInput(e as CustomEvent)} + /> ` + +`; + +const styles = css` + :host { + display: inline-flex; + flex-direction: row; + align-items: center; + gap: 0.8rem; + position: relative; + } + + label { + color: var(--vscode-input-foreground); + } + + input { + width: 30rem; + height: 2.4rem; + background-color: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px solid var(--vscode-input-background); + border-radius: 0.25rem; + padding: 0 6.6rem 0 0.4rem; + font-family: inherit; + font-size: 1rem; + } + input:focus { + outline: 1px solid var(--vscode-focusBorder); + outline-offset: -1px; + } + input::placeholder { + color: var(--vscode-input-placeholderForeground); + } + + .controls { + position: absolute; + top: 0.2rem; + right: 0.2rem; + display: inline-flex; + flex-direction: row; + align-items: center; + gap: 0.1rem; + } + + button { + display: inline-flex; + justify-content: center; + align-items: center; + width: 2rem; + height: 2rem; + padding: 0; + color: inherit; + border: none; + background: none; + text-align: center; + border-radius: 0.25rem; + } + button:focus:not([disabled]) { + outline: 1px solid var(--vscode-focusBorder); + outline-offset: -1px; + } + button:not([disabled]) { + cursor: pointer; + } + button:hover:not([disabled]) { + background-color: var(--vscode-inputOption-hoverBackground); + } + button[disabled] { + opacity: 0.5; + } + button[aria-checked='true'] { + background-color: var(--vscode-inputOption-activeBackground); + color: var(--vscode-inputOption-activeForeground); + } +`; + +@customElement({ + name: 'search-field', + template: template, + styles: styles, +}) +export class SearchField extends FASTElement { + @attr + label = 'Search'; + + @attr + placeholder = 'Search...'; + + @attr + value = ''; + + @attr({ mode: 'boolean' }) + all = false; + + @attr({ mode: 'boolean' }) + case = false; + + @attr({ mode: 'boolean' }) + regex = false; + + handleInput(e: Event) { + const value = (e.target as HTMLInputElement)?.value; + this.value = value; + this.emitSearch(); + } + handleAll(_e: Event) { + this.all = !this.all; + this.emitSearch(); + } + handleCase(_e: Event) { + this.case = !this.case; + this.emitSearch(); + } + handleRegex(_e: Event) { + this.regex = !this.regex; + if (!this.regex) { + this.case = false; + } + this.emitSearch(); + } + + emitSearch() { + this.$emit('change', { + pattern: this.value, + matchAll: this.all, + matchCase: this.case, + matchRegex: this.regex, + }); + } +} diff --git a/src/webviews/apps/shared/components/search/search-nav-react.tsx b/src/webviews/apps/shared/components/search/search-nav-react.tsx deleted file mode 100644 index 3282739e76c0a..0000000000000 --- a/src/webviews/apps/shared/components/search/search-nav-react.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { provideReactWrapper } from '@microsoft/fast-react-wrapper'; -import React from 'react'; -import { SearchNav as nativeComponent } from './search-nav'; - -export const SearchNav = provideReactWrapper(React).wrap(nativeComponent, { - events: { - onPrevious: 'previous', - onNext: 'next', - }, -});