import { KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Dropdown } from '@snack-uikit/dropdown'; import { ChevronRightSVG } from '@snack-uikit/icons'; import { ITEM_PREFIXES } from '../../../constants'; import { useCollapseContext, useFocusListContext, useNewListContext, useSelectionContext } from '../../Lists/contexts'; import { ListPrivate } from '../../Lists/ListPrivate'; import { BaseItem } from '../BaseItem'; import { useGroupItemSelection } from '../hooks'; import { CommonFlattenProps, FlattenNextListItem, ItemId } from '../types'; import { extractActiveItems, isNextListItem } from '../utils'; import { FALLBACK_PLACEMENTS } from './constants'; type NextListItemProps = Omit & CommonFlattenProps & { focusId?: ItemId }; export function NextListItem({ items, placement = 'right-start', id, scroll, scrollRef, disabled, onSublistOpenChanged, allChildIds, loading = false, focusId = id, untouchableScrollbars = false, ...option }: NextListItemProps) { const { flattenItems, focusFlattenItems, virtualized } = useNewListContext(); const { value, isSelectionSingle, isSelectionMultiple } = useSelectionContext(); const { openCollapseItems = [] } = useCollapseContext(); const item = flattenItems[id]; const { ids, expandedIds } = useMemo(() => { const { ids, expandedIds } = extractActiveItems({ focusCloseChildIds: items, focusFlattenItems, openCollapseItems, isSelectionMultiple, }); return { ids, expandedIds: expandedIds.concat([id]) }; }, [focusFlattenItems, id, isSelectionMultiple, items, openCollapseItems]); const { handleListKeyDownFactory, activeItemId, forceUpdateActiveItemId } = useFocusListContext(); const [open, setOpen] = useState(); const handleListKeyDown = useCallback( (e: KeyboardEvent) => { handleListKeyDownFactory(ids, expandedIds)(e); if (e.key === 'ArrowLeft') { forceUpdateActiveItemId?.(focusId); setOpen(false); e.stopPropagation(); return; } }, [handleListKeyDownFactory, ids, expandedIds, forceUpdateActiveItemId, focusId], ); const { indeterminate, checked: checkedProp, handleOnSelect, } = useGroupItemSelection({ items: isNextListItem(item) ? item.items : [], id, disabled, allChildIds, }); const handleOutsideClick = useCallback(() => { forceUpdateActiveItemId?.(ITEM_PREFIXES.dropFocus); setOpen(false); return true; }, [forceUpdateActiveItemId]); const isOpen = useMemo( () => Boolean(!disabled && activeItemId && focusFlattenItems[focusId].allChildIds.includes(activeItemId)), [activeItemId, disabled, focusFlattenItems, focusId], ); const checked = Boolean( (indeterminate && !open && isSelectionSingle && value && allChildIds.includes(value)) || (isSelectionMultiple && checkedProp), ); useEffect(() => { setOpen(open => open && isOpen); }, [id, isOpen]); const listRef = useRef(null); return ( { e.stopPropagation(); forceUpdateActiveItemId?.(ids[0]); }} scrollRef={scrollRef} limitedScrollHeight untouchableScrollbars={untouchableScrollbars} loading={loading} /> } trigger='hover' open={isOpen || open} onOpenChange={value => { setOpen(value); onSublistOpenChanged?.(value, id); }} placement={placement} widthStrategy='auto' > } id={id} isParentNode indeterminate={indeterminate} checked={checked} onOpenNestedList={() => { setOpen(true); setTimeout(() => { listRef.current?.focus(); }, 0); }} onSelect={handleOnSelect} /> ); }