Component exports
Components
| Prop | Type | Default | Description |
|---|---|---|---|
SearchableDropdown<T, G> | Component | — | Single-select searchable dropdown. T is the option type (string or object), G is the group context type. |
SearchableDropdownMulti<T, G> | Component | — | Multi-select variant with chip display, clear-all, and backspace deletion. |
imports.ts
import {
SearchableDropdown,
SearchableDropdownMulti,
} from "@luciodale/react-searchable-dropdown";Hook exports
Hooks
| Prop | Type | Default | Description |
|---|---|---|---|
useDebounce<T>(value, delay) | Hook | — | Returns [debouncedValue, setDebouncedValue]. When delay is 0, updates are immediate. Useful for debouncing external state that feeds into the dropdown. |
useDebounceExample.tsx
import { useDebounce } from "@luciodale/react-searchable-dropdown";
function MyComponent() {
const [query, setQuery] = useState("");
const [debouncedQuery] = useDebounce(query, 200);
// debouncedQuery updates 200ms after the last query change
}Option types
types.ts
// Base option type — either a string or an object
type TDropdownOption = TObjectLikeDropdownOption | TStringDropdownOption;
// String options
type TStringDropdownOption = string;
// Object options must have label and value
type TObjectDropdownOption = {
[key: string]: string | number | boolean;
label: string;
value: string;
};
// Created-on-the-fly options (when no match is found)
type TNewValueDropdownOption = {
isNewValue: true;
label: string;
value: string;
};
// Union of object option types
type TObjectLikeDropdownOption =
| TObjectDropdownOption
| TNewValueDropdownOption;Search types
search-types.ts
// Constrains searchOptionKeys to actual keys of the option type
type TSearchOptionKeys<T extends TDropdownOption> =
T extends { label: string; value: string }
? Array<Extract<keyof T, string>>
: never;
// Match-sorter ranking keys
type TSearchableDropdownFilterType = keyof typeof matchSorter.rankings;
// Values: "CASE_SENSITIVE_EQUAL" | "EQUAL" | "STARTS_WITH"
// | "WORD_STARTS_WITH" | "CONTAINS" | "ACRONYM"
// | "MATCHES" | "NO_MATCH"Group types
group-types.ts
// Discriminated union — provide both or neither
type TGroups<T extends TDropdownOption, G> =
| {
handleGroups: (
matchingOptions: T[]
) => {
groupCounts: number[];
groupCategories: string[];
};
groupContent: (
index: number,
groupCategories: string[],
context: G
) => React.ReactNode;
}
| {
handleGroups?: undefined;
groupContent?: undefined;
};Component prop types
component-types.ts
// Single select props (simplified)
type TSearchableDropdown<T, G> =
T extends TObjectLikeDropdownOption
? TSearchableCommon<T, G> & {
searchOptionKeys: Array<Extract<keyof T, string>>;
}
: TSearchableCommon<T, G> & {
searchOptionKeys?: undefined;
};
// Multi select props (simplified)
type TSearchableDropdownMulti<T, G> =
T extends TObjectLikeDropdownOption
? TSearchableCommonMulti<T, G> & {
searchOptionKeys: Array<Extract<keyof T, string>>;
}
: TSearchableCommonMulti<T, G> & {
searchOptionKeys?: undefined;
};
The conditional type structure means that TypeScript will require
searchOptionKeys when you pass object options and hide it when you pass
string options. This is enforced at the type level: you literally cannot pass a
meaningless searchOptionKeys to a string dropdown.
Wrapper prop types
The conditional types above (TSearchableDropdown, TSearchableDropdownMulti)
enforce searchOptionKeys at compile time. However, TypeScript cannot resolve conditional
types inside generic function bodies. If you are building a wrapper component that forwards
props generically, use the wrapper-friendly types instead.
wrapper-types.ts
// Wrapper-friendly: searchOptionKeys is always optional.
// Use these when building generic wrapper components.
type TSearchableDropdownProps<T extends TDropdownOption, G = unknown>
type TSearchableDropdownMultiProps<T extends TDropdownOption, G = unknown>Example: a wrapper that sets default props while staying generic over the option type.
WrapperExample.tsx
import {
SearchableDropdown,
type TSearchableDropdownProps,
type TDropdownOption,
} from "@luciodale/react-searchable-dropdown";
function MyDropdown<T extends TDropdownOption, G>(
props: TSearchableDropdownProps<T, G>
) {
return (
<SearchableDropdown
dropdownOptionsHeight={320}
placeholder="Search..."
debounceDelay={100}
{...props}
/>
);
}
// Usage — still fully typed
<MyDropdown options={["a", "b", "c"]} value={undefined} setValue={setValue} />
<MyDropdown
options={[{ label: "Red", value: "red" }]}
value={undefined}
setValue={setValue}
searchOptionKeys={["label"]}
/>CSS files
Importable stylesheets
| Prop | Type | Default | Description |
|---|---|---|---|
dist/single-style.css | CSS | — | Default dark theme for SearchableDropdown. Includes variables.css. |
dist/multi-style.css | CSS | — | Default dark theme for SearchableDropdownMulti. Includes variables.css and chip styles. |
dist/variables.css | CSS | — | CSS custom properties only. Import this if you want the variable definitions without the component styles. |
All type exports
type-imports.ts
import type {
TDropdownOption,
TNewValueDropdownOption,
TObjectDropdownOption,
TObjectLikeDropdownOption,
TStringDropdownOption,
TSearchableDropdown,
TSearchableDropdownMulti,
TSearchableDropdownProps,
TSearchableDropdownMultiProps,
TSearchableCommon,
TSearchableCommonMulti,
TSearchableDropdownFilterType,
TSearchOptionKeys,
TGroups,
} from "@luciodale/react-searchable-dropdown";