Select

import { Select } from '@megafon/ui-core';
Код DemoSelectWrapper
const DemoSelectWrapper = props => {
const [currentValue, setCurrentValue] = React.useState();
const handleSelect = (_e, data) => {
if (!data) {
setCurrentValue('');
return;
}
setCurrentValue(data.value);
};
return (
<div style={DemoSelectWrapperStyle}>
{props.children({
onSelect: handleSelect,
currentValue: currentValue,
})}
</div>
);
};
Демо данные
const items = [
{
value: 0,
title: 'Авиамоторная',
},
{
value: 1,
title: 'Автозаводская',
},
{
value: 2,
title: 'Академическая',
},
{
value: 3,
title: 'Бабушкинская',
},
{
value: 4,
title: 'Багратионовская',
},
{
value: 5,
title: 'ВДНХ',
},
{
value: 6,
title: 'Варшавская',
},
{
value: 7,
title: 'Деловой центр',
},
{
value: 8,
title: 'Дмитровская',
},
{
value: 9,
title: 'Калужская',
},
{
value: 10,
title: 'Кантемировская',
view: ({ filterValue = '' }) => {
const query = filterValue.replace(/[^A-Z-a-zА-ЯЁа-яё0-9]/g, w => '\\' + w);
const stringFragments = 'Кантемировская'.split(RegExp(`(${query})`, 'ig'));
return (
<>
{stringFragments.map((fragment, i) => (
<React.Fragment key={i}>
{fragment.toLowerCase() === filterValue.toLowerCase() && fragment !== '' ? (
<b>{fragment}</b>
) : (
fragment
)}
</React.Fragment>
))}
</>
);
},
},
];

Базовое использование

