Перейти к содержимому
Поиск
Разработка

Vanilla Calendar Pro: календарь выбора даты с примерами

Бесплатная мастерская Vanilla Calendar Pro без регистрации: обычный выбор даты, период, несколько дней, дата со временем и готовые сценарии. Настройте язык, ограничения и оформление, проверьте результат в браузере и скачайте исходный проект. Разбираем подключение к HTML, React и Vue, неполный диапазон, недоступные дни и часовые пояса.

Александр Некрасов

Выбор даты нужен в заявке на консультацию, фильтре отчёта, форме бронирования и расписании. В одном случае достаточно одного дня, в другом нужен период, а в третьем — дата вместе со временем. Vanilla Calendar Pro позволяет собрать эти варианты на одном компоненте и использовать его в обычной HTML-странице, React, Vue или другом интерфейсе.

Ниже работает бесплатная мастерская календаря без регистрации: переключайте примеры, выбирайте даты, меняйте ограничения и оформление, затем забирайте код и исходный проект. Настройки и выбор обрабатываются в браузере. Это демонстрация компонента; реальные заявки, запись клиентов и серверное бронирование здесь не создаются.

Дата, которую удобно выбрать

Соберите календарь для своего интерфейса

Попробуйте выбор даты, диапазона или времени. Настройте язык, оформление и ограничения, затем заберите код своего примера.

Бесплатно
Без регистрации
Повторите в своём проекте

Исходники мастерской, зафиксированная версия библиотеки, инструкции сборки и лицензии — в архиве.

Скачать пример проекта

Календарь — Vanilla Calendar Pro, Юрий Уваров и участники проекта. Мастерская и пояснения — ae-nekrasov.ru. Настройки и выбранные даты обрабатываются в браузере.

Что такое Vanilla Calendar Pro и где он пригодится

Vanilla Calendar Pro — компонент выбора даты и времени на TypeScript без зависимости от конкретного фреймворка. Он управляет собственными DOM-элементами, а ваше приложение получает выбранные значения через обработчики. Библиотека распространяется по лицензии MIT; уведомления об авторстве и лицензии следует сохранять при распространении её кода.

Для простой формы сначала рассмотрите стандартный <input type="date">. Кастомный календарь полезен, когда требуется единый внешний вид, несколько выбранных дат, диапазон, ограничения доступности или календарь прямо внутри страницы. В таком случае компонент помогает организовать выбор, а правила конкретного сервиса вы задаёте сами.

В мастерской и примерах зафиксирована версия 3.4.0. В ней дополнительные возможности подключаются расширениями: например, время — через time, несколько месяцев — через months. Это особенно важно при переносе примеров из старых публикаций. Изменения и переход на 3.4.0.

Как пользоваться мастерской на этой странице

В верхней части панели есть семь сценариев: «Одна дата», «Диапазон», «Несколько дат», «Дата и время», «Поле формы», «Рабочие дни» и «Два месяца». Начните с подходящего примера, затем измените язык, начало недели и тему. Результат выбора находится рядом с календарём: так удобно проверять, какие данные получит ваше приложение.

Ограничения добавляйте по одному. Например, сначала задайте минимальную дату, затем исключите выходные и одну конкретную дату. Проверьте как доступный день, так и заблокированный. Для диапазона посмотрите, что происходит до выбора второй границы и при попытке пройти через недоступные дни.

После настройки скопируйте пример подключения. Исходный проект пригодится для самостоятельного запуска и дальнейших изменений. Экспорт настроек помогает сохранить выбранный вариант; он не создаёт расписание сотрудников и не синхронизирует доступность с другим календарём.

Первый пример: русский календарь и выбранная дата

Следующий пример рассчитан на проект с TypeScript и сборщиком, например Vite. Установите закреплённую версию пакета:

npm install vanilla-calendar-pro@3.4.0

Добавьте контейнер и место для результата в HTML:

<div id="appointment-calendar"></div>
<p id="appointment-date" aria-live="polite">Дата не выбрана</p>

В модуле TypeScript подключите календарь и основные стили:

import { Calendar } from "vanilla-calendar-pro";
import "vanilla-calendar-pro/styles/core.css";

