Цепочка обработки данных

В основе работы Floating UI лежит концепция цепочек обработчиков (middleware chain), которые последовательно модифицируют позиционирование всплывающих элементов. Цепочка позволяет гибко управлять смещением (offset), адаптацией под границы видимой области (flip, shift) и другими аспектами поведения всплывающих элементов.

Каждый обработчик в цепочке получает объект с текущим состоянием позиции, выполняет необходимые вычисления и возвращает объект с обновлёнными координатами. Этот подход обеспечивает высокую модульность и возможность добавления собственных обработчиков.

import { computePosition, offset, flip, shift } from '@floating-ui/dom';

computePosition(reference, floating, {
  middleware: [
    offset(10),
    flip(),
    shift({ padding: 5 })
  ]
}).then(({ x, y }) => {
  Object.assign(floating.style, {
    left: `${x}px`,
    top: `${y}px`
  });
});

Порядок обработки

Цепочка выполняется строго последовательно. Результат каждого обработчика передаётся следующему. Это позволяет, например, сначала сместить элемент на фиксированное расстояние (offset), затем проверить доступное пространство и при необходимости перевернуть позицию (flip), а после — скорректировать положение внутри границ контейнера (shift).

  • offset — смещение от базового элемента.
  • flip — автоматический выбор стороны с доступным пространством.
  • shift — корректировка позиции внутри видимой области.

Каждый из этих обработчиков возвращает объект с ключами x, y, а также дополнительной информацией (middlewareData), которую можно использовать в последующих обработчиках.

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

Floating UI позволяет создавать пользовательские middleware для специфических задач. Обработчик — это функция, принимающая объект с текущим положением и возвращающая объект с модифицированными координатами.

Пример создания кастомного смещения по кривой:

function curveOffset(value) {
  return ({ x, y }) => {
    return {
      x: x + Math.sin(y / 50) * value,
      y: y + Math.cos(x / 50) * value
    };
  };
}

computePosition(reference, floating, {
  middleware: [curveOffset(15)]
});

Использование данных middleware

Каждый обработчик может сохранять данные в middlewareData. Это позволяет передавать промежуточные значения другим обработчикам или использовать их для визуальных эффектов:

function logPosition() {
  return ({ x, y, middlewareData }) => {
    console.log('Текущая позиция:', x, y);
    return { x, y, middlewareData };
  };
}

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

Асинхронные обработчики

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

function asyncOffset() {
  return async ({ x, y }) => {
    const extraOffset = await fetchOffsetFromServer();
    return { x: x + extraOffset, y };
  };
}

Цепочка корректно обработает промисы и передаст результат следующему middleware, сохраняя последовательность вычислений.

Комбинация стандартных и кастомных middleware

Для создания сложных интерфейсов Floating UI предлагает комбинировать стандартные middleware с пользовательскими, создавая полноценные цепочки обработки:

computePosition(reference, floating, {
  middleware: [
    offset(5),
    flip(),
    shift({ padding: 8 }),
    curveOffset(10),
    logPosition()
  ]
});

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

Рекомендации по построению цепочек

  • Минимизировать количество middleware — слишком длинные цепочки могут повлиять на производительность.
  • Ставить offset первым — чтобы смещения применялись до проверки границ.
  • flip и shift ставить после смещения для корректной адаптации к контейнеру.
  • Асинхронные middleware использовать только при необходимости, чтобы не усложнять обработку.

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