UNPKG

@ant-design/x

Version:

Craft AI-driven interfaces effortlessly

97 lines (95 loc) 2.78 kB
import { useEvent } from 'rc-util'; import React from 'react'; /** * Since Cascader not support ref active, we use `value` to mock the active item. */ export default function useActive(items, open, rtl, onSelect, onCancel) { const [activePaths, setActivePaths] = React.useState([]); /** Get items by column index */ const getItems = (colIndex, paths = activePaths) => { let currentItems = items; for (let i = 0; i < colIndex - 1; i += 1) { const activePath = paths[i]; const activeItem = currentItems.find(item => item.value === activePath); if (!activeItem) { break; } currentItems = activeItem.children || []; } return currentItems; }; const getValues = paths => { return paths.map((path, index) => { const currentItems = getItems(index + 1, paths); const currentItem = currentItems.find(item => item.value === path); return currentItem?.value; }); }; const offsetRow = offset => { const currentColIndex = activePaths.length || 1; const currentItems = getItems(currentColIndex); const currentRowIndex = currentItems.findIndex(item => item.value === activePaths[currentColIndex - 1]); const itemCount = currentItems.length; const nextItem = currentItems[(currentRowIndex + offset + itemCount) % itemCount]; setActivePaths([...activePaths.slice(0, currentColIndex - 1), nextItem.value]); }; const offsetPrev = () => { if (activePaths.length > 1) { setActivePaths(activePaths.slice(0, activePaths.length - 1)); } }; const offsetNext = () => { const nextItems = getItems(activePaths.length + 1); if (nextItems.length) { setActivePaths([...activePaths, nextItems[0].value]); } }; const onKeyDown = useEvent(e => { if (!open) { return; } switch (e.key) { case 'ArrowDown': offsetRow(1); e.preventDefault(); break; case 'ArrowUp': offsetRow(-1); e.preventDefault(); break; case 'ArrowRight': if (rtl) { offsetPrev(); } else { offsetNext(); } e.preventDefault(); break; case 'ArrowLeft': if (rtl) { offsetNext(); } else { offsetPrev(); } e.preventDefault(); break; case 'Enter': // Submit if not have children if (!getItems(activePaths.length + 1).length) { onSelect(getValues(activePaths)); } e.preventDefault(); break; case 'Escape': onCancel(); e.preventDefault(); break; } }); React.useEffect(() => { if (open) { setActivePaths([items[0].value]); } }, [open]); return [activePaths, onKeyDown]; }