mirror of https://github.com/buster-so/buster.git
search with key
This commit is contained in:
parent
0d98535936
commit
fd2e61808c
|
@ -31,6 +31,7 @@ const mockSearchItems: SearchItem[] = [
|
|||
value: 'document-1',
|
||||
keywords: ['document', 'file', 'pdf'],
|
||||
type: 'item',
|
||||
onSelect: fn(),
|
||||
},
|
||||
{
|
||||
icon: '📊',
|
||||
|
@ -39,6 +40,7 @@ const mockSearchItems: SearchItem[] = [
|
|||
value: 'dashboard-1',
|
||||
keywords: ['dashboard', 'analytics', 'charts'],
|
||||
type: 'item',
|
||||
onSelect: fn(),
|
||||
},
|
||||
...Array.from({ length: 10 }).map<SearchItem>((_, index) => ({
|
||||
icon: '📊',
|
||||
|
@ -47,6 +49,7 @@ const mockSearchItems: SearchItem[] = [
|
|||
value: `testing-${index}`,
|
||||
keywords: ['dashboard', 'analytics', 'charts'],
|
||||
type: 'item' as const,
|
||||
onSelect: fn(),
|
||||
})),
|
||||
];
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import { SearchEmptyState } from './SearchEmptyState';
|
|||
import { SearchFooter } from './SearchFooter';
|
||||
import { SearchInput } from './SearchInput';
|
||||
import { SearchModalContentItems } from './SearchModalContentItems';
|
||||
import type { SearchItem, SearchModalContentProps } from './search-modal.types';
|
||||
import type { SearchModalContentProps } from './search-modal.types';
|
||||
import { useViewSearchItem } from './useViewSearchItem';
|
||||
|
||||
export const SearchModalContent = <M, T extends string>({
|
||||
searchItems,
|
||||
|
@ -20,6 +21,10 @@ export const SearchModalContent = <M, T extends string>({
|
|||
secondaryContent,
|
||||
openSecondaryContent,
|
||||
}: SearchModalContentProps<M, T>) => {
|
||||
const { handleKeyDown, focusedValue, setFocusedValue } = useViewSearchItem({
|
||||
searchItems,
|
||||
onViewSearchItem,
|
||||
});
|
||||
const [searchValue, setSearchValue] = useState<string>(defaulSearchValue);
|
||||
|
||||
const onSearchChangePreflight = (searchValue: string) => {
|
||||
|
@ -30,7 +35,9 @@ export const SearchModalContent = <M, T extends string>({
|
|||
return (
|
||||
<Command
|
||||
className="min-w-[650px] min-h-[450px] max-h-[75vh] bg-background flex flex-col"
|
||||
value={searchValue}
|
||||
value={focusedValue}
|
||||
onValueChange={setFocusedValue}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<SearchInput
|
||||
searchValue={searchValue}
|
||||
|
|
|
@ -69,6 +69,7 @@ const SearchItemComponent = <M, T extends string>({
|
|||
value={value}
|
||||
disabled={disabled}
|
||||
onSelect={() => {
|
||||
console.log('onSelect', value);
|
||||
onSelect?.();
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -6,7 +6,7 @@ export type SearchItem<M = unknown, T extends string = string> = {
|
|||
value: T;
|
||||
keywords?: string[];
|
||||
meta?: M;
|
||||
onSelect?: () => void;
|
||||
onSelect?: () => void; //should only be used for side effects
|
||||
loading?: boolean;
|
||||
disabled?: boolean;
|
||||
type: 'item';
|
||||
|
@ -33,7 +33,7 @@ export type SearchModalContentProps<M = unknown, T extends string = string> = {
|
|||
filterContent?: React.ReactNode;
|
||||
searchItems: SearchItems<M, T>[];
|
||||
onSearchChange: (searchValue: string) => void;
|
||||
onSelect: (item: SearchItem<M, T>) => void;
|
||||
onSelect: (item: SearchItem<M, T>, modifier: 'select' | 'navigate') => void;
|
||||
onViewSearchItem: (item: SearchItem<M, T>) => void;
|
||||
emptyState?: React.ReactNode | string;
|
||||
placeholder?: string;
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import { useState } from 'react';
|
||||
import type { SearchItem, SearchItems } from './search-modal.types';
|
||||
|
||||
export const useViewSearchItem = <M, T extends string>({
|
||||
searchItems,
|
||||
onViewSearchItem,
|
||||
}: {
|
||||
searchItems: SearchItems<M, T>[];
|
||||
onViewSearchItem: (item: SearchItem<M, T>) => void;
|
||||
}) => {
|
||||
const [focusedValue, setFocusedValue] = useState<string>('');
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if ((e.key === 'ArrowDown' || e.key === 'ArrowUp') && onViewSearchItem) {
|
||||
// Wait for next tick to get updated focusedValue
|
||||
setTimeout(() => {
|
||||
if (!focusedValue) return;
|
||||
|
||||
const findItem = (items: typeof searchItems): SearchItem<M, T> | null => {
|
||||
for (const item of items) {
|
||||
if (item.type === 'item' && item.value === focusedValue) {
|
||||
return item;
|
||||
}
|
||||
if (item.type === 'group') {
|
||||
const found = findItem(item.items);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const item = findItem(searchItems);
|
||||
if (item) {
|
||||
onViewSearchItem(item);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
handleKeyDown,
|
||||
focusedValue,
|
||||
setFocusedValue,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue