diff --git a/distribution_fe/components/ui/select.tsx b/distribution_fe/components/ui/select.tsx index fbb1cd0..8b25b53 100644 --- a/distribution_fe/components/ui/select.tsx +++ b/distribution_fe/components/ui/select.tsx @@ -5,7 +5,9 @@ import { Select as SelectPrimitive } from "@base-ui/react/select" import { cn } from "@/lib/utils" import { HugeiconsIcon } from "@hugeicons/react" -import { UnfoldMoreIcon, Tick02Icon, ArrowUp01Icon, ArrowDown01Icon } from "@hugeicons/core-free-icons" +import { UnfoldMoreIcon, Tick02Icon, ArrowUp01Icon, ArrowDown01Icon, Search01Icon } from "@hugeicons/core-free-icons" + +const SEARCH_THRESHOLD = 7 function collectSelectItems(children: React.ReactNode): Array<{ value: unknown; label: string }> { const items: Array<{ value: unknown; label: string }> = [] @@ -66,6 +68,57 @@ function getItemLabel(children: React.ReactNode): string | undefined { return undefined } +function filterSelectChildren(children: React.ReactNode, query: string): React.ReactNode { + const normalizedQuery = query.trim().toLowerCase() + if (!normalizedQuery) return children + + const filtered = React.Children.map(children, (child) => { + if (!React.isValidElement<{ value?: unknown; label?: string; children?: React.ReactNode }>(child)) { + return child + } + + if ("value" in child.props) { + const label = child.props.label ?? getItemLabel(child.props.children) ?? "" + return label.toLowerCase().includes(normalizedQuery) ? child : null + } + + if (child.props.children) { + const filteredChildren = filterSelectChildren(child.props.children, query) + if (React.Children.count(filteredChildren) === 0) return null + return React.cloneElement(child, undefined, filteredChildren) + } + + return child + }) + + return filtered +} + +function SelectSearchInput({ + query, + onQueryChange, +}: { + query: string + onQueryChange: (value: string) => void +}) { + return ( +