const output = document.querySelector("#appointment-date");
if (!(output instanceof HTMLElement)) {
  throw new Error("Не найден элемент для результата");
}

const calendar = new Calendar("#appointment-calendar", {
  locale: "ru",
  firstWeekday: 1,
  selectionDatesMode: "single",
  onClickDate(self) {
    output.textContent = self.context.selectedDates[0]
      ?? "Дата не выбрана";
  },
});
calendar.init();

locale: "ru" задаёт русские названия, а firstWeekday: 1 начинает неделю с понедельника. Значение в обработчике берётся из self.context.selectedDates. Даже при выборе одного дня библиотека возвращает массив: пустой результат нужно учитывать. Подключите этот модуль после появления контейнеров в документе. Официальное описание локализации.

Диапазон и несколько отдельных дат — разные задачи

Период подходит для отчёта «с 12 по 18 число». Несколько отдельных дат — для занятий по выбранным дням, например 12, 15 и 18 числа. Не подменяйте одно другим: три занятия не должны превращаться в непрерывную неделю.

Для периода создайте контейнер <div id="report-calendar"></div> и календарь с режимом multiple-ranged. Здесь добавлено ограничение на учебный месяц:

import { Calendar } from "vanilla-calendar-pro";
import "vanilla-calendar-pro/styles/core.css";

const reportCalendar = new Calendar("#report-calendar", {
  locale: "ru",
  firstWeekday: 1,
  selectionDatesMode: "multiple-ranged",
  enableEdgeDatesOnly: true,
  enableDateToggle: false,
  dateMin: "2026-11-01",
  dateMax: "2026-11-30",
});
reportCalendar.init();

Для отдельных дней используйте режим multiple. В приведённом примере enableEdgeDatesOnly: true оставляет в context.selectedDates только границы периода. Пустой массив означает отсутствие выбора, одна дата — ожидание конца, две — обе выбранные границы. Настройка enableDateToggle: false позволяет вторым нажатием на тот же день получить однодневный период с двумя одинаковыми границами. Показывайте подсказку «выберите конец периода» до завершения и не считайте продолжительность по длине массива.

Заранее решите, включается ли конечная дата. В отчёте период обычно включает оба дня. В бронировании дата выезда может не считаться занятой ночью. Подпись около результата должна объяснять именно правило вашего сервиса.

Дата и время: пример записи на встречу

Для выбора времени в ESM-проекте нужны расширение time, его регистрация и стили. Пример ниже использует контейнер <div id="meeting-calendar"></div> и результат <p id="meeting-result" aria-live="polite"></p>.

import { Calendar, time } from "vanilla-calendar-pro";
import "vanilla-calendar-pro/styles/core.css";
import "vanilla-calendar-pro/styles/time.css";

const result = document.querySelector("#meeting-result");
if (!(result instanceof HTMLElement)) {
  throw new Error("Не найден результат встречи");
}

function showMeeting(self: Calendar, isError = false) {
  const output = result;
  if (!(output instanceof HTMLElement)) return;
  if (isError) {
    output.textContent = "Проверьте введённое время";
    return;
  }
  const date = self.context.selectedDates[0];
  output.textContent = date
    ? `${date} · ${self.context.selectedTime}`
    : "Выберите дату встречи";
}

const meetingCalendar = new Calendar("#meeting-calendar", {
  extensions: [time],
  locale: "ru",
  firstWeekday: 1,
  selectionDatesMode: "single",
  selectionTimeMode: 24,
  selectedTime: "10:00",
  timeStepMinute: 15,
  onInit(self) { showMeeting(self); },
  onClickDate(self) { showMeeting(self); },
  onChangeTime(self, _event, isError) {
    showMeeting(self, isError);
  },
});
meetingCalendar.init();

Шаг минут делает управление удобнее, но бизнес-правило «запись только каждые 15 минут» проверяйте отдельно, включая ручной ввод. Свободные часы для выбранного дня должны поступать из вашей системы записи. Сам календарь не знает о перерывах, занятости специалиста и параллельных заявках. Подключение времени, обработчики изменения.

