@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
126 lines (125 loc) • 8.35 kB
JavaScript
import { __assign, __rest } from "tslib";
import clsx from 'clsx';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { useAutosuggestItems, useFilteredItems, useKeyboardHandler, useSelectOption, useSelectVisibleOption, useHighlightVisibleOption } from './controller';
import { useDropdownA11yProps } from './a11y';
import Announcer from './announcer';
import VirtualList from './virtual-list';
import PlainList from './plain-list';
import Dropdown from '../internal/components/dropdown';
import DropdownStatus from '../internal/components/dropdown-status';
import { useFormFieldContext } from '../internal/context/form-field-context';
import { getBaseProps } from '../internal/base-component';
import { useUniqueId } from '../internal/hooks/use-unique-id';
import useForwardFocus from '../internal/hooks/forward-focus';
import { fireNonCancelableEvent } from '../internal/events';
import { useHighlightedOption } from '../internal/components/options-list/utils/use-highlight-option';
import InternalInput from '../input/internal';
import { useTelemetry } from '../internal/hooks/use-telemetry';
import styles from './styles.css.js';
var withinRange = function (items, index) {
return index >= -1 && index < items.length;
};
var isInteractive = function (option) {
return !!option && !option.disabled && option.type !== 'parent';
};
var handleMouseEvent = function (handler, usingMouse) { return function (e) {
e.preventDefault();
usingMouse.current = true;
var mouseTarget = e.detail.mouseTarget;
if (mouseTarget !== undefined) {
var index = parseInt(mouseTarget, 10);
if (index === index) {
handler(index);
}
}
}; };
var useLoadMoreItems = function (onLoadItems) {
var lastFilteringText = useRef(null);
return useCallback(function (firstPage, samePage, filteringText) {
if (samePage || !firstPage || filteringText === undefined || lastFilteringText.current !== filteringText) {
if (filteringText !== undefined) {
lastFilteringText.current = filteringText;
}
if (lastFilteringText.current !== null && onLoadItems) {
fireNonCancelableEvent(onLoadItems, { filteringText: lastFilteringText.current, firstPage: firstPage, samePage: samePage });
}
}
}, [onLoadItems]);
};
var Autosuggest = React.forwardRef(function (props, ref) {
var _a;
useTelemetry('Autosuggest');
var value = props.value, onChange = props.onChange, onBlur = props.onBlur, onFocus = props.onFocus, onKeyUp = props.onKeyUp, onLoadItems = props.onLoadItems, options = props.options, _b = props.filteringType, filteringType = _b === void 0 ? 'auto' : _b, _c = props.statusType, statusType = _c === void 0 ? 'finished' : _c, placeholder = props.placeholder, name = props.name, disabled = props.disabled, _d = props.disableBrowserAutocorrect, disableBrowserAutocorrect = _d === void 0 ? false : _d, autoFocus = props.autoFocus, readOnly = props.readOnly, ariaLabel = props.ariaLabel, ariaRequired = props.ariaRequired, enteredTextLabel = props.enteredTextLabel, onKeyDown = props.onKeyDown, virtualScroll = props.virtualScroll, rest = __rest(props, ["value", "onChange", "onBlur", "onFocus", "onKeyUp", "onLoadItems", "options", "filteringType", "statusType", "placeholder", "name", "disabled", "disableBrowserAutocorrect", "autoFocus", "readOnly", "ariaLabel", "ariaRequired", "enteredTextLabel", "onKeyDown", "virtualScroll"]);
var usingMouse = useRef(true);
var _e = useState(false), showAll = _e[0], setShowAll = _e[1];
var _f = useState(false), open = _f[0], setOpen = _f[1];
var autosuggestItems = useAutosuggestItems(options);
var filteredItems = useFilteredItems(autosuggestItems, value, filteringType, showAll);
var openDropdown = useCallback(function () { return !readOnly && setOpen(true); }, [readOnly]);
var scrollToIndex = useRef(null);
var _g = useHighlightedOption({
options: filteredItems,
scrollToIndex: (_a = scrollToIndex.current) !== null && _a !== void 0 ? _a : undefined,
withinRange: withinRange,
isInteractive: isInteractive
}), highlightedOption = _g.highlightedOption, moveHighlight = _g.moveHighlight, resetHighlight = _g.resetHighlight, setHighlightedIndex = _g.setHighlightedIndex;
var closeDropdown = useCallback(function () {
setOpen(false);
resetHighlight();
}, [setOpen, resetHighlight]);
var handleBlur = useCallback(function (e) {
closeDropdown();
onBlur && onBlur(e);
}, [closeDropdown, onBlur]);
var selectOption = useSelectOption(onChange, closeDropdown);
var selectHighlighted = useCallback(function () {
if (highlightedOption) {
selectOption(highlightedOption);
}
else {
closeDropdown();
}
}, [selectOption, highlightedOption, closeDropdown]);
var fireLoadMore = useLoadMoreItems(onLoadItems);
var handleDelayedInput = useCallback(function (_a) {
var detail = _a.detail;
fireLoadMore(true, false, detail.value);
}, [fireLoadMore]);
var handleInputChange = useCallback(function (e) {
openDropdown();
setShowAll(false);
resetHighlight();
onChange && onChange(e);
}, [onChange, openDropdown, resetHighlight, setShowAll]);
var highlightVisibleOption = useHighlightVisibleOption(filteredItems, setHighlightedIndex, isInteractive);
var selectVisibleOption = useSelectVisibleOption(filteredItems, selectOption, isInteractive);
var handleMouseDown = useMemo(function () { return handleMouseEvent(selectVisibleOption, usingMouse); }, [selectVisibleOption, usingMouse]);
var handleMouseMove = useMemo(function () { return handleMouseEvent(highlightVisibleOption, usingMouse); }, [highlightVisibleOption, usingMouse]);
var handleKeyDown = useKeyboardHandler(moveHighlight, openDropdown, selectHighlighted, usingMouse, onKeyDown);
var handleLoadMore = useCallback(function () {
options && options.length && statusType === 'pending' && fireLoadMore(false, false);
}, [fireLoadMore, options, statusType]);
var handleRecoveryClick = useCallback(function () { return fireLoadMore(false, true); }, [fireLoadMore]);
var formFieldContext = useFormFieldContext(rest);
var baseProps = getBaseProps(rest);
var inputRef = useRef(null);
useForwardFocus(ref, inputRef);
var listId = useUniqueId('list');
var _h = useDropdownA11yProps(listId, open, highlightedOption), inputA11yProps = _h[0], highlightedA11yProps = _h[1];
var nativeAttributes = __assign({ name: name,
placeholder: placeholder,
autoFocus: autoFocus, 'aria-label': ariaLabel }, inputA11yProps);
var handleFocus = useCallback(function (e) {
setShowAll(true);
openDropdown();
fireLoadMore(true, false, '');
onFocus && onFocus(e);
}, [setShowAll, openDropdown, onFocus, fireLoadMore]);
var dropdownStatus = (React.createElement(DropdownStatus, __assign({}, props, { onRecoveryClick: handleRecoveryClick, isEmpty: !value && !filteredItems.length })));
var ListComponent = virtualScroll ? VirtualList : PlainList;
return (React.createElement(Dropdown, __assign({}, baseProps, { className: clsx(styles.root, baseProps.className), onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, trigger: React.createElement(InternalInput, __assign({ type: "search", value: value, onChange: handleInputChange, onDelayedInput: handleDelayedInput, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, onKeyUp: onKeyUp, disabled: disabled, disableBrowserAutocorrect: disableBrowserAutocorrect, readOnly: readOnly, ariaRequired: ariaRequired, ref: inputRef, nativeAttributes: nativeAttributes }, formFieldContext)), open: open, dropdownId: listId }),
open && (React.createElement(ListComponent, { handleLoadMore: handleLoadMore, filteredItems: filteredItems, value: value, usingMouse: usingMouse, highlightedOption: highlightedOption, enteredTextLabel: enteredTextLabel, dropdownStatus: dropdownStatus, ref: scrollToIndex, highlightedA11yProps: highlightedA11yProps })),
React.createElement(Announcer, { item: highlightedOption, usingMouse: usingMouse })));
});
export default Autosuggest;