diff --git a/src/renderer/components/DatabaseTable/DatabaseSelection.tsx b/src/renderer/components/DatabaseTable/DatabaseSelection.tsx index 538bde8..f388d93 100644 --- a/src/renderer/components/DatabaseTable/DatabaseSelection.tsx +++ b/src/renderer/components/DatabaseTable/DatabaseSelection.tsx @@ -37,7 +37,7 @@ function DatabaseSelectionModal({ const { common } = useSqlExecute(); const filteredDatabaseList = useMemo(() => { - return databaseList.filter(database => + return databaseList.filter((database) => database.toLowerCase().includes(searchTerm.toLowerCase()) ); }, [databaseList, searchTerm]); @@ -82,6 +82,7 @@ function DatabaseSelectionModal({

No matching databases found.

) : ( setSelectedDatabase(item)} items={filteredDatabaseList} diff --git a/src/renderer/components/DatabaseTable/DatabaseTableList.tsx b/src/renderer/components/DatabaseTable/DatabaseTableList.tsx index f05f615..b3a641a 100644 --- a/src/renderer/components/DatabaseTable/DatabaseTableList.tsx +++ b/src/renderer/components/DatabaseTable/DatabaseTableList.tsx @@ -179,6 +179,8 @@ export default function DatabaseTableList() { {currentDatabase ? ( { items: T[]; + highlight?: string; selectedItem?: T; changeItemKeys?: string[]; emptyComponent?: ReactElement; @@ -20,6 +21,7 @@ interface ListViewProps { export default function ListView({ items, + highlight, selectedItem, changeItemKeys, extractMeta, @@ -64,6 +66,7 @@ export default function ListView({ key={key} text={text} icon={icon} + highlight={highlight} selected={key === selectedKey} changed={changeItemKeys?.includes(key)} onContextMenu={async (e) => { diff --git a/src/renderer/components/ListViewItem/index.tsx b/src/renderer/components/ListViewItem/index.tsx index 0169e91..9ffed3c 100644 --- a/src/renderer/components/ListViewItem/index.tsx +++ b/src/renderer/components/ListViewItem/index.tsx @@ -1,10 +1,11 @@ -import { ReactElement } from 'react'; +import { ReactElement, useMemo } from 'react'; import styles from './styles.module.scss'; import Icon from '../Icon'; import { useAppFeature } from 'renderer/contexts/AppFeatureProvider'; interface ListViewItemProps { text: string; + highlight?: string; icon?: ReactElement; changed?: boolean; selected?: boolean; @@ -19,8 +20,16 @@ interface ListViewItemProps { onCollapsedClick?: () => void; } +function encodeStringToHTML(s: string) { + const el = document.createElement('div'); + el.innerText = el.textContent = s; + s = el.innerHTML; + return s; +} + export default function ListViewItem({ text, + highlight, icon, selected, changed, @@ -36,6 +45,24 @@ export default function ListViewItem({ }: ListViewItemProps) { const { theme } = useAppFeature(); + const finalText = useMemo(() => { + if (highlight) { + const highlightText = encodeStringToHTML(highlight); + const santizedText = encodeStringToHTML(text || ''); + const regex = new RegExp( + '(' + highlightText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ')', + 'i' + ); + + return santizedText.replace( + regex, + `$1` + ); + } else { + return encodeStringToHTML(text || ''); + } + }, [text, highlight]); + return (
))} {!hasCollapsed &&
{icon}
} -
{text}
+
); } diff --git a/src/renderer/components/TreeView/index.tsx b/src/renderer/components/TreeView/index.tsx index 3ef899b..db5bdc0 100644 --- a/src/renderer/components/TreeView/index.tsx +++ b/src/renderer/components/TreeView/index.tsx @@ -18,6 +18,8 @@ interface TreeViewProps { onSelectChange?: (value?: TreeViewItemData) => void; onDoubleClick?: (value: TreeViewItemData) => void; onContextMenu?: React.MouseEventHandler; + highlight?: string; + highlightDepth?: number; } function TreeViewItem({ @@ -30,6 +32,9 @@ function TreeViewItem({ collapsedKeys, onCollapsedChange, onDoubleClick, + + highlight, + highlightDepth, }: { item: TreeViewItemData; depth: number; @@ -40,6 +45,8 @@ function TreeViewItem({ onCollapsedChange?: (value?: string[]) => void; collapsedKeys?: string[]; onDoubleClick?: (value: TreeViewItemData) => void; + highlight?: string; + highlightDepth?: number; }) { const hasCollapsed = item.children && item.children.length > 0; const isCollapsed = collapsedKeys?.includes(item.id); @@ -62,6 +69,7 @@ function TreeViewItem({ onDoubleClick(item); } }} + highlight={depth === highlightDepth ? highlight : undefined} hasCollapsed={hasCollapsed} collapsed={isCollapsed} selected={selected?.id === item.id} @@ -89,6 +97,8 @@ function TreeViewItem({ key={item.id} item={item} depth={depth + 1} + highlight={highlight} + highlightDepth={highlightDepth} selected={selected} onSelectChange={onSelectChange} collapsedKeys={collapsedKeys} @@ -111,6 +121,8 @@ export default function TreeView({ collapsedKeys, onDoubleClick, onContextMenu, + highlight, + highlightDepth, }: TreeViewProps) { return (
@@ -120,6 +132,8 @@ export default function TreeView({ key={item.id} item={item} depth={0} + highlight={highlight} + highlightDepth={highlightDepth} selected={selected} onSelectChange={onSelectChange} onDoubleClick={onDoubleClick}