@ttt-productions/ui-core 0.2.16 → 0.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,55 @@
1
+ export interface SearchDropdownProps<T> {
2
+ /** Current search value */
3
+ value: string;
4
+ /** Called when search value changes */
5
+ onValueChange: (value: string) => void;
6
+ /** Search results array */
7
+ results: T[];
8
+ /** Loading state */
9
+ isLoading: boolean;
10
+ /** Error message */
11
+ error: string | null;
12
+ /** Called when a result is selected */
13
+ onSelect: (result: T) => void;
14
+ /** Called when search is cleared */
15
+ onClear: () => void;
16
+ /** Placeholder text */
17
+ placeholder?: string;
18
+ /** Label for the input */
19
+ label?: string;
20
+ /** Custom className */
21
+ className?: string;
22
+ /** Disabled state */
23
+ disabled?: boolean;
24
+ /** Icon to show in input (default: Search) */
25
+ icon?: React.ReactNode;
26
+ /** Minimum characters before showing results (default: 3) */
27
+ minChars?: number;
28
+ /** Message to show when no results found */
29
+ emptyMessage?: string;
30
+ /** Custom render function for each result */
31
+ renderResult: (result: T, index: number) => React.ReactNode;
32
+ }
33
+ /**
34
+ * Generic search dropdown component with debounced input and keyboard navigation.
35
+ * Supports any data type and custom rendering.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <SearchDropdown<User>
40
+ * value={searchValue}
41
+ * onValueChange={setSearchValue}
42
+ * results={users}
43
+ * isLoading={isLoading}
44
+ * error={error}
45
+ * onSelect={(user) => console.log(user)}
46
+ * onClear={() => setSearchValue('')}
47
+ * placeholder="Search users..."
48
+ * renderResult={(user) => (
49
+ * <div>{user.displayName}</div>
50
+ * )}
51
+ * />
52
+ * ```
53
+ */
54
+ export declare function SearchDropdown<T>({ value, onValueChange, results, isLoading, error, onSelect, onClear, placeholder, label, className, disabled, icon, minChars, emptyMessage, renderResult, }: SearchDropdownProps<T>): import("react").JSX.Element;
55
+ //# sourceMappingURL=search-dropdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-dropdown.d.ts","sourceRoot":"","sources":["../../src/components/search-dropdown.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,2BAA2B;IAC3B,OAAO,EAAE,CAAC,EAAE,CAAC;IACb,oBAAoB;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,oCAAoC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,YAAY,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,EAChC,KAAK,EACL,aAAa,EACb,OAAO,EACP,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAyB,EACzB,KAAK,EACL,SAAS,EACT,QAAgB,EAChB,IAAqC,EACrC,QAAY,EACZ,YAAiC,EACjC,YAAY,GACb,EAAE,mBAAmB,CAAC,CAAC,CAAC,+BA2JxB"}
@@ -0,0 +1,129 @@
1
+ 'use client';
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import { Input } from './input';
4
+ import { Label } from './label';
5
+ import { Loader2, X, Search } from 'lucide-react';
6
+ import { cn } from '../lib/utils';
7
+ /**
8
+ * Generic search dropdown component with debounced input and keyboard navigation.
9
+ * Supports any data type and custom rendering.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <SearchDropdown<User>
14
+ * value={searchValue}
15
+ * onValueChange={setSearchValue}
16
+ * results={users}
17
+ * isLoading={isLoading}
18
+ * error={error}
19
+ * onSelect={(user) => console.log(user)}
20
+ * onClear={() => setSearchValue('')}
21
+ * placeholder="Search users..."
22
+ * renderResult={(user) => (
23
+ * <div>{user.displayName}</div>
24
+ * )}
25
+ * />
26
+ * ```
27
+ */
28
+ export function SearchDropdown({ value, onValueChange, results, isLoading, error, onSelect, onClear, placeholder = 'Search...', label, className, disabled = false, icon = <Search className="h-4 w-4"/>, minChars = 3, emptyMessage = 'No results found', renderResult, }) {
29
+ const [isOpen, setIsOpen] = useState(false);
30
+ const [selectedIndex, setSelectedIndex] = useState(-1);
31
+ const containerRef = useRef(null);
32
+ const inputRef = useRef(null);
33
+ // Close dropdown when clicking outside
34
+ useEffect(() => {
35
+ const handleClickOutside = (event) => {
36
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
37
+ setIsOpen(false);
38
+ }
39
+ };
40
+ document.addEventListener('mousedown', handleClickOutside);
41
+ return () => document.removeEventListener('mousedown', handleClickOutside);
42
+ }, []);
43
+ // Show dropdown when there are results or loading/error states
44
+ useEffect(() => {
45
+ if (value.length >= minChars && (results.length > 0 || isLoading || error)) {
46
+ setIsOpen(true);
47
+ }
48
+ else {
49
+ setIsOpen(false);
50
+ }
51
+ }, [value, results, isLoading, error, minChars]);
52
+ // Reset selected index when results change
53
+ useEffect(() => {
54
+ setSelectedIndex(-1);
55
+ }, [results]);
56
+ const handleKeyDown = (e) => {
57
+ if (!isOpen || results.length === 0)
58
+ return;
59
+ switch (e.key) {
60
+ case 'ArrowDown':
61
+ e.preventDefault();
62
+ setSelectedIndex((prev) => (prev < results.length - 1 ? prev + 1 : prev));
63
+ break;
64
+ case 'ArrowUp':
65
+ e.preventDefault();
66
+ setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));
67
+ break;
68
+ case 'Enter':
69
+ e.preventDefault();
70
+ if (selectedIndex >= 0 && selectedIndex < results.length) {
71
+ onSelect(results[selectedIndex]);
72
+ setIsOpen(false);
73
+ }
74
+ break;
75
+ case 'Escape':
76
+ e.preventDefault();
77
+ setIsOpen(false);
78
+ inputRef.current?.blur();
79
+ break;
80
+ }
81
+ };
82
+ const handleResultClick = (result) => {
83
+ onSelect(result);
84
+ setIsOpen(false);
85
+ };
86
+ const handleClear = () => {
87
+ onClear();
88
+ setIsOpen(false);
89
+ inputRef.current?.focus();
90
+ };
91
+ const showDropdown = isOpen && value.length >= minChars;
92
+ return (<div ref={containerRef} className={cn('relative', className)}>
93
+ {label && (<Label htmlFor="search-input" className="mb-2 block">
94
+ {label}
95
+ </Label>)}
96
+
97
+ <div className="relative">
98
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">
99
+ {icon}
100
+ </div>
101
+
102
+ <Input ref={inputRef} id="search-input" type="text" value={value} onChange={(e) => onValueChange(e.target.value)} onKeyDown={handleKeyDown} placeholder={placeholder} disabled={disabled} className="pl-10 pr-10"/>
103
+
104
+ <div className="absolute right-3 top-1/2 -translate-y-1/2">
105
+ {isLoading ? (<Loader2 className="h-4 w-4 animate-spin text-muted-foreground"/>) : value ? (<button type="button" onClick={handleClear} className="text-muted-foreground hover:text-foreground transition-colors" aria-label="Clear search">
106
+ <X className="h-4 w-4"/>
107
+ </button>) : null}
108
+ </div>
109
+ </div>
110
+
111
+ {showDropdown && (<div className="absolute z-50 w-full mt-1 bg-popover border rounded-md shadow-lg max-h-60 overflow-auto">
112
+ {error ? (<div className="px-3 py-2 text-sm text-destructive">
113
+ {error}
114
+ </div>) : isLoading ? (<div className="px-3 py-2 text-sm text-muted-foreground flex items-center gap-2">
115
+ <Loader2 className="h-4 w-4 animate-spin"/>
116
+ Searching...
117
+ </div>) : results.length === 0 ? (<div className="px-3 py-2 text-sm text-muted-foreground">
118
+ {emptyMessage}
119
+ </div>) : (results.map((result, index) => (<button key={index} type="button" onClick={() => handleResultClick(result)} onMouseEnter={() => setSelectedIndex(index)} className={cn('w-full text-left transition-colors cursor-pointer', 'hover:bg-accent focus:bg-accent focus:outline-none', selectedIndex === index && 'bg-accent')}>
120
+ {renderResult(result, index)}
121
+ </button>)))}
122
+ </div>)}
123
+
124
+ {value.length > 0 && value.length < minChars && (<p className="text-xs text-muted-foreground mt-1">
125
+ Type at least {minChars} characters to search
126
+ </p>)}
127
+ </div>);
128
+ }
129
+ //# sourceMappingURL=search-dropdown.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-dropdown.jsx","sourceRoot":"","sources":["../../src/components/search-dropdown.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  const TOAST_LIMIT = 1;
3
- const TOAST_REMOVE_DELAY = 1000000;
3
+ const TOAST_REMOVE_DELAY = 1000;
4
4
  const toastTimeouts = new Map();
