UNPKG

react-bootstrap-typeahead

Version:
56 lines (55 loc) 2 kB
import PropTypes from 'prop-types'; import React, { useCallback, useEffect, useRef, } from 'react'; import scrollIntoView from 'scroll-into-view-if-needed'; import { useTypeaheadContext } from '../core/Context'; import { getDisplayName, getMenuItemId, preventInputBlur } from '../utils'; import { optionType } from '../propTypes'; const propTypes = { option: optionType.isRequired, position: PropTypes.number, }; export function useItem({ label, onClick, option, position, ...props }) { const { activeIndex, id, isOnlyResult, onActiveItemChange, onInitialItemChange, onMenuItemClick, setItem, } = useTypeaheadContext(); const itemRef = useRef(null); useEffect(() => { if (position === 0) { onInitialItemChange(option); } }); useEffect(() => { if (position === activeIndex) { onActiveItemChange(option); const node = itemRef.current; node && scrollIntoView(node, { block: 'nearest', boundary: node.parentNode, inline: 'nearest', scrollMode: 'if-needed', }); } }); const handleClick = useCallback((e) => { onMenuItemClick(option, e); onClick && onClick(e); }, [onClick, onMenuItemClick, option]); const active = isOnlyResult || activeIndex === position; setItem(option, position); return { ...props, active, 'aria-label': label, 'aria-selected': active, id: getMenuItemId(id, position), onClick: handleClick, onMouseDown: preventInputBlur, ref: itemRef, role: 'option', }; } export function withItem(Component) { const WrappedMenuItem = (props) => (React.createElement(Component, { ...props, ...useItem(props) })); WrappedMenuItem.displayName = `withItem(${getDisplayName(Component)})`; WrappedMenuItem.propTypes = propTypes; return WrappedMenuItem; }