Конфликты с другими библиотеками

Механизм работы библиотеки основан на перехвате событий ввода (input, keydown, paste) и динамическом преобразовании значения поля. Такое поведение неизбежно пересекается с другими слоями логики приложения: фреймворками, менеджерами состояния, библиотеками форм и сторонними input-mask решениями. Основные конфликты возникают не на уровне самой маскировки, а на уровне конкуренции за контроль над значением поля и курсором.


Конфликты с фреймворками (React, Vue, Angular)

React: контролируемые компоненты и потеря синхронизации

В React основная проблема возникает при использовании контролируемых компонентов, где value полностью управляется состоянием.

Ключевая конфликтная ситуация:

  • Cleave.js изменяет DOM напрямую
  • React перезаписывает значение из state
  • происходит «перетягивание каната» между DOM и Virtual DOM

Типичный симптом:

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

Причина заключается в том, что Cleave.js модифицирует input.value вне React-цикла, а React при следующем рендере возвращает «старое» состояние.

Особенно критично это проявляется при:

  • обновлении state на каждый onChange
  • использовании strict mode
  • асинхронных обновлениях состояния

Vue: реактивность и watcher-циклы

Во Vue конфликт возникает через двустороннюю реактивность:

  • Cleave.js форматирует значение
  • v-model тут же реагирует на изменение
  • watcher снова форматирует или перезаписывает значение

Возникает цикл:

  1. ввод символа
  2. Cleave форматирует
  3. Vue обновляет модель
  4. модель перерисовывает input
  5. Cleave повторно применяет формат

Результат:

  • двойное форматирование
  • потеря символов
  • нестабильный курсор

Особенно проблемно при использовании кастомных директив, где Cleave и v-model работают одновременно.


Angular: formControl и паттерн ControlValueAccessor

В Angular основной конфликт связан с FormControl:

  • Cleave.js изменяет DOM напрямую
  • Angular ожидает обновления через ControlValueAccessor
  • происходит рассинхронизация модели и view

Симптомы:

  • dirty/touched состояния обновляются некорректно
  • valueChanges срабатывает с уже отформатированным значением
  • возможны бесконечные циклы при setValue

Конфликты с библиотеками форм

React Hook Form

Основная проблема — различие между uncontrolled и controlled подходом.

  • RHF предпочитает uncontrolled inputs
  • Cleave.js изменяет DOM value

Конфликтные сценарии:

  • register() + Cleave одновременно
  • watch() пересоздаёт значение
  • reset() теряет форматирование

Частая ошибка — попытка использовать Cleave как обычный input без адаптера, что приводит к:

  • потере фокуса
  • повторной инициализации маски
  • конфликту refs

Formik

Formik полностью контролирует state формы, поэтому Cleave начинает конкурировать за источник истины.

Проблема:

  • Formik хранит «чистое» значение
  • Cleave отображает «форматированное»
  • при каждом onChange происходит нормализация

Результат:

  • значение в UI и state расходятся
  • submit отдаёт не тот формат, который виден пользователю

Конфликты с другими масками ввода

Использование нескольких библиотек маскирования одновременно — один из самых нестабильных сценариев.

Типичный конфликт:

  • Cleave.js
  • Inputmask / IMask / custom formatter

Проблема: каждая библиотека перехватывает input и пытается:

  • изменить value
  • управлять курсором
  • форматировать строку

В результате:

  • символы «дёргаются»
  • ввод блокируется
  • курсор постоянно сбрасывается

Ключевая причина — отсутствие единого ownership над input value.


Конфликты с IME (Input Method Editors)

Наиболее сложный класс конфликтов связан с азиатскими раскладками (IME: китайский, японский, корейский ввод).

Cleave.js не всегда корректно обрабатывает события composition:

  • compositionstart
  • compositionupdate
  • compositionend

Проблема: во время композиции вводимые символы не являются финальными, но Cleave может:

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

Симптомы:

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

Корректная интеграция требует полного игнорирования форматирования во время composition-сессии, но это часто реализовано частично или несовместимо с другими слоями логики.


Конфликты с обработчиками событий

Перехват input и сторонние listeners

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

  • auto-save на input
  • validation pipeline
  • analytics tracking

то Cleave.js становится «посредником», который изменяет значение до того, как его увидят другие обработчики.

Проблемы:

  • аналитика получает уже форматированные данные
  • валидация работает с изменённым значением
  • debounce логика дублирует события

Paste-события

При вставке данных возникает гонка:

  1. пользователь вставляет значение
  2. Cleave перехватывает paste
  3. браузер вставляет raw value
  4. Cleave форматирует
  5. сторонний handler снова читает raw

Результат:

  • двойная обработка
  • потеря символов
  • некорректное форматирование длинных строк

Конфликты с управлением курсором

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

Cleave.js пересчитывает cursor position после каждого форматирования.

Конфликты возникают, когда:

  • внешний код также изменяет selectionStart/selectionEnd
  • используется React/Vue rerender
  • происходит debounce input

Типичные проблемы:

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

Конфликты с SSR (Server-Side Rendering)

При SSR возникает проблема гидратации:

  • сервер отдаёт «чистое» значение
  • клиент инициализирует Cleave.js и форматирует его
  • React/Vue сравнивает DOM и state

Результат:

  • hydration mismatch warnings
  • мгновенная перерисовка input
  • визуальный «флэш» изменения значения

Конфликты при повторной инициализации

Частая ошибка архитектуры — многократное создание экземпляра Cleave на одном input.

Сценарии:

  • повторный mount компонента
  • hot reload в dev-режиме
  • условный render

Если старый экземпляр не уничтожен:

  • остаются event listeners
  • дублируется форматирование
  • input обрабатывается несколькими инстансами одновременно

Симптомы:

  • двойные разделители (например, 12--34)
  • некорректный ввод при быстром наборе
  • утечки памяти через listeners

Конфликты с валидацией и схемами данных

При использовании schema-based validation (Yup, Zod, Joi) возникает расхождение форматов:

  • UI показывает форматированное значение
  • схема ожидает «сырое» значение

Cleave.js усложняет разделение этих слоёв.

Типичная ошибка:

  • валидация запускается на formatted value
  • регулярные выражения перестают совпадать
  • сервер получает невалидный формат

Конфликты с debounce/throttle логикой

При использовании debounce:

  • Cleave генерирует много промежуточных изменений
  • debounce агрегирует их
  • форматирование пересекается с задержкой

Проблемы:

  • задержка отображения
  • «откат» значения после debounce flush
  • расхождение между UI и state

Конфликты с мобильными клавиатурами

На мобильных устройствах ввод дополнительно усложняется автокоррекцией и предиктивным вводом.

Сценарии:

  • автоисправление изменяет строку после Cleave formatting
  • клавиатура вставляет символы пакетно
  • Cleave обрабатывает частично обновлённое значение

Результат:

  • неожиданные вставки символов
  • скачки курсора
  • невозможность ввести форматированные числа без ошибок

Архитектурная природа конфликтов

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

  • Cleave.js берёт на себя управление представлением значения
  • современные фреймворки и form libraries требуют единого источника истины

Любое пересечение этих двух моделей неизбежно создаёт конкуренцию за:

  • значение input
  • событие изменения
  • позицию курсора
  • момент форматирования