Multiselect
Базовый мультиселект, в основе текстовое поле. Basic multiselect component, based on a text field.
Import Permalink to "Import"
import ProximaMultiselect from 'proxima-vue/field/multiselect';
Playground Permalink to "Playground"
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const value = ref([]);
const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];
<ProximaMultiselect
label="Select person"
placeholder="Favorite tsar(evna) of Russia"
:options="options"
v-model="value"
/>
Options Permalink to "Options"
В компонент можно передать простой массив строк или объектов c указанием ключа для фильтра, по умолчанию это поле You can pass a simple array of strings or objects to the component, indicating the key for the filter; by default, this is the name
:
value: []
<ProximaMultiselect
label="Select characters"
placeholder="Who is your fav character?"
:options="candidates"
filter-key="fullname"
track-key="fullname"
v-model="value"
/>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const value = ref([]);
const candidates = [
{ fullname: 'Rick Sanchez' },
{ fullname: 'Morty Smith' },
{ fullname: 'Jerry Smith' },
{ fullname: 'Summer Smith' },
{ fullname: 'Beth Smith' },
{ fullname: 'Jessica' },
{ fullname: 'Mr. Goldenfold' },
{ fullname: 'Squanchy' },
{ fullname: 'Birdperson' },
];
Track key Permalink to "Track key"
Для отслеживания используется поле name
, но вы можете указать другой ключ через пропс track‑key
: The name
field is used for tracking, but you can specify a different key via the track‑key
prop:
value: []
<ProximaMultiselect
label="Select person"
placeholder="Favorite Rick"
:options="candidates"
track-key="reality"
v-model="value"
>
<template #option="{ option }">
<span v-text="option.name" />
<span v-text="option.reality" class="text text_dim" />
</template>
</ProximaMultiselect>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const value = ref([]);
const candidates = [
{ name: 'Rick Sanchez', reality: 'C-137' },
{ name: 'Rick Sanchez', reality: 'C-132' },
{ name: 'Rick Sanchez', reality: 'C-123' },
{ name: 'Rick Sanchez', reality: 'C-131' },
];
Max visible Permalink to "Max visible"
По умолчанию отображается 15 вариантов и текстовая подсказка об общем количестве, вы можете изменить это число, а также скрыть подсказку: By default, 15 options are displayed along with a text hint about the total quantity. You can change this number and also hide the count label:
<ProximaMultiselect
:max-visible-options="20"
:has-count-label="false"
/>
Chips Permalink to "Chips"
Компонент может содержать список выбранных элементов в виде чипов/тегов, для активации используйте пропс has‑chips
: The component can contain a list of selected elements in the form of chips/tags; to activate, use the has‑chips
prop:
<ProximaMultiselect
has-chips
/>
Search Permalink to "Search"
В компонент можно передать свою функцию для поиска элемента: You can pass your own function to search for an element:
value: []
<ProximaMultiselect
label="Select coin"
placeholder="Favorite cryptocurrency"
:search-filter="findCoinByNameAndCode"
:options="coins"
v-model="value"
/>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const findCoinByNameAndCode = (option, query) => {
const str = [option.name, option.code].join(' ').toLowerCase();
return str.includes(query.toLowerCase());
};
const value = ref([]);
const coins = [
{ name: 'Tether (TRC-20)', code: 'usdt' },
{ name: 'Bitcoin', code: 'btc' },
{ name: 'Toncoin', code: 'ton' },
{ name: 'Dogecoin', code: 'doge' },
{ name: 'Ethereum', code: 'eth' },
{ name: 'Litecoin', code: 'ltc' },
{ name: 'Dash', code: 'dash' },
{ name: 'Chia', code: 'xch' },
];
Pin Permalink to "Pin"
Вы можете передать функцию фильтр для закрепления определенных вариантов вверху списка: You can pass a filter function to pin certain options to the top of the list:
value: []
<ProximaMultiselect
label="Select person"
placeholder="Favorite tsar(evna) of Russia"
:pin-filter="pinGreatPersons"
:options="options"
v-model="value"
/>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const pinGreatPersons = (name) => name.toLowerCase().includes('great');
const value = ref([]);
const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];
Disable Permalink to "Disable"
Вы можете передать функцию фильтр для блокировки определенных вариантов: You can pass a filter function to disable certain options:
value: []
<ProximaMultiselect
label="Select person"
placeholder="Favorite tsar(evna) of Russia"
:disable-filter="disablePersons"
:options="options"
v-model="value"
/>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const disablePersons = (name) => name.toLowerCase().includes('ivan');
const value = ref([]);
const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];
Create Permalink to "Create"
Попап может содержать кнопку создания нового значения: The field popup may contain a button to create a new value:
cities: []
list: [
"Saint Petersburg",
"Barcelona",
"New York"
]
<ProximaMultiselect
label="The most beautiful city"
placeholder="You can add your city"
:options="list"
has-create-button
@create="createAndSelect"
v-model="cities"
/>
import { ref, unref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const cities = ref([]);
const list = ref(['Saint Petersburg', 'Barcelona', 'New York']);
const createAndSelect = (name) => {
unref(list).push(name);
unref(cities).push(name);
};
Fly search Permalink to "Fly search"
Для активации поиска на лету добавьте mode="fetch"
и используйте функцию useProximaFlySearch
, которая принимает в качестве аргумента метод поиска и возвращает необходимые параметры: To enable on‑the‑fly search, add mode="fetch"
and use the useProximaFlySearch
function, which takes a search method as an argument and returns the necessary parameters:
Анимация загрузки списка требуетList loading animation requires ghost.css
countries: []
<ProximaMultiselect
mode="fetch"
label="Country"
placeholder="Find country ..."
:options="flySearchResults"
:is-list-pending="isFlySearchPending"
@update:filterValue="onFlySearchUpdate"
v-model="countries"
/>
import { ref } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
import useProximaFlySearch from 'proxima-vue/composables/flySearch';
const countries = ref([]);
const findCountry = async (query) => {
const response = await fetch(`https://mocky.yoobe.ru/countries/find?name=${query}`);
const results = await response.json();
return results;
};
const { isFlySearchPending, onFlySearchUpdate, flySearchResults } =
useProximaFlySearch(findCountry);
Accessibility Permalink to "Accessibility"
Поле имеет role="combobox"
и атрибуты aria‑autocomplete="list"
, aria‑haspopup="listbox"
, aria‑multiselectable="true"
, aria‑controls
, aria‑expanded
, вспомогательные технологии обозначают активный элемент списка при навигации с клавиатуры благодаря атрибуту aria‑activedescendant
. The field has role="combobox"
and attributes aria‑autocomplete="list"
, aria‑haspopup="listbox"
, aria‑multiselectable="true"
, aria‑controls
, aria‑expanded
. Assistive technologies indicate the active list item during keyboard navigation with aria‑activedescendant
attribute.
BEM Permalink to "BEM"
Компонент имеет свои модификаторы (создаются автоматически на основе пропсов): The component has its own modifiers (automatically created based on props):
field_multiselect
field_mode_local
field_mode_fetch
field_list_pending
field_popup_opened
CSS Permalink to "CSS"
--field-chips-gap: 0.25rem;
--field-popup-background: var(--field-background);
--field-popup-color: var(--field-color);
--field-popup-overflow-y: auto;
--field-popup-scroll-padding-y-start: 0.25rem;
--field-popup-scroll-padding-y-end: 6rem;
--field-popup-footer-max-width: 24em;
--field-popup-footer-border-size: 1px;
--field-popup-footer-border-color: #eee;
--field-popup-margin-y-start: -0.25rem;
--field-popup-font-size-xxs: 0.75rem;
--field-popup-font-size-xs: 0.8125rem;
--field-popup-font-size-s: 0.875rem;
--field-popup-font-size: 0.875rem;
--field-popup-font-size-m: 0.875rem;
--field-popup-font-size-l: 1rem;
--field-popup-font-size-xl: 1.125rem;
--field-popup-font-size-xxl: 1.25rem;
/*
Options
*/
--field-options-padding-x: 0.25rem;
--field-options-padding-y: 0.25rem;
--field-options-z-index: 1;
--field-option-padding-x: 0.875em;
--field-option-padding-y: 0.75em;
--field-option-gap: 1em;
--field-option-border-radius: 0.375rem;
--field-option-selected-color: var(--field-accent-color);
--field-option-hover-background: #f6f6f6;
--field-option-disabled-opacity: 0.4;
/* Create */
--field-option-create-padding-x: 1.25em;
--field-option-create-color: var(--field-accent-color);
/* Check icon */
--field-option-tick-order: 1;
--field-option-tick-size: 1.125em;
--field-option-tick-stroke-width: 2;
--field-option-tick-margin-x-start: auto;
/* Plus icon */
--field-option-plus-size: 1em;
--field-option-plus-stroke-width: 1.25;
--field-option-plus-margin-x-start: -0.375em;
Locale Permalink to "Locale"
Компонент использует токены локализации, вы можете передать другие токены или обычный текст через пропсы: The component uses localization tokens, and you can pass other tokens or plain text via props:
notfoundLabel
countLabel
createLabel
createDescription
selectedLabel
{
fieldCreateLabel: "Create “{query}”",
fieldCreateDescription: "Press Enter to create and select “{query}”",
fieldNotfoundLabel: "Nothing was found",
fieldFilterCountLabel: "Showing {visibleCount} of {totalCount} items, refine your request to see the rest",
fieldSelectedLabel: "{n} item selected | {n} items selected",
}
Props Permalink to "Props"
interface ProximaMultiselectProps<Option> {
mode?: 'local' | 'fetch'
filterKey?: string
trackKey?: string
modelValue?: Option[]
options?: Option[]
describedby?: string
required?: boolean
minlength?: number
maxlength?: number
maxVisibleOptions?: number
notfoundLabel?: string
countLabel?: string
createLabel?: string
createDescription?: string
selectedLabel?: string
pinFilter?: (option: Option) => boolean
searchFilter?: (option: Option, query: string) => boolean
disableFilter?: (option: Option, modelValue: Option[]) => boolean
selectChecker?: (option: Option, modelValue: Option[]) => boolean
popupProps?: ProximaDynamicProps
hasCreateButton?: boolean
hasCountLabel?: boolean
hasChips?: boolean
isListPending?: boolean
}
Slots Permalink to "Slots"
<ProximaMultiselect>
<template #popup-prepend="slotProps">
you code (prepend to popup)
</template>
<template #popup="slotProps">
you code (append to popup)
</template>
<template #popup-footer="{ id, ...slotProps }">
you code (replaced popup footer)
</template>
<template #option="{ option, ...slotProps }">
you code (replaced popup option)
</template>
</ProximaMultiselect>
type SlotProps = {
maxVisibleOptions: number
filterValue: string
pinnedOptions: Option[]
unpinnedOptions: Option[]
filteredOptions: Option[]
visibleOptions: Option[]
optionIndex: number
notfoundLabel: string
countLabel: string
selectedLabel: string
hasValue: boolean
isNotfoundVisible: boolean
isFilterCountVisible: boolean
isPopupOpened: boolean
isFlySearch: boolean
}
Expose Permalink to "Expose"
Поле поддерживает все методы текстового поля и свои собственные: The field supports all text field methods and some own:
<ProximaMultiselect
ref="multiselect"
:options="options"
v-model="value"
/>
import { ref, unref, onMounted } from 'vue';
import ProximaMultiselect from 'proxima-vue/field/multiselect';
const multiselect = ref({} as InstanceType<typeof ProximaMultiselect>);
const value = ref([]);
const options = ['Bitcoin', 'Toncoin', 'Dogecoin'];
onMounted(() => {
unref(multiselect).checkOptionSelected('Bitcoin'); // false
unref(multiselect).pickOption('Bitcoin');
unref(multiselect).checkOptionSelected('Bitcoin'); // true
});
type ProximaMultiselectInstance = {
checkOptionPinned: (option: any) => boolean
checkOptionSelected: (option: any) => boolean
checkOptionDisabled: (option: any) => boolean
pickOption: (option: any) => void
pickOptionByIndex: () => void
scrollToOption: () => void
setOptionIndex: (number) => void
setPrevIndex: () => void
setNextIndex: () => void
setFirstIndex: () => void
setFilterValue: (value: string) => void
showPopup: () => void
hidePopup: () => void
}
Extends Permalink to "Extends"
Данный компонент основан на текстовом поле и поддерживает его пропсы, события, слоты, БЭМ модификаторы и кастомные свойства. This component is based on a text field and supports its props, events, slots, BEM modifiers and custom properties.