Миграция с предыдущих версий

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

Ключевой проблемой при обновлении становится не сам API, а его поведение в деталях: обработка null-значений, различия в парсинге строк дат, изменения в интеграции с Moment.js и способы подключения библиотеки в современных сборщиках.


Изменения в способе подключения библиотеки

Ранние версии Pikaday ориентировались на глобальный объект и подключение через <script>:

<script src="pikaday.js"></script>

Инициализация выглядела следующим образом:

var picker = new Pikaday({
    field: document.getElementById('date')
});

В современных версиях, ориентированных на bundler’ы, предпочтительным становится импорт:

import Pikaday from 'pikaday';

const picker = new Pikaday({
    field: document.getElementById('date')
});

При миграции важно учитывать:

  • переход на ESM-сборку
  • необходимость явного подключения CSS
  • отсутствие автоматического глобального объекта в модульной среде

Подключение стилей и изменения CSS

В старых проектах CSS часто подключался вручную:

<link rel="stylesheet" href="pikaday.css">

В современных сборках стили необходимо импортировать явно:

import 'pikaday/css/pikaday.css';

или из альтернативного пути в зависимости от сборщика.

При миграции важно проверить:

  • наличие дублирующихся стилей
  • конфликты с reset/normalize
  • переопределение классов .pika-*

Изменения структуры DOM календаря в разных версиях могут приводить к тому, что кастомные стили перестают работать корректно, особенно если они были завязаны на вложенность элементов.


Изменения в работе с датами

Уход от неявного парсинга строк

Ранние версии Pikaday допускали передачу строковых значений:

new Pikaday({
    field: input,
    defaultDate: '2020-01-01',
    setDefaultDate: true
});

В новых версиях поведение стало более строгим: предпочтение отдается объекту Date.

Корректный вариант:

new Pikaday({
    field: input,
    defaultDate: new Date(2020, 0, 1),
    setDefaultDate: true
});

Миграция требует пересмотра всех мест, где дата передавалась строкой без явного парсинга.


Изменения в интеграции с Moment.js

Ранее Pikaday мог использовать Moment.js для форматирования и парсинга:

new Pikaday({
    field: input,
    format: 'DD.MM.YYYY',
    onSelect: function(date) {
        console.log(this.getMoment().format('DD.MM.YYYY'));
    }
});

В новых версиях Moment.js перестал быть обязательной зависимостью. Это означает:

  • getMoment() может отсутствовать
  • форматирование должно выполняться вручную или через альтернативные библиотеки
  • интеграция через toString() и parse() стала предпочтительной

Пример замены:

new Pikaday({
    field: input,
    toString: function(date) {
        return date.toLocaleDateString('ru-RU');
    },
    parse: function(str) {
        const [day, month, year] = str.split('.');
        return new Date(year, month - 1, day);
    }
});

Изменения в API опций

defaultDate и setDefaultDate

Поведение этих параметров стало более предсказуемым:

  • defaultDate больше не применяется к input автоматически без setDefaultDate
  • setDefaultDate теперь явно управляет синхронизацией поля

Миграционный паттерн:

Было:

new Pikaday({
    field: input,
    defaultDate: new Date(2020, 0, 1)
});

Стало:

new Pikaday({
    field: input,
    defaultDate: new Date(2020, 0, 1),
    setDefaultDate: true
});

format и кастомное форматирование

Опция format перестала быть универсальной точкой контроля. В новых версиях рекомендуется использовать:

  • toString(date)
  • parse(dateString)

Это влияет на миграцию:

new Pikaday({
    field: input,
    toString: date => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`,
    parse: str => new Date(str)
});

bound и контейнерное поведение

В старых версиях поведение привязки к полю (bound: true) иногда приводило к неконсистентному позиционированию.

В новых версиях:

  • позиционирование стало более стабильным
  • учитываются getBoundingClientRect
  • добавлена лучшая поддержка scroll-контейнеров

При миграции стоит перепроверить:

  • fixed/absolute контейнеры
  • модальные окна
  • вложенные scroll-области

Изменения событийной модели

Основные события:

  • onSelect
  • onOpen
  • onClose
  • onDraw

Они остались, но поведение контекста this стало более строго определенным.

Ранее:

onSelect: function() {
    console.log(this.getDate());
}

Теперь рекомендуется явно использовать переданные значения:

onSelect: function(date) {
    console.log(date);
}

Особенно важно учитывать, что:

  • this может не гарантировать доступ ко всем методам
  • события становятся более функциональными по стилю

Изменения в методах экземпляра

getDate / setDate

Поведение стало более предсказуемым:

picker.setDate(new Date(), true);

Второй параметр (trigger) теперь критичен для синхронизации событий.

При миграции важно проверить:

  • не вызываются ли события повторно
  • не происходит ли двойная установка значения input

destroy

В новых версиях уничтожение экземпляра стало более «чистым»:

picker.destroy();

При миграции следует учитывать:

  • необходимость ручного удаления обработчиков
  • очистку ссылок в SPA (React/Vue/Angular)

Изменения в позиционировании и рендеринге

В старых версиях календарь иногда «прыгал» при скролле.

В новых версиях:

  • улучшена привязка к window.scroll
  • переработан расчет координат
  • исправлены баги с fixed-элементами

Однако миграция может выявить:

  • несовместимость с кастомными overflow-контейнерами
  • проблемы при transform: scale у родителей

Изменения в модульной архитектуре

CommonJS → ESM

Ранее:

const Pikaday = require('pikaday');

Теперь:

import Pikaday from 'pikaday';

В проектах с Webpack/Vite это влияет на:

  • tree-shaking
  • размер бандла
  • необходимость настройки transpile для node_modules

Типичные проблемы при миграции

1. Некорректный формат даты

Симптомы:

  • пустой input
  • NaN в логах
  • неправильный месяц

Причина:

  • передача строк вместо Date

2. Потеря Moment.js методов

Симптомы:

  • getMoment is not a function

Причина:

  • удаление зависимости Moment.js

3. Сломанная верстка календаря

Симптомы:

  • элементы смещены
  • календарь выходит за пределы контейнера

Причина:

  • кастомные CSS, завязанные на старую DOM-структуру

4. Двойные события

Симптомы:

  • дважды вызывается onSelect

Причина:

  • неправильное использование второго параметра setDate

Рекомендуемый порядок миграции

  1. Обновление пакета Pikaday
  2. Замена CommonJS на ESM импорт
  3. Проверка всех мест с передачей строк дат
  4. Удаление зависимости от Moment.js (если использовалась)
  5. Переписывание format → toString/parse
  6. Проверка CSS и позиционирования
  7. Тестирование событийной модели
  8. Проверка destroy в SPA

Совместимость старых конфигураций

Некоторые опции продолжают работать, но считаются устаревшими:

  • format (частично устаревшая концепция)
  • неявный парсинг строк
  • reliance на Moment.js

При сохранении старого поведения требуется явная эмуляция через toString и parse, иначе логика календаря может измениться незаметно.