Popper.js использует концепцию модификаторов для управления поведением всплывающих элементов (popper) относительно их опорного элемента (reference). Каждый модификатор может быть настроен через определённый тип, который определяет структуру его данных, допустимые значения и поведение при инициализации.
Модификатор в Popper.js представляет собой объект с обязательными и опциональными полями:
const exampleModifier = {
name: 'example',
enabled: true,
phase: 'main',
fn: ({ state, name, options }) => {
// логика модификатора
},
effect: ({ state, name, options }) => {
// побочный эффект модификатора
return () => {
// функция очистки
};
},
options: {
key1: 'value1',
key2: 42
},
};
Ключевые свойства:
name — уникальное имя модификатора.enabled — флаг включения/отключения.phase — этап жизненного цикла (beforeRead,
read, afterRead, beforeMain,
main, afterMain, beforeWrite,
write, afterWrite).fn — функция, выполняющая основное действие
модификатора.effect — функция побочного эффекта, которая вызывается
один раз при инициализации.options — объект с пользовательскими настройками.optionsPopper.js позволяет создавать модификаторы с различными типами опций. Стандартно выделяют несколько категорий:
boolean)Используются для включения или отключения специфического поведения модификатора.
const hideModifier = {
name: 'hide',
enabled: true,
options: {
checkOverflow: true
}
};
number)Применяются для указания расстояний, задержек, смещений и коэффициентов масштабирования.
const offsetModifier = {
name: 'offset',
enabled: true,
options: {
offset: [0, 10] // [skidding, distance]
}
};
string)Обычно указывают направление (start, end,
top, bottom, left,
right) или стратегию позиционирования
(absolute, fixed).
const flipModifier = {
name: 'flip',
enabled: true,
options: {
fallbackPlacements: ['top', 'right']
}
};
array)Используются для перечисления допустимых значений, например fallback-позиций или списка элементов для наблюдения.
const preventOverflowModifier = {
name: 'preventOverflow',
enabled: true,
options: {
altAxis: true,
padding: [5, 10, 5, 10] // [top, right, bottom, left]
}
};
object)Позволяют передавать сложные настройки, включая функции обратного вызова, массивы и вложенные структуры.
const arrowModifier = {
name: 'arrow',
enabled: true,
options: {
element: document.querySelector('.arrow'),
padding: { top: 5, bottom: 5, left: 8, right: 8 }
}
};
function)Используются для динамического расчёта значения модификатора во время его выполнения.
const computeStylesModifier = {
name: 'computeStyles',
enabled: true,
options: {
adaptive: (state) => state.rects.reference.width > 100
}
};
Popper.js поставляется с типами, которые помогают строго контролировать структуры модификаторов. Основной тип модификатора в TypeScript выглядит так:
interface Modifier<Name extends string = string, Options = any> {
name: Name;
enabled?: boolean;
phase?: ModifierPhases;
requires?: string[];
requiresIfExists?: string[];
fn: ModifierFn<Options>;
effect?: ModifierEffect<Options>;
options?: Partial<Options>;
}
Ключевые моменты типизации:
Name — строковый литерал, уникальный для каждого
модификатора.Options — интерфейс, описывающий типы данных внутри
options.fn и effect строго типизированы через
обобщённые параметры Options.requires и requiresIfExists задают
зависимости модификаторов.Popper.js допускает создание пользовательских модификаторов. Чтобы избежать ошибок при передаче некорректных опций:
interface MyCustomOptions {
offsetValue: number;
isEnabled: boolean;
}
const myCustomModifier: Modifier<'myModifier', MyCustomOptions> = {
name: 'myModifier',
enabled: true,
phase: 'main',
fn: ({ state, options }) => {
if (options.isEnabled) {
state.styles.popper.transform += ` translateY(${options.offsetValue}px)`;
}
},
options: {
offsetValue: 10,
isEnabled: true
}
};
Использование строгих типов позволяет IDE и TypeScript сразу предупреждать о несоответствиях, что снижает количество ошибок в рантайме.
Модификаторы Popper.js могут быть вложенными. Например, объект
padding внутри preventOverflow может иметь
разные типы:
number — одинаковое значение для всех сторон.object — отдельные значения для каждой стороны.function — динамическое вычисление значения на основе
состояния.options: {
padding: ({ placement, rects }) => {
return placement.startsWith('top') ? 10 : 5;
}
}
Использование правильного типа обеспечивает корректное позиционирование и работу модификатора с разными вариантами конфигурации.
Типы модификаторов — это не просто формальность, а мощный инструмент контроля поведения Popper.js. Они позволяют:
Правильная типизация и строгий контроль типов делают работу с Popper.js безопасной и удобной даже в крупных проектах.