@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
105 lines (104 loc) • 8.18 kB
JavaScript
import { __assign, __rest, __spreadArrays } from "tslib";
import React, { useCallback, useMemo, useState, useRef } from 'react';
import clsx from 'clsx';
import styles from './styles.css.js';
import Dropdown from '../internal/components/dropdown';
import DropdownStatus from '../internal/components/dropdown-status';
import Filter from '../select/parts/filter';
import Trigger from '../select/parts/trigger';
import SelectedTokens from '../internal/components/selected-tokens';
import { LiveRegion } from '../internal/components/live-region';
import { getBaseProps } from '../internal/base-component';
import { flattenOptions } from '../internal/components/option/utils/flatten-options';
import { filterOptions } from '../internal/components/option/utils/filter-options';
import { useSelect } from '../select/utils/use-select';
import { fireNonCancelableEvent } from '../internal/events';
import { useSelectedTokens } from './utils/use-selected-tokens';
import { useLoadItems } from '../select/utils/use-load-items';
import { useAnnouncement } from '../select/utils/use-announcement';
import { useFocusTracker } from '../internal/hooks/use-focus-tracker';
import { useFormFieldContext } from '../internal/context/form-field-context';
import { findOptionIndex } from '../select/utils/connect-options';
import { generateTestIndexes } from '../internal/components/options-list/utils/test-indexes';
import PlainList from '../select/parts/plain-list';
import VirtualList from '../select/parts/virtual-list';
import { useTelemetry } from '../internal/hooks/use-telemetry';
var InternalMultiselect = React.forwardRef(function (_a, externalRef) {
var _b;
var _c = _a.options, options = _c === void 0 ? [] : _c, _d = _a.filteringType, filteringType = _d === void 0 ? 'none' : _d, filteringPlaceholder = _a.filteringPlaceholder, filteringAriaLabel = _a.filteringAriaLabel, ariaRequired = _a.ariaRequired, placeholder = _a.placeholder, disabled = _a.disabled, ariaLabel = _a.ariaLabel, _e = _a.statusType, statusType = _e === void 0 ? 'finished' : _e, empty = _a.empty, loadingText = _a.loadingText, finishedText = _a.finishedText, errorText = _a.errorText, recoveryText = _a.recoveryText, noMatch = _a.noMatch, selectedAriaLabel = _a.selectedAriaLabel, renderHighlightedAriaLive = _a.renderHighlightedAriaLive, _f = _a.selectedOptions, selectedOptions = _f === void 0 ? [] : _f, deselectAriaLabel = _a.deselectAriaLabel, _g = _a.keepOpen, keepOpen = _g === void 0 ? true : _g, tokenLimit = _a.tokenLimit, i18nStrings = _a.i18nStrings, onBlur = _a.onBlur, onFocus = _a.onFocus, onLoadItems = _a.onLoadItems, onChange = _a.onChange, virtualScroll = _a.virtualScroll, _h = _a.__hideTokens, __hideTokens = _h === void 0 ? false : _h, restProps = __rest(_a, ["options", "filteringType", "filteringPlaceholder", "filteringAriaLabel", "ariaRequired", "placeholder", "disabled", "ariaLabel", "statusType", "empty", "loadingText", "finishedText", "errorText", "recoveryText", "noMatch", "selectedAriaLabel", "renderHighlightedAriaLive", "selectedOptions", "deselectAriaLabel", "keepOpen", "tokenLimit", "i18nStrings", "onBlur", "onFocus", "onLoadItems", "onChange", "virtualScroll", "__hideTokens"]);
useTelemetry('Multiselect');
var baseProps = getBaseProps(restProps);
var formFieldContext = useFormFieldContext(restProps);
var _j = useLoadItems({
onLoadItems: onLoadItems,
options: options,
statusType: statusType
}), fireDelayedInput = _j.fireDelayedInput, handleLoadMore = _j.handleLoadMore, handleRecoveryClick = _j.handleRecoveryClick, fireLoadItems = _j.fireLoadItems;
var _k = useState(''), filteringValue = _k[0], setFilteringValue = _k[1];
var updateSelectedOption = useCallback(function (option) {
var newSelectedOptions = __spreadArrays(selectedOptions);
var index = findOptionIndex(newSelectedOptions, option);
if (index > -1) {
newSelectedOptions.splice(index, 1);
}
else {
newSelectedOptions.push(option);
}
fireNonCancelableEvent(onChange, {
selectedOptions: newSelectedOptions
});
}, [onChange, selectedOptions]);
var _l = useMemo(function () {
return flattenOptions(options);
}, [options]), flatOptions = _l.flatOptions, parentMap = _l.parentMap;
var filteredOptions = useMemo(function () {
if (filteringType !== 'auto') {
return flatOptions;
}
return filterOptions(flatOptions, filteringValue);
}, [flatOptions, filteringType, filteringValue]);
generateTestIndexes(filteredOptions, parentMap.get.bind(parentMap));
var rootRef = useRef();
useFocusTracker({ rootRef: rootRef, onBlur: onBlur, onFocus: onFocus });
var scrollToIndex = useRef(null);
var _m = useSelect({
selectedOptions: selectedOptions,
updateSelectedOption: updateSelectedOption,
options: filteredOptions,
filteringType: filteringType,
rootRef: rootRef,
externalRef: externalRef,
keepOpen: keepOpen,
multiSelection: true,
fireLoadItems: fireLoadItems,
setFilteringValue: setFilteringValue,
scrollToIndex: (_b = scrollToIndex.current) !== null && _b !== void 0 ? _b : undefined
}), isOpen = _m.isOpen, highlightedOption = _m.highlightedOption, getTriggerProps = _m.getTriggerProps, getFilterProps = _m.getFilterProps, getMenuProps = _m.getMenuProps, getDropdownProps = _m.getDropdownProps, getOptionProps = _m.getOptionProps, isKeyboard = _m.isKeyboard, resetHighlight = _m.resetHighlight, announceSelected = _m.announceSelected;
var filter = (React.createElement(Filter, { filteringType: filteringType, filteringPlaceholder: filteringPlaceholder, filteringAriaLabel: filteringAriaLabel, ariaRequired: ariaRequired, filterProps: getFilterProps(), filteringValue: filteringValue, setFilteringValue: setFilteringValue, resetHighlight: resetHighlight, fireDelayedInput: fireDelayedInput }));
var trigger = (React.createElement(Trigger, __assign({ placeholder: placeholder, disabled: disabled, ariaLabel: ariaLabel, triggerProps: getTriggerProps(disabled), selectedOption: null, isOpen: isOpen }, formFieldContext)));
var dropdownProps = __assign({ trigger: trigger, header: filter }, getDropdownProps());
var menuProps = __assign(__assign({}, getMenuProps()), { onLoadMore: handleLoadMore });
var dropdownStatus = (React.createElement(DropdownStatus, { statusType: statusType, empty: empty, loadingText: loadingText, finishedText: finishedText, errorText: errorText, recoveryText: recoveryText, noMatch: noMatch, onRecoveryClick: handleRecoveryClick, isNoMatch: filteredOptions && filteredOptions.length === 0, isEmpty: !options || options.length === 0 }));
var announcement = useAnnouncement({
announceSelected: announceSelected,
highlightedOption: highlightedOption,
parentMap: parentMap,
selectedAriaLabel: selectedAriaLabel,
renderHighlightedAriaLive: renderHighlightedAriaLive
});
var selectedTokensProps = useSelectedTokens({
disabled: disabled,
tokenLimit: tokenLimit,
i18nStrings: i18nStrings,
selectedOptions: selectedOptions,
updateSelectedOption: updateSelectedOption,
updateFocus: function () { return getTriggerProps().ref.current.focus(); }
});
var ListComponent = virtualScroll ? VirtualList : PlainList;
return (React.createElement("div", __assign({}, baseProps, { ref: rootRef, className: clsx(styles.root, baseProps.className) }),
React.createElement(Dropdown, __assign({}, dropdownProps),
React.createElement(ListComponent, { menuProps: menuProps, getOptionProps: getOptionProps, filteredOptions: filteredOptions, filteringValue: filteringValue, isKeyboard: isKeyboard, dropdownStatus: dropdownStatus, ref: scrollToIndex, checkboxes: true })),
!__hideTokens && React.createElement(SelectedTokens, __assign({}, selectedTokensProps, { deselectAriaLabel: deselectAriaLabel })),
isKeyboard && React.createElement(LiveRegion, { message: announcement })));
});
export default InternalMultiselect;