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 = () => (