В библиотеке Floating UI объект middleware представляет
собой фундаментальный инструмент для управления позиционированием
всплывающих элементов. Middleware отвечает за модификацию координат,
обработку смещений, ограничение области видимости и динамическую
адаптацию поведения элементов интерфейса.
middleware всегда передается в функцию
computePosition в виде массива объектов или функций. Каждый
middleware выполняется последовательно, получая текущие координаты
x и y, а также дополнительную информацию о
положении элемента и его окружении. На выходе middleware возвращает
объект с возможными изменениями этих координат или другими параметрами,
влияющими на рендеринг.
Простейший пример структуры middleware:
const middleware = [
offset(10),
flip(),
shift()
];
Здесь offset, flip и shift —
встроенные middleware, каждый из которых реализует определенное
поведение.
Каждый middleware в Floating UI представляет собой объект или функцию, которая может содержать следующие свойства:
name (строка) Уникальное имя middleware. Оно используется для идентификации в цепочке обработки и для логирования.
{ name: 'offset' }options (объект, необязательный) Настройки middleware, задающие его поведение. Например, величина смещения, направление срабатывания, ограничения по экрану.
{ name: 'offset', options: { mainAxis: 10, crossAxis: 5 } }fn (функция) Основная функция middleware, принимающая объект с текущим состоянием позиционирования и возвращающая изменения. Аргументы функции обычно включают:
x и y — текущие координаты элемента.placement — позиция относительно reference-элемента
(top, bottom, left,
right).strategy — стратегия позиционирования
(absolute или fixed).elements — объект с элементами reference и
floating.rects — размеры reference и floating элементов.platform — объект платформы с низкоуровневыми методами
для работы с DOM.Функция возвращает объект с изменениями:
{
x: newX,
y: newY,
data: { customData }
}
Пример простого middleware для смещения:
function customOffset({ x, y, options }) {
return {
x: x + (options?.x || 0),
y: y + (options?.y || 0)
};
}
const middleware = { name: 'customOffset', fn: customOffset, options: { x: 20, y: 10 } };Middleware может возвращать несколько ключевых полей, влияющих на позиционирование:
Пример с reset:
function limitToViewport({ x, y, rects, elements }) {
if (x + rects.floating.width > window.innerWidth) {
return { reset: { x: window.innerWidth - rects.floating.width } };
}
return { x, y };
}
Middleware обрабатываются последовательно. Каждый следующий middleware получает координаты, модифицированные предыдущими. Это позволяет строить сложные цепочки трансформаций:
Если один из middleware возвращает reset, цепочка
прерывается, и происходит повторный вызов computePosition с
обновленными параметрами.
name для идентификации
middleware.data для передачи промежуточных вычислений
другим middleware.elements или rects
напрямую, использовать только возвращаемые координаты.function adaptiveShift({ x, y, rects, placement, options }) {
let newX = x;
let newY = y;
if (x + rects.floating.width > window.innerWidth) {
newX = window.innerWidth - rects.floating.width - (options?.padding || 8);
}
if (y + rects.floating.height > window.innerHeight) {
newY = window.innerHeight - rects.floating.height - (options?.padding || 8);
}
return {
x: newX,
y: newY,
data: { adjusted: true }
};
}
const middleware = [
offset({ mainAxis: 10 }),
adaptiveShift({ padding: 12 }),
flip()
];
В этом примере middleware adaptiveShift динамически
корректирует положение, учитывая границы viewport, а цепочка позволяет
гибко сочетать смещение, адаптивную подгонку и поворот элемента.
Структура объекта middleware в Floating UI обеспечивает мощный,
модульный и предсказуемый механизм управления позиционированием.
Понимание ключевых полей name, fn,
options и возвращаемых значений x,
y, data и reset позволяет
создавать как простые, так и сложные решения для любых
UI-компонентов.