DatetimePicker 
DatetimePicker компонент для вводу дати та часу
Звичайний вибір дати 
Ви можете вибрати довільну дату (за замовчуванням пікер працює в режимі календаря з вибором дня місяця)
<template>
  <AppDateTimePicker v-model="model" placeholder="Виберіть дату" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script><template>
  <AppDateTimePicker v-model="model" placeholder="Виберіть дату" />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
};
</script>Вибір дати та часу 
Передавши атрибут type='datetime', ви переведете пікер в режим, коли можна вибрати дату і час
<template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    placeholder="Виберіть дату"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    placeholder="Виберіть дату"
  />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
};
</script>selectingadaterange 
При передачі атрибута type=‘daterange’ або type='datetimerange' пікер перейде в режим вибору діапазону дат або дати і часу
<template>
  <AppDateTimePicker
    v-model="dateRange"
    type="daterange"
    start-placeholder="Початкова дата"
    end-placeholder="Кінцева дата"
  />
  <AppDateTimePicker
    v-model="dateTimeRange"
    type="datetimerange"
    start-placeholder="Початкова дата"
    end-placeholder="Кінцева дата"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const dateRange = ref(null);
const dateTimeRange = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="dateRange"
    type="daterange"
    start-placeholder="Початкова дата"
    end-placeholder="Кінцева дата"
  />
  <AppDateTimePicker
    v-model="dateTimeRange"
    type="datetimerange"
    start-placeholder="Початкова дата"
    end-placeholder="Кінцева дата"
  />
</template>
<script>
export default {
  data() {
    return {
      dateRange: null,
      dateTimeRange: null,
    };
  },
};
</script>Режими ^0.1.0
Ви можете налаштувати потрібний вам режим календаря
- day- початкове відображення календаря: дні місяця (також можна вибрати місяць або рік)
- month- початкове відображення календаря: місяці року (також є можливість вибору року)
- year- початок відображення календаря: роки десятиліття
ІНФОРМАЦІЯ
Зверніть увагу, що значення, яке буде передано назад, буде датою, а не числом
 Щоб коректно відобразити значення у інпуті, передайте відповідний формат за допомогою атрибута 
 date-format
<template>
  <AppDateTimePicker
    v-model="month"
    mode="month"
    date-format="MM"
    placeholder="Оберіть місяць"
  />
  <AppDateTimePicker
    v-model="yearRange"
    date-format="yyyy"
    type="daterange"
    start-placeholder="Початковий рік"
    end-placeholder="Кінцевий рік"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const month = ref(null);
const yearRange = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="month"
    mode="month"
    date-format="MM"
    placeholder="Оберіть місяць"
  />
  <AppDateTimePicker
    v-model="yearRange"
    date-format="yyyy"
    type="daterange"
    start-placeholder="Початковий рік"
    end-placeholder="Кінцевий рік"
  />
</template>
<script>
export default {
  data() {
    return {
      month: null,
      yearRange: null,
    };
  },
};
</script>Ярлики для швидкого доступу 
Ви можете налаштувати ярлики для швидкого вибору дати
<template>
  <AppDateTimePicker
    v-model="model"
    :shortcuts="shortcuts"
    placeholder="Виберіть дату"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
