import { autoUpdate, FloatingFocusManager, FloatingPortal, flip, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, } from '@floating-ui/react' import Fuse from 'fuse.js' import { useAtom, useAtomValue } from 'jotai' import { forwardRef, useId, useMemo, useRef, useState } from 'react' import { charactersAtom, selectedTargetInventoryAtom } from '@/state/atoms' interface AccountInventorySelectorItemProps { children: React.ReactNode active: boolean } const AccountInventorySelectorItem = forwardRef< HTMLDivElement, AccountInventorySelectorItemProps & React.HTMLProps >(({ children, active, ...rest }, ref) => { const id = useId() return (
{children}
) }) export const InventoryTargetSelector = () => { const [open, setOpen] = useState(false) const [inputValue, setInputValue] = useState('') const [activeIndex, setActiveIndex] = useState(null) const listRef = useRef>([]) const { refs, floatingStyles, context } = useFloating({ whileElementsMounted: autoUpdate, open, onOpenChange: setOpen, middleware: [ flip({ padding: 10 }), size({ apply({ rects, availableHeight, elements }) { Object.assign(elements.floating.style, { width: `${rects.reference.width}px`, maxHeight: `${availableHeight}px`, }) }, padding: 10, }), ], }) const role = useRole(context, { role: 'listbox' }) const dismiss = useDismiss(context) const listNav = useListNavigation(context, { listRef, activeIndex, onNavigate: setActiveIndex, virtual: true, loop: true, }) const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([ role, dismiss, listNav, ]) function onChange(event: React.ChangeEvent) { const value = event.target.value setInputValue(value) setSelectedTargetInventory(undefined) if (value) { setOpen(true) setActiveIndex(0) } else { setOpen(false) } } const { data: subaccounts } = useAtomValue(charactersAtom) const [selectedTargetInventory, setSelectedTargetInventory] = useAtom(selectedTargetInventoryAtom) const searcher = useMemo(() => { return new Fuse(subaccounts?.flatMap(x => [x.bank, x.character]) || [], { keys: ['path', 'name'], findAllMatches: true, threshold: 0.8, useExtendedSearch: true, }) }, [subaccounts]) const items = searcher.search(inputValue || '!-', { limit: 10 }).map(x => x.item) return ( <> {open && (
{items.map((item, index) => ( {item.name} ))}
)} ) }