aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/frontend/src')
-rw-r--r--plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx63
-rw-r--r--plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx13
-rw-r--r--plugins/base/frontend/src/main/components/search/search.tsx116
-rw-r--r--plugins/base/frontend/src/main/components/search/searchIcon.svg3
-rw-r--r--plugins/base/frontend/src/main/components/search/searchResultRow.tsx24
-rw-r--r--plugins/base/frontend/src/main/components/search/types.ts19
-rw-r--r--plugins/base/frontend/src/main/types/@jetbrains/index.d.ts6
7 files changed, 123 insertions, 121 deletions
diff --git a/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx
new file mode 100644
index 00000000..725fbaee
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/dokkaFuzzyFilter.tsx
@@ -0,0 +1,63 @@
+import {Select} from "@jetbrains/ring-ui";
+import {Option, OptionWithHighlightComponent, OptionWithSearchResult, SearchRank} from "./types";
+import fuzzyHighlight from '@jetbrains/ring-ui/components/global/fuzzy-highlight.js'
+import React from "react";
+import {SearchResultRow} from "./searchResultRow";
+
+const orderRecords = (records: OptionWithSearchResult[], searchPhrase: string): OptionWithSearchResult[] => {
+ return records.sort((a: OptionWithSearchResult, b: OptionWithSearchResult) => {
+ //Prefer higher rank
+ const byRank = b.rank - a.rank
+ if(byRank !== 0){
+ return byRank
+ }
+ //Prefer exact matches
+ const aIncludes = a.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0
+ const bIncludes = b.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0
+ const byIncludes = bIncludes - aIncludes
+ if(byIncludes != 0){
+ return byIncludes
+ }
+
+ //Prefer matches that are closer
+ const byFirstMatchedPosition = a.highlight.indexOf("**") - b.highlight.indexOf("**")
+ if(byFirstMatchedPosition == 0) {
+ return a.name.toLowerCase().localeCompare(b.name.toLowerCase())
+ }
+ return byFirstMatchedPosition
+ })
+}
+
+const highlightMatchedPhrases = (records: OptionWithSearchResult[]): OptionWithHighlightComponent[] => {
+ // @ts-ignore
+ return records.map(record => {
+ return {
+ ...record,
+ template: <SearchResultRow searchResult={record}/>
+ }
+ })
+}
+
+export class DokkaFuzzyFilterComponent extends Select {
+ getListItems(rawFilterString: string, _: Option[]) {
+ const matchedRecords = this.props.data
+ .map((record: Option) => {
+ const bySearchKey = fuzzyHighlight(rawFilterString.trim(), record.searchKey, false)
+ if(bySearchKey.matched){
+ return {
+ ...bySearchKey,
+ ...record,
+ rank: SearchRank.SearchKeyMatch
+ }
+ }
+ return {
+ ...fuzzyHighlight(rawFilterString.trim(), record.name, false),
+ ...record,
+ rank: SearchRank.NameMatch
+ }
+ })
+ .filter((record: OptionWithSearchResult) => record.matched)
+
+ return highlightMatchedPhrases(orderRecords(matchedRecords, rawFilterString))
+ }
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx b/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx
new file mode 100644
index 00000000..ad0b5f8f
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/dokkaSearchAnchor.tsx
@@ -0,0 +1,13 @@
+import React from "react";
+import SearchIcon from 'react-svg-loader!./searchIcon.svg';
+
+export const DokkaSearchAnchor = ({wrapperProps, buttonProps, popup}: any) => {
+ return (
+ <span {...wrapperProps}>
+ <button type="button" {...buttonProps}>
+ <SearchIcon />
+ </button>
+ {popup}
+ </span>
+ )
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/search.tsx b/plugins/base/frontend/src/main/components/search/search.tsx
index b4c5b1cd..c7976edb 100644
--- a/plugins/base/frontend/src/main/components/search/search.tsx
+++ b/plugins/base/frontend/src/main/components/search/search.tsx
@@ -1,107 +1,10 @@
import React, {useCallback, useState} from 'react';
import {Select, List} from '@jetbrains/ring-ui';
-import fuzzyHighlight from '@jetbrains/ring-ui/components/global/fuzzy-highlight.js'
import '@jetbrains/ring-ui/components/input-size/input-size.scss';
import './search.scss';
-import {IWindow, Option, Props, Page} from "./types";
-
-enum SearchRank {
- SearchKeyMatch = 1,
- NameMatch = 0
-}
-type OptionWithSearchResult = Option & {
- matched: boolean,
- highlight: string,
- rank: SearchRank
-}
-
-type OptionWithHighlightComponent = Option & {
- name: React.FC<SearchProps>
-}
-
-type SearchProps = {
- searchResult: OptionWithSearchResult,
-}
-
-const orderRecords = (records: OptionWithSearchResult[], searchPhrase: string): OptionWithSearchResult[] => {
- return records.sort((a: OptionWithSearchResult, b: OptionWithSearchResult) => {
- //Prefer higher rank
- const byRank = b.rank - a.rank
- if(byRank !== 0){
- return byRank
- }
- //Prefer exact matches
- const aIncludes = a.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0
- const bIncludes = b.name.toLowerCase().includes(searchPhrase.toLowerCase()) ? 1 : 0
- const byIncludes = bIncludes - aIncludes
- if(byIncludes != 0){
- return byIncludes
- }
-
- //Prefer matches that are closer
- const byFirstMatchedPosition = a.highlight.indexOf("**") - b.highlight.indexOf("**")
- if(byFirstMatchedPosition == 0) {
- return a.name.toLowerCase().localeCompare(b.name.toLowerCase())
- }
- return byFirstMatchedPosition
- })
-}
-
-const SearchResultRow: React.FC<SearchProps> = ({searchResult}: SearchProps) => {
- const signatureFromSearchResult = (searchResult: OptionWithSearchResult): string => {
- if(searchResult.rank == SearchRank.SearchKeyMatch){
- return searchResult.name.replace(searchResult.searchKey, searchResult.highlight)
- }
- return searchResult.highlight
- }
-
- const renderHighlightMarkersAsHtml = (record: string): string => {
- return record.replace(/\*\*(.*?)\*\*/g, '<span class="phraseHighlight">$1</span>')
- }
-
- return (
- <div className="template-wrapper">
- <span dangerouslySetInnerHTML={
- {__html: renderHighlightMarkersAsHtml(signatureFromSearchResult(searchResult)) }
- }/>
- <span className="template-description">{searchResult.description}</span>
- </div>
- )
-}
-
-const highlightMatchedPhrases = (records: OptionWithSearchResult[]): OptionWithHighlightComponent[] => {
- // @ts-ignore
- return records.map(record => {
- return {
- ...record,
- template: <SearchResultRow searchResult={record}/>
- }
- })
-}
-
-class DokkaFuzzyFilterComponent extends Select {
- getListItems(rawFilterString: string, _: Option[]) {
- const matchedRecords = this.props.data
- .map((record: Option) => {
- const bySearchKey = fuzzyHighlight(rawFilterString.trim(), record.searchKey, true)
- if(bySearchKey.matched){
- return {
- ...bySearchKey,
- ...record,
- rank: SearchRank.SearchKeyMatch
- }
- }
- return {
- ...fuzzyHighlight(rawFilterString.trim(), record.name),
- ...record,
- rank: SearchRank.NameMatch
- }
- })
- .filter((record: OptionWithSearchResult) => record.matched)
-
- return highlightMatchedPhrases(orderRecords(matchedRecords, rawFilterString))
- }
-}
+import {IWindow, Option, Props} from "./types";
+import {DokkaSearchAnchor} from "./dokkaSearchAnchor";
+import {DokkaFuzzyFilterComponent} from "./dokkaFuzzyFilter";
const WithFuzzySearchFilterComponent: React.FC<Props> = ({data}: Props) => {
const [selected, onSelected] = useState<Option>(data[0]);
@@ -136,19 +39,6 @@ const WithFuzzySearchFilterComponent: React.FC<Props> = ({data}: Props) => {
)
}
-const DokkaSearchAnchor = ({wrapperProps, buttonProps, popup}) => {
- return (
- <span {...wrapperProps}>
- <button type="button" {...buttonProps}>
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
- <path d="M19.64 18.36l-6.24-6.24a7.52 7.52 0 1 0-1.28 1.28l6.24 6.24zM7.5 13.4a5.9 5.9 0 1 1 5.9-5.9 5.91 5.91 0 0 1-5.9 5.9z"/>
- </svg>
- </button>
- {popup}
- </span>
- )
-}
-
export const WithFuzzySearchFilter = () => {
let data: Option[] = [];
const pages = (window as IWindow).pages;
diff --git a/plugins/base/frontend/src/main/components/search/searchIcon.svg b/plugins/base/frontend/src/main/components/search/searchIcon.svg
new file mode 100644
index 00000000..391b1cab
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/searchIcon.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+ <path d="M19.64 18.36l-6.24-6.24a7.52 7.52 0 1 0-1.28 1.28l6.24 6.24zM7.5 13.4a5.9 5.9 0 1 1 5.9-5.9 5.91 5.91 0 0 1-5.9 5.9z"/>
+</svg> \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/searchResultRow.tsx b/plugins/base/frontend/src/main/components/search/searchResultRow.tsx
new file mode 100644
index 00000000..9ae19cb9
--- /dev/null
+++ b/plugins/base/frontend/src/main/components/search/searchResultRow.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+import {OptionWithSearchResult, SearchProps, SearchRank} from "./types";
+
+export const SearchResultRow: React.FC<SearchProps> = ({searchResult}: SearchProps) => {
+ const signatureFromSearchResult = (searchResult: OptionWithSearchResult): string => {
+ if(searchResult.rank == SearchRank.SearchKeyMatch){
+ return searchResult.name.replace(searchResult.searchKey, searchResult.highlight)
+ }
+ return searchResult.highlight
+ }
+
+ const renderHighlightMarkersAsHtml = (record: string): string => {
+ return record.replace(/\*\*(.*?)\*\*/g, '<span class="phraseHighlight">$1</span>')
+ }
+
+ return (
+ <div className="template-wrapper">
+ <span dangerouslySetInnerHTML={
+ {__html: renderHighlightMarkersAsHtml(signatureFromSearchResult(searchResult)) }
+ }/>
+ <span className="template-description">{searchResult.description}</span>
+ </div>
+ )
+} \ No newline at end of file
diff --git a/plugins/base/frontend/src/main/components/search/types.ts b/plugins/base/frontend/src/main/components/search/types.ts
index a6736a2d..922935bd 100644
--- a/plugins/base/frontend/src/main/components/search/types.ts
+++ b/plugins/base/frontend/src/main/components/search/types.ts
@@ -1,3 +1,5 @@
+import React from "react";
+
export type Page = {
name: string;
kind: string;
@@ -23,7 +25,20 @@ export type Props = {
data: Option[]
};
+export enum SearchRank {
+ SearchKeyMatch = 1,
+ NameMatch = 0
+}
+export type OptionWithSearchResult = Option & {
+ matched: boolean,
+ highlight: string,
+ rank: SearchRank
+}
+
+export type OptionWithHighlightComponent = Option & {
+ name: React.FC<SearchProps>
+}
-export type State = {
- selected: any
+export type SearchProps = {
+ searchResult: OptionWithSearchResult,
}
diff --git a/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts b/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts
index 8ab594e3..3d209657 100644
--- a/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts
+++ b/plugins/base/frontend/src/main/types/@jetbrains/index.d.ts
@@ -2,9 +2,3 @@ declare module '@jetbrains/ring-ui' {
export const Select: any;
export const List: any;
}
-
-declare module '@jetbrains/ring-ui/components/global/fuzzy-highlight.js' {
- import {Option} from "../../components/search/types";
-
- export const fuzzyHighlight: (string, string, boolean) => Option[]
-}