Недоступные дни, границы и проверка заявки

Настройки dateMin и dateMax ограничивают даты выбора. disableWeekdays: [0, 6] исключает воскресенье и субботу; disableDates: ["2026-11-04"] блокирует отдельный день. Это иллюстративные ограничения, а не готовый производственный календарь праздников.

Для непрерывного периода проверяйте все включённые дни, а не только начало и конец. Например, свободные понедельник и пятница не означают, что между ними доступна среда. Если ваши правила запрещают такой период, покажите причину возле результата и не разрешайте отправку до исправления.

Окончательную проверку выполняет сервер при отправке заявки: допустимость дат, время, часовой пояс и актуальная доступность. Между открытием формы и отправкой другой человек мог занять тот же слот. Интерфейс должен сохранить введённые данные, объяснить конфликт и предложить новый выбор. Ограничения отдельных дней.

Календарная дата, время и часовой пояс

Строка 2026-11-12 — календарный день. Для отчёта её обычно достаточно хранить как дату без часового пояса. Значение 10:00 — время на часах; само по себе оно не определяет момент встречи. Для записи укажите, например, «10:00, время Москвы», а в данных сохраните выбранную дату, время и зону Europe/Moscow.

Не превращайте дату без времени в UTC-метку просто ради форматирования: new Date("2026-11-12") трактует такую строку как UTC, и вывод в другой зоне может показать предыдущий день. Для календарных дат используйте подход, который сохраняет день; для реального момента встречи выполняйте осмысленное преобразование с известной зоной. Различие строк даты и даты со временем у MDN.

Подключение к React, Vue и жизненному циклу страницы

В обычной странице создайте экземпляр после появления контейнера. В React используйте DOM-ссылку и создавайте календарь внутри эффекта, а при очистке эффекта вызывайте calendar.destroy(). В Vue создавайте его в onMounted и удаляйте в onBeforeUnmount. Фреймворк управляет внешним контейнером, библиотека — его содержимым.

Не создавайте новый экземпляр при каждом рендере компонента. Для изменения настроек есть set() и update(); при обновлении учитывайте, нужно ли сохранять уже выбранные пользователем значения. Расширения регистрируются при создании и не добавляются через последующее изменение настроек. Если экземпляр больше не нужен, destroy() завершает его работу. Методы экземпляра, пример интеграции с Vue.

В приложении с серверным рендерингом запускайте DOM-календарь на клиенте. Выбранные значения передавайте в состояние приложения через обработчики; не считывайте их из случайных элементов отрисованной сетки.

Тема, мобильная версия и понятное управление

Выбирайте тему под реальный фон формы и проверяйте контраст выбранных, доступных и заблокированных дней. Не различайте состояния только цветом: подпись результата и доступные названия элементов помогают понять выбор. Размер текста и кнопок должен оставаться удобным на телефоне.

Два месяца рядом удобны для длинного периода, но на узком экране лучше показать один месяц или расположить их вертикально. Для нескольких месяцев в 3.4.0 подключается расширение months и его стили; режим задаётся параметрами type: "multiple" и displayMonthsCount: 2. Проверьте переход между месяцами, выбор с клавиатуры и возврат фокуса после закрытия календаря у поля.

Один язык календарной сетки не переводит все подсказки вашего приложения. Подписи полей, сообщения о неполном периоде, ошибки и обозначение часового пояса оформляйте согласованно.

Что проверить перед использованием в своём проекте

Пройдите обычный сценарий и граничные случаи: пустой выбор, один день, смена месяца и года, неполный период, недоступный день внутри диапазона, ручное изменение времени и сброс. Затем повторите работу на телефоне и клавиатурой. Пользователь должен понимать текущий результат и причину запрета без чтения документации библиотеки.

Сохраните версии зависимостей в проекте и lock-файл, а обновление сначала проверяйте отдельно. В скачиваемом примере есть рабочая основа мастерской и инструкция запуска. Настройте форму под собственные правила, соедините её с серверной проверкой и только после этого используйте для настоящей записи. Официальная документация Vanilla Calendar Pro поможет расширить календарь дополнительными возможностями.