@papernote/ui
Version:
A modern React component library with a paper notebook aesthetic - minimal, professional, and expressive
83 lines • 3.16 kB
TypeScript
import { ReactNode } from 'react';
export interface SearchableListItem<T = unknown> {
key: string;
data: T;
}
export interface SearchableListProps<T = unknown> {
/** Array of items to display */
items: SearchableListItem<T>[];
/** Search input placeholder */
searchPlaceholder?: string;
/** Controlled search value */
searchValue?: string;
/** Callback when search changes */
onSearchChange?: (value: string) => void;
/** Custom filter function */
filterFn?: (item: SearchableListItem<T>, searchTerm: string) => boolean;
/** Debounce delay for search in ms */
debounceMs?: number;
/** Render function for each item */
renderItem: (item: SearchableListItem<T>, index: number, isSelected: boolean, isHighlighted: boolean) => ReactNode;
/** Currently selected item key */
selectedKey?: string;
/** Callback when item is selected */
onSelect?: (item: SearchableListItem<T>) => void;
/** Maximum height with overflow scroll */
maxHeight?: string | number;
/** Show result count */
showResultCount?: boolean;
/** Result count format function */
formatResultCount?: (count: number, total: number) => string;
/** Message when no items available */
emptyMessage?: string | ReactNode;
/** Message when search has no results */
noResultsMessage?: string | ReactNode;
/** Loading state */
loading?: boolean;
/** Loading message */
loadingMessage?: string | ReactNode;
/** Size variant */
size?: 'sm' | 'md' | 'lg';
/** Visual variant */
variant?: 'default' | 'bordered' | 'card';
/** Additional CSS classes */
className?: string;
/** Enable keyboard navigation (arrow keys, enter) */
enableKeyboardNavigation?: boolean;
/** Auto-focus search input */
autoFocus?: boolean;
}
/**
* SearchableList - List component with integrated search/filter functionality
*
* @example Basic usage
* ```tsx
* <SearchableList
* items={users.map(u => ({ key: u.id, data: u }))}
* renderItem={(item) => <div>{item.data.name}</div>}
* onSelect={(item) => setSelectedUser(item.data)}
* searchable
* searchPlaceholder="Search users..."
* />
* ```
*
* @example With custom filter and loading
* ```tsx
* <SearchableList
* items={products}
* renderItem={(item, index, isSelected) => (
* <div className={isSelected ? 'bg-accent-50' : ''}>
* {item.data.name} - ${item.data.price}
* </div>
* )}
* filterFn={(item, term) =>
* item.data.name.toLowerCase().includes(term.toLowerCase())
* }
* loading={isLoading}
* loadingMessage="Fetching products..."
* maxHeight="400px"
* />
* ```
*/
export default function SearchableList<T = unknown>({ items, searchPlaceholder, searchValue: controlledSearchValue, onSearchChange, filterFn, debounceMs, renderItem, selectedKey, onSelect, maxHeight, showResultCount, formatResultCount, emptyMessage, noResultsMessage, loading, loadingMessage, size, variant, className, enableKeyboardNavigation, autoFocus, }: SearchableListProps<T>): import("react/jsx-runtime").JSX.Element;
//# sourceMappingURL=SearchableList.d.ts.map