import { computed, defineComponent, type PropType, ref, type Ref, } from 'vue' import useClickOutside from '../../composables/use-click-outside' import defineTemplate from './template' import type { AllCheckState, SelectSlotParams } from './types' import './styles.scss' export interface DefaultSelectMultipleExposed { isOpened: boolean } export const defineMultipleDefaultSelect = () => defineComponent({ props: { /** * Функционал 'Выбрать все' */ canCheckAll: { type: Boolean, default: false, }, /** * Пользовательская установка значения **подсветки** \ */ customHighlightSearch: { type: Function as PropType<(value: string) => string>, default: undefined, }, modelValue: { type: Array as PropType, default: () => ([]), }, title: { type: String, }, placeholder: { type: String, }, /** * Скрытие поиска */ hideSearch: { type: Boolean, default: true, }, onValueChange: { type: Function as PropType<(value: T[]) => void>, required: true, }, items: { type: Array as PropType, required: true, }, itemSlot: { type: Function as PropType<(item: T, params: SelectSlotParams) => JSX.Element>, }, disabled: { type: Boolean, default: false, }, resetable: { type: Boolean, default: true, }, errors: { type: Array as PropType, default: () => [], }, size: { type: String as PropType<'M'|'S'>, }, showItemsCount: { type: Number, default: 6, }, 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 topItems: Ref = ref([]) const items = computed(() => { let result = props.items if (search.value) { result = props.items.filter(({ name }) => name.toLowerCase().includes(search.value.toLowerCase())) } return result }) topItems.value = [...props.modelValue] const isSelected = (item: T) => Boolean(props.modelValue.find((i) => i.id === item.id)) const allCheckState = computed(() => { if (!props.canCheckAll) return undefined if (props.modelValue.length) { if (items.value.length === props.modelValue.length) { return true } return 'multiple' } return false }) const toggleAll = () => { if (allCheckState.value === undefined) return props.onValueChange(allCheckState.value === 'multiple' || !allCheckState.value ? items.value : []) } const toggleItem = (item: T) => { if (isSelected(item)) { const i = props.modelValue.find((i) => i.id === item.id) if (!i) return const newValue = [...props.modelValue] newValue.splice(newValue.indexOf(i), 1) if (props.onValueChange) props.onValueChange(newValue) } else if (props.onValueChange) props.onValueChange([...props.modelValue, item]) } useClickOutside(select, () => { isOpened.value = false topItems.value = [...props.modelValue] }) const clear = () => { if (props.onValueChange) props.onValueChange([]) } app.expose({ isOpened }) const toggleOpened = () => { isOpened.value = !isOpened.value topItems.value = [...props.modelValue] } const SelectTemplate = defineTemplate() return (): JSX.Element => { const templateProps = { allCheckState: allCheckState.value, clear, disabled: props.disabled, errors: props.errors, isLoadingNext: false, isLoadingPrev: false, isOpened: isOpened.value, isSelected, items: items.value, itemSlot: props.itemSlot, modelValue: props.modelValue, placeholder: props.placeholder, resetable: props.resetable, root, select, title: props.title, toggleAll, toggleItem, toggleOpened, topItems: topItems.value, triggerUp, triggerDown, tableIconType: 'arrow', isSingle: false, 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 } }, }) export default defineMultipleDefaultSelect<{id: string, name: string}>()