const shortcuts = [
  {
    text: 'Сьогодні',
    value: new Date(),
  },
  {
    text: 'Наступний понеділок',
    value: (() => {
      const today = new Date();
      const nextMonday = new Date(
        today.setDate(today.getDate() + ((8 - today.getDay()) % 7 || 7))
      );
      return nextMonday;
    })(),
  },
  {
    text: 'Наступного тижня',
    value: new Date(new Date().setDate(new Date().getDate() + 7)),
  },
];
</script><template>
  <AppDateTimePicker
    v-model="model"
    :shortcuts="shortcuts"
    placeholder="Виберіть дату"
  />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
  computed: {
    shortcuts: [
      {
        text: 'Сьогодні',
        value: new Date(),
      },
      {
        text: 'Наступний понеділок',
        value: (() => {
          const today = new Date();
          const nextMonday = new Date(
            today.setDate(today.getDate() + ((8 - today.getDay()) % 7 || 7))
          );
          return nextMonday;
        })(),
      },
      {
        text: 'Наступного тижня',
        value: new Date(new Date().setDate(new Date().getDate() + 7)),
      },
    ],
  },
};
</script>Час за замовчуванням 
Ви можете налаштувати, який час буде підставлятися за замовчуванням
<template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    default-time="15:00:00"
    placeholder="Виберіть дату"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    default-time="15:00:00"
    placeholder="Виберіть дату"
  />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
};
</script>Часовий пояс 
Атрибут timezone використовується для корекції часу в пікері
ПОПЕРЕДЖЕННЯ
Об'єкт Date завжди залишається в локальному часовому поясі
Коли вибрано дату, компонент атоматично обчислює різницю між локальним часовим поясом користувача і часовим поясом, зазначеним у timezone, і додає або віднімає її від часу вибраної дати для остаточного відображення.
Те ж саме відбувається, коли користувач вперше вибирає дату, тільки в цьому випадку дата повертається, приведена до місцевого часу користувача
ІНФОРМАЦІЯ
Обраний часовий пояс: America/New_York
Ваш місцевий час: Sat Apr 26 2025 16:22:41 GMT+0000 (Coordinated Universal Time)
<template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    timezone="America/New_York"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    timezone="America/New_York"
  />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
};
</script>Формати 
ПІДКАЗКА
Щоб дізнатися більше про доступні формати, перейдіть за цим посиланням
У цьому компоненті ви можете налаштувати формат дати, яка буде відображатися у вхідних даних.
date-format атрибут відповідає за формат, який буде відображено в головному інпуті
time-format атрибут відповідає за формат, який буде відображатися при виборі часу у інпуті який знаходиться в поповері
Використання атрибуту combine-formats (за замовчуванням - true) можна визначити, чи потрібно поєднувати формат date-format & time-format для основного кроку (використовується, коли збирач працює в часовому типі)
Приклад, коли атрибут має негативне значення:
<template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    date-format="yyyy-MM-dd"
    time-format="HH-mm-ss"
    placeholder="yyyy-MM-dd HH-mm-ss"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const model = ref(null);
</script><template>
  <AppDateTimePicker
    v-model="model"
    type="datetime"
    date-format="yyyy-MM-dd"
    time-format="HH-mm-ss"
    placeholder="yyyy-MM-dd HH-mm-ss"
  />
</template>
<script>
export default {
  data() {
    return {
      model: null,
    };
  },
};
</script>Заблокована дата 
Для того, щоб заблокувати дату для вибору в пікері або при введенні, потрібно передати в атрибут disabled-date функцію, яка перевіряє, чи заблокована дата
Блокувати дату, яка менша за поточну:
Діапазон доступних дат (2 дні до і 2 дні після поточної дати):
<template>
  <p>Блокувати дату, яка менша за поточну:</p>
  <AppDateTimePicker
    v-model="modelOne"
    :disabled-date="isDateDisabledBeforeToday"
    placeholder="Виберіть дату"
  />
  <p>Діапазон доступних дат (2 дні до і 2 дні після поточної дати):</p>
  <AppDateTimePicker
    v-model="modelTwo"
    :disabled-date="isDateNotInRange"
    placeholder="Виберіть дату"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const modelOne = ref(null);
const modelTwo = ref(null);
function isDateDisabledBeforeToday(date: Date) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return date < today;
}
function isDateNotInRange(date: Date) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const twoDaysBefore = new Date(today);
  twoDaysBefore.setDate(today.getDate() - 2);
  const twoDaysAfter = new Date(today);
  twoDaysAfter.setDate(today.getDate() + 2);
  return date <= twoDaysBefore || date >= twoDaysAfter;
}
</script><template>
  <p>Блокувати дату, яка менша за поточну:</p>
  <AppDateTimePicker
    v-model="modelOne"
    :disabled-date="isDateDisabledBeforeToday"
    placeholder="Виберіть дату"
  />
  <p>Діапазон доступних дат (2 дні до і 2 дні після поточної дати):</p>
  <AppDateTimePicker
    v-model="modelTwo"
    :disabled-date="isDateNotInRange"
    placeholder="Виберіть дату"
  />
