@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
JavaScript
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
};
};