diff --git a/package.json b/package.json index 2192d65b7d4..05f503f820c 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "@types/react-beautiful-dnd": "12.1.2", "@types/react-dom": "16.9.9", "@types/react-grid-layout": "1.1.1", + "@types/react-highlight-words": "^0.16.2", "@types/react-redux": "7.1.7", "@types/react-router-dom": "^5.1.7", "@types/react-select": "4.0.13", @@ -277,7 +278,7 @@ "react-diff-viewer": "^3.1.1", "react-dom": "17.0.1", "react-grid-layout": "1.2.0", - "react-highlight-words": "0.16.0", + "react-highlight-words": "0.17.0", "react-inlinesvg": "2.3.0", "react-loadable": "5.5.0", "react-popper": "2.2.4", diff --git a/packages/grafana-data/src/text/text.ts b/packages/grafana-data/src/text/text.ts index 567b85094f1..5b98ba11a6a 100644 --- a/packages/grafana-data/src/text/text.ts +++ b/packages/grafana-data/src/text/text.ts @@ -13,10 +13,14 @@ export function findHighlightChunksInText({ searchWords, textToHighlight, }: { - searchWords: string[]; + searchWords: Array; textToHighlight: string; }) { - return searchWords.reduce((acc: any, term: string) => [...acc, ...findMatchesInText(textToHighlight, term)], []); + const chunks: TextMatch[] = []; + for (const term of searchWords) { + chunks.push(...findMatchesInText(textToHighlight, term as string)); + } + return chunks; } const cleanNeedle = (needle: string): string => { diff --git a/packages/grafana-ui/src/components/Forms/Label.tsx b/packages/grafana-ui/src/components/Forms/Label.tsx index ace084e48ad..746f1d389db 100644 --- a/packages/grafana-ui/src/components/Forms/Label.tsx +++ b/packages/grafana-ui/src/components/Forms/Label.tsx @@ -7,7 +7,7 @@ import { Icon } from '../Icon/Icon'; export interface LabelProps extends React.LabelHTMLAttributes { children: React.ReactNode; description?: React.ReactNode; - category?: string[]; + category?: React.ReactNode[]; } export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => { diff --git a/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx b/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx index 134cc7a6688..4bd3cf868e0 100644 --- a/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx +++ b/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx @@ -106,7 +106,7 @@ class UnThemedLogRowMessage extends PureComponent { {needsHighlighter ? ( diff --git a/packages/grafana-ui/src/components/Typeahead/TypeaheadItem.tsx b/packages/grafana-ui/src/components/Typeahead/TypeaheadItem.tsx index 042dff4f05c..c2cde3dbd39 100644 --- a/packages/grafana-ui/src/components/Typeahead/TypeaheadItem.tsx +++ b/packages/grafana-ui/src/components/Typeahead/TypeaheadItem.tsx @@ -90,7 +90,7 @@ export const TypeaheadItem: React.FC = (props: Props) => { highlightParts={item.highlightParts} > ) : ( - + )} ); diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor.tsx index 3e595286af7..a71447ec788 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor.tsx @@ -37,7 +37,7 @@ export class OptionsPaneCategoryDescriptor { return this; } - render(isSearching?: boolean) { + render(searchQuery?: string) { if (this.props.customRender) { return this.props.customRender(); } diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx index 292b1df8b68..ba34c989657 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx @@ -1,6 +1,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { Field, Label } from '@grafana/ui'; import React, { ReactNode } from 'react'; +import Highlighter from 'react-highlight-words'; import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor'; export interface OptionsPaneItemProps { @@ -21,10 +22,10 @@ export class OptionsPaneItemDescriptor { constructor(public props: OptionsPaneItemProps) {} - getLabel(isSearching?: boolean): ReactNode { + getLabel(searchQuery?: string): ReactNode { const { title, description } = this.props; - if (!isSearching) { + if (!searchQuery) { // Do not render label for categories with only one child if (this.parent.props.title === title) { return null; @@ -33,24 +34,30 @@ export class OptionsPaneItemDescriptor { return title; } - const categories: string[] = []; + const categories: React.ReactNode[] = []; if (this.parent.parent) { - categories.push(this.parent.parent.props.title); + categories.push(this.highlightWord(this.parent.parent.props.title, searchQuery)); } if (this.parent.props.title !== title) { - categories.push(this.parent.props.title); + categories.push(this.highlightWord(this.parent.props.title, searchQuery)); } return ( -