Breaking changes

Одним из ключевых направлений развития Flatpickr стало постепенное изменение подхода к инициализации и управлению экземпляром календаря. Ранние версии библиотеки допускали более «свободную» интеграцию через глобальный объект, тогда как современные подходы ориентированы на модульность и явное создание экземпляра.

В старых интеграциях использовался прямой вызов через глобальный namespace:

flatpickr("#input", {});

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

const instance = flatpickr("#input", {
  enableTime: true
});

При этом важно учитывать, что возврат экземпляра стал критически важным элементом API. Ранее многие разработчики игнорировали его, но с ростом сложности приложений это привело к проблемам при повторной инициализации и управлении жизненным циклом.

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


Переход к модульной структуре и сборке

Одним из наиболее значимых breaking changes стал переход к модульной архитектуре и поддержке современных сборщиков (Webpack, Vite, Rollup).

Ранее Flatpickr часто подключался как единый UMD-бандл:

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

Современный подход предполагает ES-модули:

import flatpickr from "flatpickr";
import "flatpickr/dist/flatpickr.css";

Это изменение повлияло на:

  • способ подключения локализаций;
  • загрузку плагинов;
  • работу tree-shaking;
  • структуру сборки CSS.

Особенно критичным стало разделение локалей:

import { Russian } from "flatpickr/dist/l10n/ru.js";

flatpickr("#input", {
  locale: Russian
});

Ранее локализация могла подключаться глобально, что приводило к неявным зависимостям.


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

Flatpickr исторически стремился оставаться независимым от внешних библиотек дат. Однако внутренние изменения логики обработки дат приводили к breaking changes в следующих областях:

Строгая нормализация входных значений

Ранее библиотека более «прощала» некорректные входные строки. Например:

  • частично валидные даты могли интерпретироваться по-разному;
  • строки без явного формата иногда парсились в зависимости от браузера.

В новых версиях логика стала более строгой:

  • предпочтение отдаётся явно заданному dateFormat;
  • неоднозначные строки чаще приводят к Invalid Date;
  • уменьшена зависимость от поведения Date.parse.

Изменения в dateFormat

Форматирование стало более детерминированным. Некоторые старые паттерны интерпретации были пересмотрены:

  • строгая поддержка токенов Y, m, d;
  • усиленная изоляция от локали при парсинге;
  • более предсказуемое поведение при round-trip (input → output → input).

Пример:

flatpickr("#input", {
  dateFormat: "Y-m-d"
});

Ранее некоторые вариации вроде y-m-d могли вести к неоднозначным результатам.


Изменения в событиях и их сигнатурах

Существенные breaking changes затронули event hooks. Основная проблема старых версий заключалась в нестабильности аргументов и их порядка.

onChange

Ранее обработчик мог получать разные наборы аргументов в зависимости от режима:

onChange: function(selectedDates, dateStr, instance) {}

В более новых версиях поведение стабилизировано, но важно учитывать:

  • selectedDates всегда массив;
  • dateStr всегда соответствует dateFormat;
  • instance всегда является последним аргументом.

Изменение, которое часто ломает старый код, связано с тем, что разработчики ранее полагались на неявные дополнительные параметры.


onOpen и onClose

Ранее некоторые версии могли передавать контекст через this, что считалось устаревшей практикой. Современная реализация полностью исключает зависимость от this, делая API функционально-ориентированным.

onOpen: (selectedDates, dateStr, instance) => {
  instance.calendarContainer.classList.add("opened");
}

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

Механизм altInput претерпел несколько несовместимых изменений, связанных с синхронизацией основного и альтернативного input.

Ранее поведение

  • возможна десинхронизация при ручном изменении DOM;
  • события могли дублироваться;
  • обновление значения не всегда триггерило rerender.

Новое поведение

  • строгая синхронизация между altInput и исходным input;
  • единая точка обновления состояния;
  • предотвращение рекурсивных событий.
flatpickr("#input", {
  altInput: true,
  altFormat: "F j, Y"
});

Критическое изменение: прямое изменение altInput.value перестало считаться валидным способом обновления состояния.


Изменения в плагинах и расширениях

Flatpickr поддерживает плагины, однако их модель подключения претерпела значительные изменения.

Ранее

Плагины могли подключаться как побочные эффекты:

