import React, { useCallback, useMemo, useRef, useState } from 'react';
import { View, Text, TextInput, Pressable } from 'react-native';
import { FlashList } from '@shopify/flash-list';
import BottomSheet, { BottomSheetBackdrop, BottomSheetView } from '@gorhom/bottom-sheet';
import Svg, { Path } from 'react-native-svg';
import type { SearchableEntity, SearchResult } from '../types/algorand';
import { searchEntities } from '../utils/search';
function SearchIcon({ size = 16, color = '#a1a1aa' }: { size?: number; color?: string }) {
return (
);
}
interface SearchSheetProps {
data: T[];
placeholder?: string;
onSelect?: (item: T) => void;
renderItem: (item: T) => React.ReactElement;
className?: string;
}
export function SearchSheet({
data,
placeholder = 'Search...',
onSelect,
renderItem,
className,
}: SearchSheetProps) {
const sheetRef = useRef(null);
const [query, setQuery] = useState('');
const [isOpen, setIsOpen] = useState(false);
const snapPoints = useMemo(() => ['50%', '80%'], []);
const results = useMemo(() => {
if (!query.trim()) {
return data.slice(0, 10).map((item) => ({ item, score: 1, matches: [] as string[] }));
}
return searchEntities(data, query, 10);
}, [data, query]);
const handleOpen = useCallback(() => {
setIsOpen(true);
sheetRef.current?.snapToIndex(0);
}, []);
const handleSelect = useCallback(
(item: T) => {
onSelect?.(item);
setQuery('');
sheetRef.current?.close();
},
[onSelect],
);
const renderBackdrop = useCallback(
(props: React.ComponentProps) => (
),
[],
);
const renderResultItem = useCallback(
({ item }: { item: SearchResult }) => (
handleSelect(item.item)}
className="px-4 py-3 border-b border-zinc-800"
>
{renderItem(item.item)}
),
[handleSelect, renderItem],
);
return (
{/* Search Trigger Button */}
{placeholder}
{/* Bottom Sheet */}
{
if (index === -1) setIsOpen(false);
}}
>
{/* Search Input */}
{/* Results */}
`search-${index}`}
ListEmptyComponent={
{query.trim() ? 'No results found.' : 'No items available.'}
}
/>
);
}