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',
|
value: 'document-1',
|
||||||
keywords: ['document', 'file', 'pdf'],
|
keywords: ['document', 'file', 'pdf'],
|
||||||
type: 'item',
|
type: 'item',
|
||||||
|
onSelect: fn(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: '📊',
|
icon: '📊',
|
||||||
|
@ -39,6 +40,7 @@ const mockSearchItems: SearchItem[] = [
|
||||||
value: 'dashboard-1',
|
value: 'dashboard-1',
|
||||||
keywords: ['dashboard', 'analytics', 'charts'],
|
keywords: ['dashboard', 'analytics', 'charts'],
|
||||||
type: 'item',
|
type: 'item',
|
||||||
|
onSelect: fn(),
|
||||||
},
|
},
|
||||||
...Array.from({ length: 10 }).map<SearchItem>((_, index) => ({
|
...Array.from({ length: 10 }).map<SearchItem>((_, index) => ({
|
||||||
icon: '📊',
|
icon: '📊',
|
||||||
|
@ -47,6 +49,7 @@ const mockSearchItems: SearchItem[] = [
|
||||||
value: `testing-${index}`,
|
value: `testing-${index}`,
|
||||||
keywords: ['dashboard', 'analytics', 'charts'],
|
keywords: ['dashboard', 'analytics', 'charts'],
|
||||||
type: 'item' as const,
|
type: 'item' as const,
|
||||||
|
onSelect: fn(),
|
||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { SearchEmptyState } from './SearchEmptyState';
|
||||||
import { SearchFooter } from './SearchFooter';
|
import { SearchFooter } from './SearchFooter';
|
||||||
import { SearchInput } from './SearchInput';
|
import { SearchInput } from './SearchInput';
|
||||||
import { SearchModalContentItems } from './SearchModalContentItems';
|
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>({
|
export const SearchModalContent = <M, T extends string>({
|
||||||
searchItems,
|
searchItems,
|
||||||
|
@ -20,6 +21,10 @@ export const SearchModalContent = <M, T extends string>({
|
||||||
secondaryContent,
|
secondaryContent,
|
||||||
openSecondaryContent,
|
openSecondaryContent,
|
||||||
}: SearchModalContentProps<M, T>) => {
|
}: SearchModalContentProps<M, T>) => {
|
||||||
|
const { handleKeyDown, focusedValue, setFocusedValue } = useViewSearchItem({
|
||||||
|
searchItems,
|
||||||
|
onViewSearchItem,
|
||||||
|
});
|
||||||
const [searchValue, setSearchValue] = useState<string>(defaulSearchValue);
|
const [searchValue, setSearchValue] = useState<string>(defaulSearchValue);
|
||||||
|
|
||||||
const onSearchChangePreflight = (searchValue: string) => {
|
const onSearchChangePreflight = (searchValue: string) => {
|
||||||
|
@ -30,7 +35,9 @@ export const SearchModalContent = <M, T extends string>({
|
||||||
return (
|
return (
|
||||||
<Command
|
<Command
|
||||||
className="min-w-[650px] min-h-[450px] max-h-[75vh] bg-background flex flex-col"
|
className="min-w-[650px] min-h-[450px] max-h-[75vh] bg-background flex flex-col"
|
||||||
value={searchValue}
|
value={focusedValue}
|
||||||
|
onValueChange={setFocusedValue}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
>
|
>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
searchValue={searchValue}
|
searchValue={searchValue}
|
||||||
|
|
|
@ -69,6 +69,7 @@ const SearchItemComponent = <M, T extends string>({
|
||||||
value={value}
|
value={value}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
|
console.log('onSelect', value);
|
||||||
onSelect?.();
|
onSelect?.();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -6,7 +6,7 @@ export type SearchItem<M = unknown, T extends string = string> = {
|
||||||
value: T;
|
value: T;
|
||||||
keywords?: string[];
|
keywords?: string[];
|
||||||
meta?: M;
|
meta?: M;
|
||||||
onSelect?: () => void;
|
onSelect?: () => void; //should only be used for side effects
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
type: 'item';
|
type: 'item';
|
||||||
|
@ -33,7 +33,7 @@ export type SearchModalContentProps<M = unknown, T extends string = string> = {
|
||||||
filterContent?: React.ReactNode;
|
filterContent?: React.ReactNode;
|
||||||
searchItems: SearchItems<M, T>[];
|
searchItems: SearchItems<M, T>[];
|
||||||
onSearchChange: (searchValue: string) => void;
|
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;
|
onViewSearchItem: (item: SearchItem<M, T>) => void;
|
||||||
emptyState?: React.ReactNode | string;
|
emptyState?: React.ReactNode | string;
|
||||||
placeholder?: 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