import { defineComponent, type Ref, type PropType, ref, computed, } from 'vue' import useClickOutside from '../../composables/use-click-outside' import defineTemplate from './template' import type { SelectSlotParams } from './types' import './styles.scss' export interface DefaultSelectExposed { isActive: boolean } /** * Пользовательский компонент для отображения селекта, соответствующий дизайну. *

* Дизайн *

*/ export const defineDefaultSelect = () => defineComponent({ name: 'DefaultSelect', props: { /** * Опция копирования значения */ isWithCopy: { type: Boolean, default: false, }, /** * Вариант отображения селекта (filter, form) */ appearance: { type: String as PropType<'filter'|'form'>, default: 'filter', }, /** * Пользовательская установка значения **подсветки** \ */ customHighlightSearch: { type: Function as PropType<(value: string) => string>, default: undefined, }, /** * Скрытие поиска */ hideSearch: { type: Boolean, default: true, }, /** * Значение селекта */ modelValue: { type: Object as PropType, default: undefined, }, /** * Название селекта. Располагается над селектом */ title: { type: String, }, /** * Текстовая подсказка в окне селекта при значении undefined в modelValue */ placeholder: { type: String, }, /** * Описание селекта. Располагается под селектом */ description: { type: String, default: '', }, /** * Функция смены значения */ onValueChange: { type: Function as PropType<(value: T|undefined) => void>, required: true, }, /** * Массив объектов для выпадающего списка * Пример: const items = [ { id: '1', name: 'Вариант 1' }, { id: '2', name: 'Вариант 2' } ] */ items: { type: Array as PropType, required: true, }, /** * Функция со слотом кастомных элементов списка */ itemSlot: { type: Function as PropType<(item: T, params: SelectSlotParams) => JSX.Element>, }, /** * Вкл/Выкл возможность очищать выбранное значение */ resetable: { type: Boolean, default: true, }, /** * Размер селекта */ size: { type: String as PropType<'M'|'S'>, }, /** * Флаг, указывающий, отключен ли селект */ disabled: { type: Boolean, default: false, }, /** * Массив ошибок */ errors: { type: [Array, String] as PropType, default: () => [], }, /** * Число отображаемых элементов в раскрытом списке */ showItemsCount: { type: Number, default: 6, }, /** * Отметить как обязательный */ isRequired: { type: Boolean, default: false, }, /** * Флаг, в значении true отображает id каждого элемента */ showDescriptionId: { type: Boolean, default: false, }, }, setup(props, app) { const isOpened = ref(false) const search = ref('') const root = ref(null) as unknown as Ref const select = ref(null) as unknown as Ref const triggerDown = ref(null) as unknown as Ref const triggerUp = ref(null) as unknown as Ref const value = computed(() => props.modelValue as T) const items = computed(() => { let result = props.items if (search.value) { result = props.items.filter(({ name }) => name.toLowerCase().includes(search.value.toLowerCase())) } return result }) useClickOutside(select, () => { isOpened.value = false }) const clear = () => { if (props.onValueChange) props.onValueChange(undefined) } app.expose({ isOpened }) const toggleOpened = () => { isOpened.value = !isOpened.value } const toggleItem = (item: T) => { if (value.value?.id !== item.id && props.onValueChange) { props.onValueChange(item) } toggleOpened() } const isSelected = (item: T) => value.value?.id === item.id const SelectTemplate = defineTemplate() const templateProps = computed(() => ({ clear, close: () => { isOpened.value = false }, isWithCopy: props.isWithCopy, disabled: props.disabled, errors: props.errors, isLoadingNext: false, isLoadingPrev: false, isOpened: isOpened.value, isSelected, items: items.value, itemSlot: props.itemSlot, modelValue: value.value ? [value.value] : [], placeholder: props.placeholder, description: props.description, isRequired: props.isRequired, resetable: props.resetable, root, select, title: props.title, toggleItem, toggleOpened, topItems: [], triggerUp, triggerDown, tableIconType: 'arrow', isSingle: true, appearance: props.appearance, size: props.size, showItemsCount: props.showItemsCount, showDescriptionId: props.showDescriptionId, hideSearch: props.hideSearch, search: search.value, setSearch: (s: string) => { search.value = s }, customHighlightSearch: props.customHighlightSearch?.(search.value), })) return (): JSX.Element => }, }) export default defineDefaultSelect<{id: string, name: string}>()