import { defineComponent, type Ref, ref, type PropType, watch, computed, } from 'vue' import ARKCheckbox from '../checkbox/ARKCheckbox.vue' import LineLoader from '../line-loader/ARKLineLoader.vue' import { copyTooltip, highlight } from '../../helpers' import type { AllCheckState, SelectSlotParams } from './types' const highlightText = (text: string, search?: string) => { if (!search) return text return highlight(text, search, '$&') } export const DEFAULT_SHOW_ITEMS_COUNT = 6 export default function defineTemplate() { return defineComponent({ name: 'SelectTemplate', props: { allCheckState: { type: [String, Boolean] as PropType, default: undefined, }, clear: { type: Function as PropType<() => void>, required: true, }, customHighlightSearch: { type: String, default: undefined, }, disabled: { type: Boolean, required: true, }, errors: { type: [Array, String] as PropType, required: true, }, /** * Опция копирования значения * Копирует только самое первое значение, это значит * что для мультиселектов всегда будет копироваться первое значение */ isWithCopy: { type: Boolean, default: false, }, isLoadingNext: { type: Boolean, required: true, }, isLoadingPrev: { type: Boolean, required: true, }, isOpened: { type: Boolean, required: true, }, isSelected: { type: Function as PropType<(i: T) => boolean>, required: true, }, items: { type: Array as PropType, required: true, }, itemSlot: { type: Function as PropType<(item: T, params: SelectSlotParams) => JSX.Element>, }, leftSlot: { type: Function as PropType<(item: T[]) => JSX.Element>, default: undefined, }, modelValue: { type: Array as PropType, required: true, }, placeholder: { type: String, }, resetable: { type: Boolean, required: true, }, root: { type: Object as PropType>, required: true, }, search: { type: String, }, setSearch: { type: Function as PropType<(s: string) => void>, }, select: { type: Object as PropType>, required: true, }, size: { type: String as PropType<'M'|'S'>, }, title: { type: String, }, toggleAll: { type: Function as PropType<() => void>, default: undefined, }, toggleItem: { type: Function as PropType<(i: T) => void>, required: true, }, toggleOpened: { type: Function as PropType<() => void>, required: true, }, topItems: { type: Array as PropType, required: true, }, triggerDown: { type: Object as PropType>, required: true, }, triggerUp: { type: Object as PropType>, required: true, }, tableIconType: { type: String, }, isSingle: { type: Boolean, required: true, }, appearance: { type: String as PropType<'filter'|'form'>, default: 'filter', }, additionalItems: { type: Array as PropType, }, showItemsCount: { type: Number, default: DEFAULT_SHOW_ITEMS_COUNT, }, description: { type: String, default: '', }, isRequired: { type: Boolean, default: false, }, hideSearch: { type: Boolean, default: false, }, showDescriptionId: { type: Boolean, required: true, }, }, setup(props) { return () => { const tableIconType = props.tableIconType || 'search' const isFormAppearance = props.isSingle && props.appearance === 'form' const setSelector = () => `ark-ui-select ${props.size || 'M'} ${props.isOpened ? 'is-opened' : ''} ${props.disabled ? 'is-disabled' : ''} ${props.isWithCopy ? 'with-copy' : ''} ${props.errors.length ? 'with-errors' : ''} ${props.modelValue.length > 0 && isFormAppearance && props.resetable ? 'selected-resetable' : ''}` const toggleOpened = () => { if (props.disabled) return props.toggleOpened() } const copy = (event: MouseEvent) => { if (!props.isWithCopy) return copyTooltip(props.modelValue[0]?.name, event.clientX + 10, event.clientY - 30) } const isFocus: Ref = ref(null) const inputSearchFocus = () => { if (isFocus.value) { isFocus.value.focus() } } watch(() => props.modelValue, (value) => { if (!value.length && !props.isOpened && props.setSearch) props.setSearch('') }) const render = (item: T) => { if (props.itemSlot) { return props.itemSlot(item, { isSelected: props.isSelected, toggleItem: props.toggleItem, }) } return (
{ e.stopPropagation(); props.toggleItem(item) }} > { !props.isSingle && ({})}/> }
{props.showDescriptionId && item.id}
) } const isEmpty = computed( () => !props.isLoadingNext && !props.isLoadingPrev && ![props.items, props.topItems, props.additionalItems] .some((item) => item?.length), ) return (
{ props.title &&
{ props.title }{ props.isRequired ? '*' : '' }
}
{ props.modelValue.length > 0 && !isFormAppearance && (
{ props.modelValue.length }
{ !props.disabled &&
{ e.stopPropagation(); props.clear() }}/> }
) } { props.placeholder && !(isFormAppearance && props.modelValue.length > 0) && !(props.modelValue.length > 0 && props.title) && (
{ props.placeholder }
) } { isFormAppearance && props.isSingle && props.modelValue.length > 0 && [ props.leftSlot?.(props.modelValue),
{ props.modelValue[0].name }
, props.resetable && !props.disabled &&
, ] }
{ props.resetable && props.modelValue.length > 0 &&
} { !props.disabled &&
}
{ props.search !== undefined && !props.hideSearch && ( ) }
{ props.isLoadingPrev && }
{ props.allCheckState !== undefined && (
{ e.stopPropagation(); props.toggleAll?.() }} > ({})} />
Выбрать все
) } { !props.isSingle && props.topItems.map((item) => render(item)) } { props.additionalItems && props.additionalItems.filter((item) => props.isSingle || !props.topItems.find((i) => i.id === item.id)).map((item) => render(item)) } { props.items.filter((item) => props.isSingle || !props.topItems.find((i) => i.id === item.id)).map((item) => render(item)) }
{ props.isLoadingNext && }
По вашему запросу ничего не найдено
{ !props.disabled && ( <> { typeof props.errors === 'string' && props.errors.length > 0 ?
{ props.errors }
: Array.isArray(props.errors) && props.errors.length > 0 ? props.errors.map((error) =>
{ error }
) : props.description ?
{ props.description }
: '' } ) }
) } }, }) }