UNPKG

@awsui/components-react

Version:

AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A

184 lines (183 loc) • 8.72 kB
import { useEffect, useRef, useCallback } from 'react'; import { useHighlightedOption } from '../../internal/components/options-list/utils/use-highlight-option'; import { useOpenState } from '../../internal/components/options-list/utils/use-open-state'; import { useMenuKeyboard, useTriggerKeyboard, useSpaceAwareClickHandler } from '../../internal/components/options-list/utils/use-keyboard'; import { createMouseHandler } from '../../internal/components/dropdown/utils/mouse-handler'; import { useIds } from '../../internal/components/options-list/utils/use-ids'; import { useNativeSearch } from '../../internal/components/option/utils/use-native-search'; import { connectOptionsByValue } from './connect-options'; import useForwardFocus from '../../internal/hooks/forward-focus'; import { usePrevious } from '../../internal/hooks/use-previous'; var isInteractive = function (option) { return !!option && !option.disabled && option.type !== 'parent'; }; export var useSelect = function (_a) { var selectedOptions = _a.selectedOptions, updateSelectedOption = _a.updateSelectedOption, options = _a.options, filteringType = _a.filteringType, rootRef = _a.rootRef, externalRef = _a.externalRef, keepOpen = _a.keepOpen, multiSelection = _a.multiSelection, fireLoadItems = _a.fireLoadItems, setFilteringValue = _a.setFilteringValue, scrollToIndex = _a.scrollToIndex; var filterRef = useRef(); var triggerRef = useRef(); var menuRef = useRef(null); var hasFilter = filteringType !== 'none'; var activeRef = hasFilter ? filterRef : menuRef; var isKeyboard = useRef(false); var isSelectingUsingSpace = useRef(false); var __selectedOptions = connectOptionsByValue(options, selectedOptions); var _b = useHighlightedOption({ options: options, isInteractive: isInteractive, scrollToIndex: scrollToIndex }), highlightedOption = _b.highlightedOption, moveHighlight = _b.moveHighlight, resetHighlight = _b.resetHighlight, setHighlightedIndex = _b.setHighlightedIndex, highlightOption = _b.highlightOption, goHome = _b.goHome, goEnd = _b.goEnd; var onOpen = useCallback(function () { return fireLoadItems({ firstPage: true, samePage: false, filteringText: '' }); }, [ fireLoadItems ]); var onClose = useCallback(function () { return setFilteringValue(''); }, [setFilteringValue]); var _c = useOpenState({ resetHighlight: resetHighlight, onOpen: onOpen, onClose: onClose }), isOpen = _c.isOpen, openDropdown = _c.openDropdown, closeDropdown = _c.closeDropdown, toggleDropdown = _c.toggleDropdown; var isClosedAndNativeSearchAllowed = !multiSelection && isOpen === false && !hasFilter; var isNativeSearchEnabled = !hasFilter || isClosedAndNativeSearchAllowed; var hasHighlightedOption = !!highlightedOption; var hasSelectedOption = __selectedOptions.length > 0; var _d = useIds({ hasHighlightedOption: hasHighlightedOption, hasSelectedOption: hasSelectedOption }), highlightedOptionId = _d.highlightedOptionId, selectedOptionId = _d.selectedOptionId, menuId = _d.menuId; var selectOption = function (option) { isSelectingUsingSpace.current = false; var optionToSelect = option || highlightedOption; if (!optionToSelect) { return; } updateSelectedOption(optionToSelect.option); !keepOpen && closeDropdown(); }; var activeKeyDownHandler = useMenuKeyboard({ moveHighlight: moveHighlight, selectOption: selectOption, goHome: goHome, goEnd: goEnd, closeDropdown: closeDropdown, isKeyboard: isKeyboard, isSelectingUsingSpace: isSelectingUsingSpace, preventNativeSpace: !hasFilter }); var triggerKeyDownHandler = useTriggerKeyboard({ openDropdown: openDropdown, goHome: goHome, isKeyboard: isKeyboard }); var handleNativeSearch = useNativeSearch({ options: options, highlightOption: isClosedAndNativeSearchAllowed ? selectOption : highlightOption, highlightedOption: isClosedAndNativeSearchAllowed ? selectedOptions[0] : highlightedOption === null || highlightedOption === void 0 ? void 0 : highlightedOption.option, isInteractive: isInteractive, isKeyboard: isKeyboard }); var _e = useSpaceAwareClickHandler({ isSelectingUsingSpace: isSelectingUsingSpace, toggleDropdown: toggleDropdown }), triggerClickHandler = _e.triggerClickHandler, triggerKeyUpHandler = _e.triggerKeyUpHandler; var getTriggerProps = function (disabled) { var triggerProps = { ref: triggerRef }; if (!disabled) { triggerProps.onClick = triggerClickHandler; triggerProps.onKeyDown = triggerKeyDownHandler; triggerProps.onKeyUp = triggerKeyUpHandler; } if (hasSelectedOption) { triggerProps.ariaLabelledby = selectedOptionId; } return triggerProps; }; var getFilterProps = function () { var _a; var filterProps = {}; if (hasFilter) { filterProps.ref = filterRef; filterProps.onKeyDown = activeKeyDownHandler; filterProps.onBlur = closeDropdown; filterProps.nativeAttributes = (_a = { 'aria-activedescendant': highlightedOptionId }, _a['aria-owns'] = menuId, _a); } return filterProps; }; var getMenuProps = function () { var menuProps = { id: menuId, ref: menuRef, open: isOpen }; if (!hasFilter) { menuProps.onKeyDown = activeKeyDownHandler; menuProps.onBlur = closeDropdown; menuProps.nativeAttributes = { 'aria-activedescendant': highlightedOptionId }; } return menuProps; }; var mouseDownHandler = createMouseHandler(function (index) { isKeyboard.current = false; selectOption(options[index]); }); var mouseMoveHandler = createMouseHandler(function (index) { isKeyboard.current = false; setHighlightedIndex(index); }); var getDropdownProps = function () { var dropdownProps = { onMouseDown: mouseDownHandler, onMouseMove: mouseMoveHandler, open: isOpen }; return dropdownProps; }; var getOptionProps = function (option, index) { var _a; var highlighted = option === highlightedOption; var selected = __selectedOptions.indexOf(option) > -1; var optionProps = (_a = { key: index, option: option, highlighted: highlighted, selected: selected }, _a['data-mouse-target'] = isInteractive(option) ? index : -1, _a); if (highlighted) { optionProps.id = highlightedOptionId; } return optionProps; }; var prevOpen = usePrevious(isOpen); useEffect(function () { if (isOpen && !prevOpen && hasSelectedOption) { setHighlightedIndex(options.indexOf(__selectedOptions[0])); } }, [isOpen, __selectedOptions, hasSelectedOption, setHighlightedIndex, options, prevOpen]); useEffect(function () { var _a, _b, _c; if (isOpen) { (_a = activeRef.current) === null || _a === void 0 ? void 0 : _a.focus(); } else if ((_b = rootRef.current) === null || _b === void 0 ? void 0 : _b.contains(document.activeElement)) { (_c = triggerRef.current) === null || _c === void 0 ? void 0 : _c.focus(); } }, [isOpen, activeRef, triggerRef]); useEffect(function () { var _a; isNativeSearchEnabled && ((_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keypress', handleNativeSearch)); return function () { var _a; return (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keypress', handleNativeSearch); }; }, [isNativeSearchEnabled, handleNativeSearch]); useForwardFocus(externalRef, triggerRef); var announceSelected = !!highlightedOption && __selectedOptions.indexOf(highlightedOption) > -1; return { isOpen: isOpen, highlightedOption: highlightedOption, getTriggerProps: getTriggerProps, getMenuProps: getMenuProps, getDropdownProps: getDropdownProps, getFilterProps: getFilterProps, getOptionProps: getOptionProps, isKeyboard: isKeyboard.current, resetHighlight: resetHighlight, announceSelected: announceSelected }; };