Библиотека Floating UI предоставляет мощный механизм позиционирования всплывающих элементов (tooltip, dropdown, popover) относительно якорных элементов. В средах с использованием TypeScript типизация играет ключевую роль в обеспечении надежности, предсказуемости и удобства разработки.
Типы в Floating UI охватывают:
Основой позиционирования является структура координат:
interface Coords {
x: number;
y: number;
}
Эти значения представляют финальную позицию floating-элемента.
Ключевым типом является Placement, определяющий
расположение относительно якоря:
type Placement =
| 'top'
| 'bottom'
| 'left'
| 'right'
| 'top-start'
| 'top-end'
| 'bottom-start'
| 'bottom-end'
| 'left-start'
| 'left-end'
| 'right-start'
| 'right-end';
Типизация placement:
Главная функция библиотеки:
computePosition(reference, floating, options)
Типизация параметров:
function computePosition(
reference: ReferenceElement,
floating: FloatingElement,
options?: ComputePositionConfig
): Promise<ComputePositionReturn>;
type ReferenceElement =
| Element
| VirtualElement;
Поддержка виртуальных элементов позволяет позиционировать относительно:
type FloatingElement = HTMLElement;
Тип виртуального элемента:
interface VirtualElement {
getBoundingClientRect(): DOMRect;
contextElement?: Element;
}
Особенности:
getBoundingClientRectТипизация гарантирует:
interface ComputePositionConfig {
placement?: Placement;
strategy?: 'absolute' | 'fixed';
middleware?: Middleware[];
platform?: Platform;
}
Тип строго ограничен Placement, исключая некорректные
значения.
type Strategy = 'absolute' | 'fixed';
Типизация:
type Middleware = {
name: string;
options?: any;
fn: MiddlewareFn;
};
Middleware — ключевая часть Floating UI. Они обрабатывают позиционирование по цепочке.
type MiddlewareFn = (state: MiddlewareState) => MiddlewareReturn;
interface MiddlewareState {
x: number;
y: number;
initialPlacement: Placement;
placement: Placement;
strategy: Strategy;
middlewareData: Record<string, any>;
elements: {
reference: ReferenceElement;
floating: FloatingElement;
};
rects: {
reference: Rect;
floating: Rect;
};
platform: Platform;
}
Типизация состояния:
interface MiddlewareReturn {
x?: number;
y?: number;
data?: Record<string, any>;
reset?: {
placement?: Placement;
rects?: boolean;
};
}
Особенности:
Floating UI предоставляет готовые middleware с типизированными опциями.
function offset(
value: number | OffsetOptions
): Middleware;
interface OffsetOptions {
mainAxis?: number;
crossAxis?: number;
alignmentAxis?: number | null;
}
interface FlipOptions {
fallbackPlacements?: Placement[];
padding?: Padding;
boundary?: Boundary;
}
interface ShiftOptions {
mainAxis?: boolean;
crossAxis?: boolean;
limiter?: {
fn: (state: MiddlewareState) => Coords;
};
}
Типизация:
Абстракция платформы позволяет использовать Floating UI вне браузера.
interface Platform {
getElementRects(...): Promise<ElementRects>;
getClippingRect(...): Promise<Rect>;
getDimensions(...): Promise<Dimensions>;
convertOffsetParentRelativeRectToViewportRelativeRect(...): Rect;
getOffsetParent(...): Promise<Element | null>;
isElement(value: unknown): value is Element;
getDocumentElement(...): Element;
}
Типизация:
interface ComputePositionReturn {
x: number;
y: number;
placement: Placement;
strategy: Strategy;
middlewareData: Record<string, any>;
}
Типизация результата:
Floating UI активно использует дженерики для расширяемости.
Пример пользовательского middleware:
type CustomData = {
myValue: number;
};
const myMiddleware: Middleware = {
name: 'myMiddleware',
fn(state) {
return {
data: {
myValue: 42
}
};
}
};
При строгой типизации можно расширить
middlewareData:
interface ExtendedMiddlewareData {
myMiddleware?: CustomData;
}
Это позволяет:
anytype Padding =
| number
| {
top?: number;
right?: number;
bottom?: number;
left?: number;
};
type Boundary =
| Element
| Element[]
| 'clippingAncestors';
Преимущества:
Floating UI использует type guards:
function isElement(value: unknown): value is Element;
Это позволяет:
При использовании с React:
const referenceRef = useRef<HTMLElement | null>(null);
const floatingRef = useRef<HTMLDivElement | null>(null);
Типизация:
Эффективное использование типизации в Floating UI включает:
1. Избегание any
2. Явное указание Placement
const placement: Placement = 'bottom-start';
3. Типизация middlewareData
const data = middlewareData.myMiddleware?.myValue;
4. Использование дженериков
Ошибка: неверный placement
placement: 'bottom-left' // ошибка
Типизация предотвращает это на этапе компиляции.
Ошибка: неправильная структура middleware
fn: () => ({ wrongField: true }) // ошибка типов
Ошибка: работа с null-элементами
referenceRef.current.getBoundingClientRect() // возможна ошибка
Решение:
if (referenceRef.current) {
// безопасно
}
Типизация в Floating UI:
Строгие типы превращают библиотеку из утилиты позиционирования в устойчивый фундамент для построения сложных UI-систем.