5
5
  const reducer = (state, action) => {
6
6
  switch (action.type) {
@@ -1 +1 @@
1
- {"version":3,"file":"use-toast.jsx","sourceRoot":"","sources":["../../src/hooks/use-toast.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-toast.jsx","sourceRoot":"","sources":["../../src/hooks/use-toast.tsx"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export * from "./components/scroll-area";
31
31
  export * from "./components/table";
32
32
  export * from "./components/sheet";
33
33
  export * from "./components/collapsible";
34
+ export * from "./components/search-dropdown";
34
35
  export * from "./components/layout/screen-adaptive-view";
35
36
  export * from "./hooks/use-media-query";
36
37
  export * from "./lib/utils";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,0CAA0C,CAAC;AAGzD,cAAc,yBAAyB,CAAC;AAGxC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAG7C,cAAc,0CAA0C,CAAC;AAGzD,cAAc,yBAAyB,CAAC;AAGxC,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ export * from "./components/scroll-area";
32
32
  export * from "./components/table";
33
33
  export * from "./components/sheet";
34
34
  export * from "./components/collapsible";
35
+ export * from "./components/search-dropdown";
35
36
  // Layout
36
37
  export * from "./components/layout/screen-adaptive-view";
37
38
  // Hooks
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AAEzC,SAAS;AACT,cAAc,0CAA0C,CAAC;AAEzD,QAAQ;AACR,cAAc,yBAAyB,CAAC;AAExC,mBAAmB;AACnB,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAE7C,SAAS;AACT,cAAc,0CAA0C,CAAC;AAEzD,QAAQ;AACR,cAAc,yBAAyB,CAAC;AAExC,mBAAmB;AACnB,cAAc,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/ui-core",
3
- "version": "0.2.16",
3
+ "version": "0.2.19",
4
4
  "description": "Shared UI components for TTT Productions projects",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,234 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { Input } from './input';
5
+ import { Label } from './label';
6
+ import { Loader2, X, Search } from 'lucide-react';
7
+ import { cn } from '../lib/utils';
8
+
9
+ export interface SearchDropdownProps<T> {
10
+ /** Current search value */
11
+ value: string;
12
+ /** Called when search value changes */
13
+ onValueChange: (value: string) => void;
14
+ /** Search results array */
15
+ results: T[];
16
+ /** Loading state */
17
+ isLoading: boolean;
18
+ /** Error message */
19
+ error: string | null;
20
+ /** Called when a result is selected */
21
+ onSelect: (result: T) => void;
22
+ /** Called when search is cleared */
23
+ onClear: () => void;
24
+ /** Placeholder text */
25
+ placeholder?: string;
26
+ /** Label for the input */
27
+ label?: string;
28
+ /** Custom className */
29
+ className?: string;
30
+ /** Disabled state */
31
+ disabled?: boolean;
32
+ /** Icon to show in input (default: Search) */
33
+ icon?: React.ReactNode;
34
+ /** Minimum characters before showing results (default: 3) */
35
+ minChars?: number;
36
+ /** Message to show when no results found */
37
+ emptyMessage?: string;
38
+ /** Custom render function for each result */
39
+ renderResult: (result: T, index: number) => React.ReactNode;
40
+ }
41
+
42
+ /**
43
+ * Generic search dropdown component with debounced input and keyboard navigation.
44
+ * Supports any data type and custom rendering.
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * <SearchDropdown<User>
49
+ * value={searchValue}
50
+ * onValueChange={setSearchValue}
51
+ * results={users}
52
+ * isLoading={isLoading}
53
+ * error={error}
54
+ * onSelect={(user) => console.log(user)}
55
+ * onClear={() => setSearchValue('')}
56
+ * placeholder="Search users..."
57
+ * renderResult={(user) => (
58
+ * <div>{user.displayName}</div>
59
+ * )}
60
+ * />
61
+ * ```
62
+ */
63
+ export function SearchDropdown<T>({
64
+ value,
65
+ onValueChange,
66
+ results,
67
+ isLoading,
68
+ error,
69
+ onSelect,
70
+ onClear,
71
+ placeholder = 'Search...',
72
+ label,
73
+ className,
74
+ disabled = false,
75
+ icon = <Search className="h-4 w-4" />,
76
+ minChars = 3,
77
+ emptyMessage = 'No results found',
78
+ renderResult,
79
+ }: SearchDropdownProps<T>) {
80
+ const [isOpen, setIsOpen] = useState(false);
81
+ const [selectedIndex, setSelectedIndex] = useState(-1);
82
+ const containerRef = useRef<HTMLDivElement>(null);
83
+ const inputRef = useRef<HTMLInputElement>(null);
84
+
85
+ // Close dropdown when clicking outside
86
+ useEffect(() => {
87
+ const handleClickOutside = (event: MouseEvent) => {
88
+ if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
89
+ setIsOpen(false);
90
+ }
91
+ };
92
+
93
+ document.addEventListener('mousedown', handleClickOutside);
94
+ return () => document.removeEventListener('mousedown', handleClickOutside);
95
+ }, []);
96
+
97
+ // Show dropdown when there are results or loading/error states
98
+ useEffect(() => {
99
+ if (value.length >= minChars && (results.length > 0 || isLoading || error)) {
100
+ setIsOpen(true);
101
+ } else {
102
+ setIsOpen(false);
103
+ }
104
+ }, [value, results, isLoading, error, minChars]);
105
+
106
+ // Reset selected index when results change
107
+ useEffect(() => {
108
+ setSelectedIndex(-1);
109
+ }, [results]);
110
+
111
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
112
+ if (!isOpen || results.length === 0) return;
113
+
114
+ switch (e.key) {
115
+ case 'ArrowDown':
116
+ e.preventDefault();
117
+ setSelectedIndex((prev) => (prev < results.length - 1 ? prev + 1 : prev));
118
+ break;
119
+ case 'ArrowUp':
120
+ e.preventDefault();
121
+ setSelectedIndex((prev) => (prev > 0 ? prev - 1 : 0));
122
+ break;
123
+ case 'Enter':
124
+ e.preventDefault();
125
+ if (selectedIndex >= 0 && selectedIndex < results.length) {
126
+ onSelect(results[selectedIndex]);
127
+ setIsOpen(false);
128
+ }
129
+ break;
130
+ case 'Escape':
131
+ e.preventDefault();
132
+ setIsOpen(false);
133
+ inputRef.current?.blur();
134
+ break;
135
+ }
136
+ };
137
+
138
+ const handleResultClick = (result: T) => {
139
+ onSelect(result);
140
+ setIsOpen(false);
141
+ };
142
+
143
+ const handleClear = () => {
144
+ onClear();
145
+ setIsOpen(false);
146
+ inputRef.current?.focus();
147
+ };
148
+
149
+ const showDropdown = isOpen && value.length >= minChars;
150
+
151
+ return (
152
+ <div ref={containerRef} className={cn('relative', className)}>
153
+ {label && (
154
+ <Label htmlFor="search-input" className="mb-2 block">
155
+ {label}
156
+ </Label>
157
+ )}
158
+
159
+ <div className="relative">
160
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">
161
+ {icon}
162
+ </div>
163
+
164
+ <Input
165
+ ref={inputRef}
166
+ id="search-input"
167
+ type="text"
168
+ value={value}
169
+ onChange={(e) => onValueChange(e.target.value)}
170
+ onKeyDown={handleKeyDown}
171
+ placeholder={placeholder}
172
+ disabled={disabled}
173
+ className="pl-10 pr-10"
174
+ />
175
+
176
+ <div className="absolute right-3 top-1/2 -translate-y-1/2">
177
+ {isLoading ? (
178
+ <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
179
+ ) : value ? (
180
+ <button
181
+ type="button"
182
+ onClick={handleClear}
183
+ className="text-muted-foreground hover:text-foreground transition-colors"
184
+ aria-label="Clear search"
185
+ >
186
+ <X className="h-4 w-4" />
187
+ </button>
188
+ ) : null}
189
+ </div>
190
+ </div>
191
+
192
+ {showDropdown && (
193
+ <div className="absolute z-50 w-full mt-1 bg-popover border rounded-md shadow-lg max-h-60 overflow-auto">
194
+ {error ? (
195
+ <div className="px-3 py-2 text-sm text-destructive">
196
+ {error}
197
+ </div>
198
+ ) : isLoading ? (
199
+ <div className="px-3 py-2 text-sm text-muted-foreground flex items-center gap-2">
200
+ <Loader2 className="h-4 w-4 animate-spin" />
201
+ Searching...
202
+ </div>
203
+ ) : results.length === 0 ? (
204
+ <div className="px-3 py-2 text-sm text-muted-foreground">
205
+ {emptyMessage}
206
+ </div>
207
+ ) : (
208
+ results.map((result, index) => (
209
+ <button
210
+ key={index}
211
+ type="button"
212
+ onClick={() => handleResultClick(result)}
213
+ onMouseEnter={() => setSelectedIndex(index)}
214
+ className={cn(
215
+ 'w-full text-left transition-colors cursor-pointer',
216
+ 'hover:bg-accent focus:bg-accent focus:outline-none',
217
+ selectedIndex === index && 'bg-accent'
218
+ )}
219
+ >
220
+ {renderResult(result, index)}
221
+ </button>
222
+ ))
223
+ )}
224
+ </div>
225
+ )}
226
+
227
+ {value.length > 0 && value.length < minChars && (
228
+ <p className="text-xs text-muted-foreground mt-1">
229
+ Type at least {minChars} characters to search
230
+ </p>
231
+ )}
232
+ </div>
233
+ );
234
+ }
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
 
3
3
  const TOAST_LIMIT = 1;
4
- const TOAST_REMOVE_DELAY = 1000000;
4
+ const TOAST_REMOVE_DELAY = 1000;
5
5
 
6
6
  export type ToastVariant = "default" | "destructive" | "success" | "warning" | "error";
7
7
 
package/src/index.ts CHANGED
@@ -32,6 +32,7 @@ export * from "./components/scroll-area";
32
32
  export * from "./components/table";
33
33
  export * from "./components/sheet";
34
34
  export * from "./components/collapsible";
35
+ export * from "./components/search-dropdown";
35
36
 
36
37
  // Layout
37
38
  export * from "./components/layout/screen-adaptive-view";