</template>
<script>
export default {
  data() {
    return {
      modelOne: null,
      modelTwo: null,
    };
  },
  methods: {
    isDateDisabledBeforeToday(date) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      return date < today;
    },
    isDateNotInRange(date) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      const twoDaysBefore = new Date(today);
      twoDaysBefore.setDate(today.getDate() - 2);
      const twoDaysAfter = new Date(today);
      twoDaysAfter.setDate(today.getDate() + 2);
      return date <= twoDaysBefore || date >= twoDaysAfter;
    },
  },
};
</script>API 
Атрибути 
| Назва | Опис | Тип | За замовчуванням | 
|---|---|---|---|
| v-model / model-value | значення прив'язки, якщо це масив, то довжина повинна бути 2 | null/Date/object | null | 
| date-format | призначений для відображення дати в інпуті у певному форматі.більше | string | yyyy/MM/dd | 
| time-format | призначений для відображення дати в інпуті у певному форматі, який знаходиться в поповері при режимах більше datetime,datetimerange) | string | HH:mm:ss | 
| combine-formats | згенерувати формат для пікера на основі пропсів  date-format&time-format | boolean | true | 
| type | який тип пікера слід відображати | string | date | 
| mode^0.1.0 | в якому режимі ви хочете відображати календар.більше | string | day | 
| first-day-of-week | порядок днів тижня в денному календарі | number | 1 | 
| weekday-format | формат днів тижня в денному календарі | string | short | 
| month-cell-format | формат місяців у календарі | string | short | 
| month-button-format | формат місяця в кнопці яка знаходиться у верхній панелі календаря | string | long | 
| shortcuts | список ярликів для швидкого вибору дати.більше | object | [] | 
| default-time | час, який буде встановлено за замовчуванням. Очікуваний формат - «00:00:00».більше | string/object | " | 
| locale | мова, якою ви хочете відображати дані в пікері (Використовуйте тільки якщо у вас немає пакета  vue-i18n) | string | en | 
| time-options | налаштування пікера часу | string | {} | 
| disabled-date | визначення заблокованих дат | Function | — | 
| hide-offset-day^0.3.0 | приховати дні іншого місяця в календарі | false | false | 
| auto-apply^0.2.0 | застосування змін без натискання кнопки "Застосувати" | boolean | false | 
| disabled | чи заблокований пікер | boolean | false | 
| readonly | чи пікер доступний тільки для читання | boolean | false | 
| input-readonly^0.0.2 | перевести інпут в режим read-only, але через поповер є можливість обирати дату | boolean | false | 
| clearable | відображення контролера для очищення входу даних, коли він переповнений | boolean | false | 
| timezone | який часовий пояс буде використовуватися для корекції дати.більше | string | " | 
| placeholder | заповнювач, який буде відображатися в інпуті, коли пікер працює в одиночному режимі | string | " | 
| start-placeholder | заповнювач, який буде відображено у першому інпуті, коли пікер працює у режимі діапазону | string | " | 
| end-placeholder | заповнювач, який буде відображено у останньому інпуті, коли пікер працює у режимі діапазону | string | " | 
| align | положення поповера | string | left | 
| start-id^0.2.0 | id для першого нативного інпута (також використовується для нативного інпута, якщо він лише один) | string | " | 
| end-id^0.2.0 | id для останнього нативного інпута | string | " | 
| start-name^0.2.0 | атрибут name для першого нативного інпута (також використовується для нативного інпута, якщо він лише один) | string | " | 
| end-name^0.2.0 | атрибут name для останнього нативного інпута | string | " | 
| apply-text | текст, що відображається в кнопці застосувати у поповері | string | "Apply" | 
| cancel-text | текст, що відображається в кнопці скасування у поповері | string | "Cancel" | 
| invalid | пікер має невірне значення | boolean | false | 
| z-index^0.3.0 | z-index для вмісту поповера | number | 1000 | 
| client-only-popover-content^0.3.0 | Відображати вміст поповеру всередині  | boolean | false | 
| open-delay | затримка в мілісекундах перед відкриттям поповера | number | 0 | 
| close-delay | затримка в мілісекундах перед закриттям поповера | number | 150 | 
| append-to-body |  визначає, чи слід додавати вміст спливаючого вікна до  bodyзамість того, щоб вкладати його в структуру DOM компонента. | boolean | true | 
| stay-opened | залишайте пікап відкритим після відкриття. Використовуйте його для налагодження або дослідження поповера | boolean | false | 
Події 
| Назва | Опис | Тип | 
|---|---|---|
| change | спрацьовує при зміні значення | Function | 
| focus | спрацьовує, коли пікер знаходиться в фокусі | Function | 
| blur | спрацьовує, коли пікер перестає бути в фокусі | Function | 
Слоти 
| Назва | Опис | 
|---|---|
| default | кастомне посилання для поповера | 
| separator | кастомний вміст роздільника діапазону | 
Default слот ^0.0.2
Цей слот замінює поле введення дати. Нижче наведено таблицю з доступними пропсами для цього слоту
| Назва | Опис | Тип | 
|---|---|---|
| value | Значення, яке передається в поле введення (без форматування) | null/Date/object | 
| popoverVisible | повертає, чи відкритий поповер в даний момент чи ні | boolean | 
| input | встановлення нового значення в пікері | Function | 
| blur | прибрати фокус з пікера | Function | 
| focus | виконати фокус на пікер | Function | 
<template>
  <AppDateTimePicker v-model="model">
    <template #default="{ value, popoverVisible, input, focus }">
      <input
        :value="dateToStringDate(value)"
        :class="{ 'custom-input--focus': popoverVisible }"
        class="custom-input"
        placeholder="Виберіть дату"
        @focus="focus"
        @input="event => stringDateToDate(event, input)"
      />
    </template>
  </AppDateTimePicker>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { format, isDate, parse } from 'date-fns';
