search-input
shuip/search-inputFreeComponent
shuip publishes no description for this item.
Install it
npx shadcn@latest add https://shuip.plvo.dev/r/search-input.jsonSource
1'use client';23import { Search } from 'lucide-react';4import * as React from 'react';5import { Input } from '@/components/ui/input';6import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';7import { cn } from '@/lib/utils';89function isEditableTarget(target: EventTarget | null): boolean {10 if (!(target instanceof HTMLElement)) return false;11 const tag = target.tagName;12 return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;13}1415export interface SearchInputProps extends Omit<React.ComponentProps<'input'>, 'onChange'> {16 onChange: (value: string) => void;17 debounceMs?: number;18 hotkey?: string | false;19 hotkeyTooltip?: string;20}2122export function SearchInput({23 value,24 onChange,25 placeholder = 'Search…',26 debounceMs = 250,27 hotkey = '/',28 hotkeyTooltip,29 autoFocus,30 className,31 ...props32}: SearchInputProps) {33 const inputRef = React.useRef<HTMLInputElement>(null);34 const timer = React.useRef<ReturnType<typeof setTimeout> | null>(null);35 const [text, setText] = React.useState(typeof value === 'string' ? value : '');36 const [prevValue, setPrevValue] = React.useState(value);37 const [focused, setFocused] = React.useState(false);38 const [hintOpen, setHintOpen] = React.useState(false);3940 if (prevValue !== value) {41 setPrevValue(value);42 if (typeof value === 'string') setText(value);43 }4445 const resolvedTooltip = hotkeyTooltip ?? (hotkey ? `Press ${hotkey} to search` : undefined);4647 React.useEffect(48 () => () => {49 if (timer.current) clearTimeout(timer.current);50 },51 [],52 );5354 React.useEffect(() => {55 if (!hotkey) return;56 function onKey(e: KeyboardEvent) {57 if (e.key !== hotkey || e.metaKey || e.ctrlKey || e.altKey) return;58 if (isEditableTarget(e.target)) return;59 e.preventDefault();60 inputRef.current?.focus();61 }62 document.addEventListener('keydown', onKey);63 return () => document.removeEventListener('keydown', onKey);64 }, [hotkey]);6566 function handleChange(next: string) {67 setText(next);68 if (timer.current) clearTimeout(timer.current);69 if (debounceMs <= 0) {70 onChange(next);71 return;72 }73 timer.current = setTimeout(() => onChange(next), debounceMs);74 }7576 const showHotkeyBadge = Boolean(hotkey) && !focused && text.length === 0;7778 return (79 <div className={cn('relative', className)}>80// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from shuip
All 52 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| confirmation-dialogconfirmation-dialog | shuip | Components | Free | 1 dep | |
| copy-buttoncopy-button | shuip | Components | Free | 3 deps | |
| hover-revealhover-reveal | shuip | Components | Free | 1 dep | |
| rhf-address-fieldrhf-address-field | shuip | Components | Free | 5 deps · 2 files | |
| rhf-autocomplete-fieldrhf-autocomplete-field | shuip | Components | Free | 4 deps | |
| rhf-checkbox-fieldrhf-checkbox-field | shuip | Components | Free | 3 deps | |
| rhf-combobox-fieldrhf-combobox-field | shuip | Components | Free | 5 deps | |
| rhf-date-fieldrhf-date-field | shuip | Components | Free | 6 deps |
