import { useIntersectionObserver } from '~/hooks/useIntersectionObserver' import { noop } from 'lodash-es' import { Check, ChevronsUpDown } from 'lucide-react' import { useEffect, useRef, useState } from 'react' import { Button_Shadcn_ as Button, cn, Command, CommandGroup as CommandGroup, CommandInput, CommandItem as CommandItem, CommandList as CommandList, Popover, PopoverContent, PopoverTrigger, ScrollArea, } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' export interface ComboBoxOption { id: string value: string displayName: string disabled?: boolean } export function ComboBox({ isLoading, disabled, name, options, selectedOption, selectedDisplayName, onSelectOption = noop, className, search = '', hasNextPage = false, isFetching = false, isFetchingNextPage = false, fetchNextPage, setSearch = () => {}, useCommandSearch = true, }: { isLoading: boolean disabled?: boolean name: string options: Opt[] selectedOption?: string selectedDisplayName?: string onSelectOption?: (newValue: string) => void className?: string search?: string hasNextPage?: boolean isFetching?: boolean isFetchingNextPage?: boolean fetchNextPage?: () => void setSearch?: (value: string) => void useCommandSearch?: boolean }) { const [open, setOpen] = useState(false) const scrollRootRef = useRef(null) const [sentinelRef, entry] = useIntersectionObserver({ root: scrollRootRef.current, threshold: 0, rootMargin: '0px', }) useEffect(() => { if (!isLoading && !isFetching && !isFetchingNextPage && hasNextPage && entry?.isIntersecting) { fetchNextPage?.() } }, [isLoading, isFetching, isFetchingNextPage, hasNextPage, entry?.isIntersecting, fetchNextPage]) return ( { setOpen(value) if (!value) setSearch('') }} > setSearch('')} /> {isLoading ? (
) : ( <> {search.length > 0 && options.length === 0 && (

No {name}s found based on your search

)} 7 ? 'h-[210px]' : ''}> {options.map((option) => ( { setOpen(false) onSelectOption(selectedValue) }} className="cursor-pointer" > {option.displayName} ))}
{hasNextPage && } )} ) }