flatpickr("#input", {
  plugins: [somePlugin()]
});

Иногда плагины модифицировали внутренние структуры напрямую, что приводило к хрупкости системы.

Сейчас

Плагины стали более изолированными:

  • ограниченный доступ к внутренним методам;
  • формализованный lifecycle;
  • контроль точек расширения.

Это привело к несовместимости со старыми кастомными плагинами, которые использовали приватные свойства экземпляра.


Изменения в destroy и повторной инициализации

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

Старое поведение

instance.destroy();
  • не всегда очищались event listeners;
  • DOM-изменения могли оставаться;
  • повторная инициализация приводила к дубликатам.

Новое поведение

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

Однако это привело к breaking change: код, который полагался на сохранение модифицированного DOM после destroy, перестал работать.


Изменения в локализации (i18n)

Локализация стала строго модульной и явной.

Ранее

flatpickr.localize(flatpickr.l10ns.ru);

или подключение через глобальный объект.

Сейчас

import { Russian } from "flatpickr/dist/l10n/ru.js";

flatpickr("#input", {
  locale: Russian
});

Breaking change заключается в отказе от глобального состояния локали. Это повлияло на:

  • динамическую смену языков;
  • SSR-рендеринг;
  • изоляцию компонентов.

Изменения в поведении minDate и maxDate

Логика ограничений дат была уточнена.

Старые версии

  • допускали строковые значения без строгого парсинга;
  • могли интерпретировать даты относительно локали браузера;
  • иногда приводили к смещению диапазона на день из-за timezone.

Новая модель

  • строгая нормализация через внутренний парсер Flatpickr;
  • единое поведение для всех окружений;
  • устранение timezone-дрейфа в большинстве сценариев.
flatpickr("#input", {
  minDate: "2026-01-01",
  maxDate: "2026-12-31"
});

Изменения в мобильном поведении

Flatpickr исторически отключал собственный UI на мобильных устройствах, отдавая управление нативным input.

Breaking changes затронули:

  • детекцию мобильных браузеров;
  • поведение disableMobile;
  • отображение календаря в hybrid режимах.

Ранее

  • нестабильное определение устройств;
  • различия между iOS Safari и Android Chrome;
  • непредсказуемое переключение UI.

Сейчас

  • унифицированная стратегия определения окружения;
  • более явное управление через disableMobile: true|false;
  • уменьшение скрытой логики.

Изменения в кастомных форматтерах и парсерах

Ранее разработчики могли переопределять внутренние методы форматирования:

  • formatDate
  • parseDate

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

  • доступ ограничен;
  • рекомендуется использовать hooks и внешние утилиты;
  • внутренние реализации считаются приватными.

Breaking change: прямое переопределение функций перестало гарантировать корректную работу всех режимов (особенно time + range + multiple).


Изменения в совместимости с TypeScript

Добавление TypeScript-типов привело к уточнению контрактов API:

  • строгая типизация Date[] вместо гибких массивов;
  • фиксированные интерфейсы options;
  • запрет на неизвестные поля без расширений.

Это сломало часть старых проектов, где использовались кастомные опции без типового расширения.


Изменения в поведении range mode и multiple mode

Режимы выбора дат получили более строгую логику.

Range mode

Ранее:

  • допускалась частичная инициализация диапазона;
  • возможны были «разорванные» состояния.

Сейчас:

  • диапазон всегда нормализуется;
  • начало и конец строго контролируются;
  • автоматическая корректировка порядка дат.

Multiple mode

  • устранены дубликаты;
  • улучшена сортировка выбранных дат;
  • строгая уникальность значений.

Изменения в внутренних CSS-классах

Breaking changes затронули и DOM-структуру:

  • некоторые классы переименованы;
  • изменена иерархия контейнеров;
  • добавлены новые обёртки для accessibility.

Пример влияния:

  • старые селекторы .flatpickr-calendar.open могли перестать работать;
  • кастомные темы требуют обновления.

Изменения в доступности (a11y)

Обновления привели к:

  • добавлению ARIA-атрибутов;
  • улучшенной навигации с клавиатуры;
  • изменению структуры фокуса.

Breaking change: кастомные модификации DOM могли нарушать фокус-менеджмент, так как теперь он строго контролируется библиотекой.