@yandex/ui
Version:
Yandex UI components
77 lines (76 loc) • 5.14 kB
JavaScript
import { __assign, __rest } from "tslib";
import React from 'react';
import { Registry, withRegistry } from '@bem-react/di';
import { compose } from '@bem-react/core';
import { cn } from '@bem-react/classname';
import { Select, cnSelect } from '../../Select.bundle/desktop';
import { withOutsideClick } from '../../../withOutsideClick/withOutsideClick';
import { withZIndex } from '../../../withZIndex/withZIndex';
import { Popup } from '../../../Popup/Popup.bundle/desktop';
import { Menu } from '../../../Menu/Menu.bundle/desktop';
import { Icon } from '../../../Icon/Icon.bundle/desktop';
import { Text } from '../../../Text/Text.bundle/desktop';
import { Button } from '../../../Button/Button.bundle/desktop';
import { ListTile } from '../../../ListTile/ListTile';
import { Textinput } from '../../../Textinput/Textinput.bundle/desktop';
import { Spin } from '../../../Spin/Spin.bundle/desktop';
import { Spacer } from '../../../Spacer/Spacer';
import { UserPic } from '../../../UserPic/UserPic@desktop';
import './index.css';
var c = cn('ComboBox');
var SelectedItemContext = React.createContext(undefined);
var SearchTextContext = React.createContext(undefined);
var Option = function (props) {
return (React.createElement(ListTile, { leading: React.createElement(UserPic, { className: c('Avatar'), lodpiUrl: props.avatar }), leftSpace: "m", alignItems: "center", rightSpace: "m", trailing: React.createElement(Icon, { glyph: "type-check" }) },
React.createElement(Text, { as: "div", typography: "control-xl" }, props.title),
React.createElement(Text, { as: "div", typography: "control-s", color: "secondary" }, props.subtitle)));
};
var Trigger = function (_a) {
var className = _a.className, props = __rest(_a, ["className"]);
var item = React.useContext(SelectedItemContext);
var pressKeys = React.useMemo(function () { return []; }, []);
return (React.createElement(Button, __assign({}, props, { pressKeys: pressKeys, className: className + " " + c('Trigger'), iconRight: props.iconRight }), item ? React.createElement(Option, __assign({}, item)) : '-'));
};
var MenuWithSearch = function (props) {
var _a = React.useContext(SearchTextContext), searchText = _a.searchText, searchInProgress = _a.searchInProgress, onChangeSearchText = _a.onChangeSearchText;
var inputRef = React.useRef(null);
var initialActiveElement = React.useRef(null);
// Фокусируемся на текстовом поле при открытии попапа, возвращаем фокус при закрытии
React.useLayoutEffect(function () {
var input = inputRef.current;
if (props.focused) {
initialActiveElement.current = document.activeElement;
input.focus();
input.setSelectionRange(0, Number.MAX_SAFE_INTEGER);
}
else if (input === document.activeElement && initialActiveElement.current) {
initialActiveElement.current.focus();
}
}, [props.focused]);
return (React.createElement("div", { className: c('MenuWithSearch') },
React.createElement("div", { className: c('Search') },
React.createElement(Textinput, { controlRef: inputRef, view: "default", size: "m", value: searchText, onChange: function (e) { return onChangeSearchText(e.target.value); }, iconRight: searchInProgress ? React.createElement(Spacer, { all: "10px" },
React.createElement(Spin, { view: "default", size: "xxs", progress: true })) : undefined })),
React.createElement(Menu, __assign({}, props))));
};
var registry = new Registry({ id: cnSelect() })
.set('Trigger', Trigger)
.set('Popup', compose(withOutsideClick, withZIndex)(Popup))
.set('Menu', MenuWithSearch)
.set('Icon', Icon);
var CustomSelect = withRegistry(registry)(Select);
export var ComboBox = function (_a) {
var searchText = _a.searchText, searchInProgress = _a.searchInProgress, onChangeSearchText = _a.onChangeSearchText, value = _a.value, items = _a.options, onChange = _a.onChange, props = __rest(_a, ["searchText", "searchInProgress", "onChangeSearchText", "value", "options", "onChange"]);
var options = React.useMemo(function () { return items.map(function (item) { return (__assign(__assign({}, item), { value: item.id, content: (React.createElement(Option, __assign({}, item))) })); }); }, [items]);
var searchTextValue = React.useMemo(function () { return ({
searchText: searchText,
searchInProgress: searchInProgress,
onChangeSearchText: onChangeSearchText,
}); }, [searchText, searchInProgress, onChangeSearchText]);
var handleChange = React.useCallback(function (e) {
onChange(items.find((function (item) { return item.id === e.target.value; })));
}, [onChange, items]);
return (React.createElement(SelectedItemContext.Provider, { value: value },
React.createElement(SearchTextContext.Provider, { value: searchTextValue },
React.createElement(CustomSelect, __assign({ className: c(), view: "default", size: "m", value: value && value.id, onChange: handleChange, options: options }, props)))));
};