const model = ref(null);
const dateFormat = 'yyyy-MM-dd';
function dateToStringDate(value: Date | null) {
  if (!value || !isDate(value)) return '';
  return format(value, dateFormat);
}
function stringDateToDate(event: InputEvent, cb: (value: unknown) => void) {
  const value = (event.target as HTMLInputElement).value;
  const parsed = parse(value, dateFormat, new Date());
  if (!value) {
    cb(null);
  }
  if (value.length === dateFormat.length && isDate(parsed)) {
    cb(parsed);
  }
}
</script>
<style lang="scss" scoped>
.custom-input {
  width: 100%;
  border: 1px solid;
  &:focus,
  &--focus {
    border-color: blue;
  }
}
</style><template>
  <AppDateTimePicker v-model="model">
    <template #default="{ value, popoverVisible, input, focus }">
      <input
        :value="dateToStringDate(value)"
        :class="{ 'custom-input--focus': popoverVisible }"
        class="custom-input"
        placeholder="Виберіть дату"
        @focus="focus"
        @input="event => stringDateToDate(event, input)"
      />
    </template>
  </AppDateTimePicker>
</template>
<script>
export default {
  data() {
    return {
      model: null,
      dateFormat: 'yyyy-MM-dd',
    };
  },
  methods: {
    dateToStringDate(value) {
      if (!value || !isDate(value)) return '';
      return format(value, this.dateFormat);
    },
    stringDateToDate(event, cb) {
      const value = event.target.value;
      const parsed = parse(value, this.dateFormat, new Date());
      if (!value) {
        cb(null);
      }
      if (value.length === this.dateFormat.length && isDate(parsed)) {
        cb(parsed);
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.custom-input {
  width: 100%;
  border: 1px solid;
  &:focus,
  &--focus {
    border-color: blue;
  }
}
</style>Доступні властивості компонента 
| Назва | Опис | Тип | 
|---|---|---|
| popoverVisible | повертає, чи відкрито спливаюче вікно в даний момент чи ні | object | 
| focus | виконати фокус на пікер | Function | 
| blur | прибрати фокус з пікера | Function |