From 4a367d24577166806bf04e7ee94c684843277d06 Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Tue, 18 Feb 2025 23:21:27 +1100 Subject: [PATCH] update command palette to also use highlights api --- src/features/command/palette.module.css | 4 +-- src/features/command/palette.tsx | 41 +++++++++++++++++-------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/features/command/palette.module.css b/src/features/command/palette.module.css index 7f3cf77..80c4b95 100644 --- a/src/features/command/palette.module.css +++ b/src/features/command/palette.module.css @@ -36,8 +36,8 @@ background-color: color(from var(--info) xyz x y z / .5); } - & b { - color: var(--text-1); + & ::highlight(command-pelette-query) { + background-color: var(--secondary-900); } } } \ No newline at end of file diff --git a/src/features/command/palette.tsx b/src/features/command/palette.tsx index c7f8465..ddf943c 100644 --- a/src/features/command/palette.tsx +++ b/src/features/command/palette.tsx @@ -4,6 +4,7 @@ import { CommandType } from "./command"; import { useCommands } from "./context"; import css from "./palette.module.css"; import { split_by_filter } from "~/utilities"; +import { getTextNodes } from "@solid-primitives/selection"; export interface CommandPaletteApi { readonly open: Accessor; @@ -56,14 +57,9 @@ export const CommandPalette: Component<{ api?: (api: CommandPaletteApi) => any, }; return setOpen(false)}> - t(item.label) as string} context={setSearch} onSubmit={onSubmit}>{ - (item, ctx) => { - const label = t(item.label) as string; - const filter = ctx.filter().toLowerCase(); - - return { - ([is_hit, part]) => {part} - }; + (t(item.label) ?? item.label) as string} context={setSearch} onSubmit={onSubmit}>{ + (item) => { + return <>{t(item.label) ?? item.label}; } } ; @@ -86,7 +82,7 @@ interface SearchableListProps { title?: string; keySelector(item: T): string; filter?: (item: T, search: string) => boolean; - children(item: T, context: SearchContext): JSX.Element; + children(item: T): JSX.Element; context?: (context: SearchContext) => any, onSubmit?: SubmitHandler; } @@ -94,6 +90,7 @@ interface SearchableListProps { function SearchableList(props: SearchableListProps): JSX.Element { const [term, setTerm] = createSignal(''); const [selected, setSelected] = createSignal(0); + const [outputRef, setOutputRef] = createSignal(); const id = createUniqueId(); const results = createMemo(() => { @@ -131,6 +128,25 @@ function SearchableList(props: SearchableListProps): JSX.Element { setSelected(current => Math.min(current, length)); }); + createEffect(() => { + const filter = term(); + const regexp = new RegExp(filter, 'gi'); + const ref = outputRef()!; + + const ranges = getTextNodes(ref).flatMap(node => { + return node.textContent!.matchAll(regexp).map(({ index }) => { + const range = new Range(); + + range.setStart(node, index); + range.setEnd(node, index + filter.length); + + return range; + }).toArray(); + }); + + CSS.highlights.set('command-pelette-query', new Highlight(...ranges)); + }); + const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'ArrowUp') { setSelected(current => Math.max(0, current - 1)); @@ -162,9 +178,9 @@ function SearchableList(props: SearchableListProps): JSX.Element {
setTerm(e.target.value)} placeholder="start typing for command" autofocus autocomplete="off" enterkeyhint="go" /> - + { - (result, index) =>
{props.children(result, ctx)}
+ (result, index) =>
{props.children(result)}
}
@@ -172,5 +188,4 @@ function SearchableList(props: SearchableListProps): JSX.Element { }; let keyCounter = 0; -const createUniqueId = () => `key-${keyCounter++}`; - +const createUniqueId = () => `key-${keyCounter++}`; \ No newline at end of file