Показать код
<DemoSelectWrapper>
      {({ onSelect, currentValue }) => (
          <Select
              label="Заголовок"
              onSelect={onSelect}
              placeholder="Choose your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>

С коротким списком элементов

Показать код
<DemoSelectWrapper>
      {({ onSelect, currentValue }) => (
          <Select
              shortList
              label="Заголовок"
              onSelect={onSelect}
              placeholder="Choose your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>

С кастомным отображением элементов

Показать код
<DemoSelectWrapper>
      {({ onSelect, canOpen, currentValue }) => (
          <Select
              label="Заголовок"
              placeholder="Choose your step"
              items={items.map(item => ({
                  title: item.title,
                  value: item.value,
                  paddings: 'small',
                  view: (
                      <>
                          <Metro style={{ width: '24px', minWidth: '24px', height: '24px', marginRight: '16px' }} />
                          {item.title}
                      </>
                  ),
                  selectedView: (
                      <>
                          <Metro style={{ width: '24px', minWidth: '24px', height: '24px', marginRight: '16px' }} />
                          {item.title}
                      </>
                  ),
              }))}
              onSelect={onSelect}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>

Выключенное состояние

Показать код
<DemoSelectWrapper>
      {() => (
          <Select
              label="Заголовок"
              disabled
              items={items}
          />
      )}
  </DemoSelectWrapper>
  <DemoSelectWrapper>
      {() => (
          <Select
              label="Заголовок"
              disabled
              items={items}
              currentValue={0}
          />
      )}
  </DemoSelectWrapper>

Валидация

Показать код
<DemoSelectWrapper>
      {({ onSelect, currentValue = 3 }) => (
          <Select
              label="Успешное состояние"
              required
              verification="valid"
              noticeText="Success message"
              onSelect={onSelect}
              placeholder="Choose your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>
  <DemoSelectWrapper>
      {({ onSelect, currentValue }) => (
          <Select
              label="Состояние ошибки"
              required
              verification="error"
              noticeText="Error message"
              onSelect={onSelect}
              placeholder="Choose your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>

Тип сombobox

Показать код
<DemoSelectWrapper>
      {({ onSelect, currentValue }) => (
          <Select
              label="Сombobox"
              type="combobox"
              onSelect={onSelect}
              placeholder="Choose or type your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>
  <DemoSelectWrapper>
      {({ onSelect, currentValue = 6 }) => (
          <Select
              label="Combobox с выбранным по умолчанию значением"
              type="combobox"
              onSelect={onSelect}
              placeholder="Choose or type your step"
              items={items}
              currentValue={currentValue}
          />
      )}
  </DemoSelectWrapper>

Дополнительный контент в шапке выпадающего списка

Функция renderHeaderContent добавляет кастомный блок над списком элементов.

Показать код
<DemoSelectWithHeader>
      {({ onSelect, currentValue, currentClients, onButtonClick }) => (
          <Select
              label="Выберите клиента"
              currentValue={currentValue}
              items={currentClients}
              onSelect={onSelect}
              renderHeaderContent={({ onClose }) => (
                  <div style={{ borderBottom: '1px solid var(--spbSky1)', paddingBlock: '12px', marginBottom: '8px' }}>
                      <button type="button" style={{ color: 'var(--systemBlue)' }} onClick={onButtonClick(onClose)}>
                          Добавить клиента
                      </button>
                  </div>
              )}
          />
      )}
  </DemoSelectWithHeader>
  <DemoSelectWithHeader>
      {({ onSelect, currentValue, currentClients, onButtonClick }) => (
          <Select
              type="combobox"
              label="Выберите клиента"
              placeholder="Введите имя"
              currentValue={currentValue}
              items={currentClients}
              onSelect={onSelect}
              renderHeaderContent={({ items, searchValue, selectedValue, onClose }) => {
                  const selectedItem = items.find(item => item.value === selectedValue)?.title;

                  return (
                      <div style={{ borderBottom: '1px solid var(--spbSky1)', marginBottom: '8px' }}>
                          {searchValue && searchValue !== selectedItem ? (
                              <Button type="text" onClick={onButtonClick(onClose, searchValue )}>
                                  Добавить {searchValue}
                              </Button>
                          ) : (
                              <Paragraph color="gray">Для добавления нового клиента введите имя</Paragraph>
                          )}
                      </div>
                  );
              }}
          />
      )}
  </DemoSelectWithHeader>
Код DemoSelectWithHeader
type ClientType = {
value: string;
title: string;
};
export const DemoSelectWithHeader = ({ children }) => {
const [currentClients, setCurrentClients] = React.useState<ClientType[]>([]);
const [currentValue, setCurrentValue] = React.useState<string>('');
const handleSelect = (
_e: React.SyntheticEvent<EventTarget> | React.KeyboardEvent<HTMLDivElement>,
data: ISelectItem<string>,
) => {
setCurrentValue(data?.value ?? '');
};
const handleButtonClick = (onClose?: () => void, title?: string) => () => {
const newClient = {
value: generateClientId(),
title: title ?? generateClientName(),
};
setCurrentClients([newClient, ...currentClients]);
setCurrentValue(newClient.value);
onClose?.();
};
return (
<div style={selectWrapperStyle}>
{children({
currentValue,
currentClients,
onSelect: handleSelect,
onButtonClick: handleButtonClick,
})}
</div>
);
};
Prop nameTypeDefaultDescription
typeSelectTypesType | undefinedclassicТип компонента
labelstring | undefinedЗаголовок поля
labelIdstring | undefinedHTML идентификатор для заголовка поля
currentValueSelectItemValueTypeТекущий выбранный элемент селекта (extends SelectItemValueType)
verificationVerificationType | undefinedРезультат проверки данных
noticeTextstring | Element | undefinedДополнительный текст под полем. Свойство verification влияет на цвет текста.
disabledboolean | undefinedfalseОтключение селекта
requiredboolean | undefinedfalseДелает поле обязательным
placeholderstring | undefinedТекст внутри поля по умолчанию
notFoundTextstring | undefinedНичего не нашлосьТекст при отсутствии результатов поиска
items*ISelectItem<T>[]Массив элементов селекта
shortListboolean | undefinedfalseОтображать короткий выпадающий список
classNamestring | undefinedДополнительный класс корневого элемента
classes{ root?: string | undefined; control?: string | undefined; title?: string | undefined; titleInner?: string | undefined; list?: string | undefined; listInner?: string | undefined; listItem?: string | undefined; listItemTitle?: string | undefined; } | undefined{}Дополнительные классы для внутренних элементов
dataAttrs{ root?: Record<string, string> | undefined; label?: Record<string, string> | undefined; control?: Record<string, string> | undefined; title?: Record<string, string> | undefined; ... 7 more ...; notFound?: Record<...> | undefined; } | undefinedДополнительные data атрибуты к внутренним элементам
inputRef((node: HTMLDivElement) => void) | undefinedRef обработчик
onSelect((e: MouseEvent<Element, MouseEvent> | KeyboardEvent<Element> | null, dataItem?: ISelectItem<T> | undefined) => void) | undefinedОбработчик выбора элемента селекта
onOpened(() => void) | undefinedОбработчик при открытом селекте
onClosed(() => void) | undefinedОбработчик при закрытом селекте
renderHeaderContent((props: { items: ISelectItem<T>[]; selectedValue?: T | undefined; searchValue?: string | undefined; onClose: () => void; }) => ReactNode) | undefinedФункция рендера контента в шапке выпадающего списка