import { type Moment } from 'moment' import { defineComponent, type PropType, ref, type Ref, type ComputedRef, computed, Teleport, } from 'vue' import Calendar from '../calendars/calendar' import useClickOutside from '../../../composables/use-click-outside' import { copyTooltip } from '../../../helpers' import './calendar-input.sass' /** * Компонент представляет собой ввод даты (с календарем). * Обладает различными настраиваемыми свойствами: возможность отключения, очистки, отображения текста и пр. *

* Дизайн *

*/ export default defineComponent({ props: { /** * Отключен ли ввод. */ isDisabled: { type: Boolean, default: false, }, /** * Можно ли очистить значение поля ввода. * Добавляет кнопку "крестик". */ isClearable: { type: Boolean, default: false, }, /** * Отображается ли лейбл (название) над инпутом. */ isShowLabel: { type: Boolean, default: true, }, /** * Определяет, используется ли компонент внутри таблицы. */ isForTable: { type: Boolean, default: false, }, /** * Опция копирования значения */ isWithCopy: { type: Boolean, default: false, }, /** * Использовать `vue`шный `Teleport` для показа попапа календаря */ isUseTeleport: { type: Boolean, default: false, }, /** * Название поля, расположено над инпутом. */ label: { type: String, default: '', }, /** * Значение, отображаемое в поле ввода, если оно пусто. */ placeholder: { type: String, default: '__.__.____', }, /** * Массив строк с ошибками. */ errors: { type: Array as PropType, default: () => [], }, /** * Строка, представляющая формат даты. */ format: { type: String, default: 'DD.MM.YYYY', }, /** * Значение поля ввода. */ modelValue: { type: [Object, null] as PropType, required: true, }, /** * Определяет, является ли поле обязательным для заполнения. */ isRequired: { type: Boolean, default: false, }, /** * Описание поля ввода. Отображается под инпутом. */ description: { type: String, default: '', }, /** * Функция обратного вызова при изменении значения. */ onValueChange: { type: Function as PropType<(v: Moment | null) => void>, required: true, }, }, setup(props) { const isShowCalendar: Ref = ref(false) const formattedValue: ComputedRef = computed(() => props.modelValue?.format(props.format) ?? '') const popupStyle = ref({}) const calendarElement: Ref = ref(null) const inputElement: Ref = ref(null) const setDate = (val: Moment | null) => { if (props.onValueChange) { props.onValueChange(val) } } const copy = (event: MouseEvent) => { if (!props.isWithCopy) return copyTooltip(formattedValue.value, event.clientX + 10, event.clientY - 30) } const onClick = (event: MouseEvent) => { copy(event) if (props.isDisabled && !isShowCalendar.value) return isShowCalendar.value = !isShowCalendar.value if (props.isUseTeleport && inputElement.value) { const rect = inputElement.value.getBoundingClientRect() popupStyle.value = { top: `${rect.bottom + window.scrollY}px`, left: `${rect.left + window.scrollX}px`, } } } useClickOutside(calendarElement, () => { isShowCalendar.value = false }) const renderPopupElement = () => (
{ props.isForTable && (
{ props.modelValue && (
setDate(null)} class="ark-ui-calendar-input-calendar-container-clear" /> ) }
) }
) return () => (
{ props.label && props.isShowLabel && (
{ props.label }{ props.isRequired ? '*' : '' }
) } { !props.isDisabled && (
) }
{ props.isForTable && (
{ props.placeholder }
) } { !props.isForTable && ( ) } { props.isClearable && props.modelValue ?
setDate(null)} class='ark-ui-calendar-input-icon ark-ui-calendar-input-icon-clear' /> :
}
{ !props.isDisabled && props.errors && props.errors.length > 0 ? props.errors.map((error) =>
{error}
) : props.description ?
{props.description}
: '' } { isShowCalendar.value && (<> {props.isUseTeleport ? ( {renderPopupElement()} ) : renderPopupElement()} ) }
) }, })