// size — computes the width/height available to the floating element within the // clipping boundary and hands it to `apply` (the consumer writes CSS vars). // PURE. Our engine never re-reads DOM mid-loop: `apply` doesn't resize the // floating element synchronously in the soma layer, so the floating-ui // `reset: { rects: true }` round-trip is unnecessary (a real resize re-triggers // via the autoUpdate ResizeObserver). Reimplemented from floating-ui's `size`. import { getAlignment, getSide, getSideAxis } from '../geometry' import { detectOverflow, type DetectOverflowOptions } from '../overflow' import type { Middleware, MiddlewareState } from '../types' export type SizeApplyArgs = MiddlewareState & { availableWidth: number availableHeight: number } export type SizeOptions = DetectOverflowOptions & { apply?: (args: SizeApplyArgs) => void } const { min, max } = Math export function size(options: SizeOptions = {}): Middleware { const { apply = () => {}, ...detectOptions } = options return { name: 'size', options, fn(state) { const { placement, rects, rtl, middlewareData } = state const overflow = detectOverflow(state, detectOptions) const side = getSide(placement) const alignment = getAlignment(placement) const isYAxis = getSideAxis(placement) === 'y' const { width, height } = rects.floating let heightSide: 'top' | 'bottom' let widthSide: 'left' | 'right' if (side === 'top' || side === 'bottom') { heightSide = side widthSide = alignment === (rtl ? 'start' : 'end') ? 'left' : 'right' } else { widthSide = side as 'left' | 'right' heightSide = alignment === 'end' ? 'top' : 'bottom' } const maximumClippingHeight = height - overflow.top - overflow.bottom const maximumClippingWidth = width - overflow.left - overflow.right const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight) const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth) const shiftData = middlewareData.shift as | { enabled?: { x?: boolean; y?: boolean } } | undefined const noShift = !shiftData let availableHeight = overflowAvailableHeight let availableWidth = overflowAvailableWidth if (shiftData?.enabled?.x) availableWidth = maximumClippingWidth if (shiftData?.enabled?.y) availableHeight = maximumClippingHeight if (noShift && !alignment) { const xMin = max(overflow.left, 0) const xMax = max(overflow.right, 0) const yMin = max(overflow.top, 0) const yMax = max(overflow.bottom, 0) if (isYAxis) { availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right)) } else { availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom)) } } apply({ ...state, availableWidth, availableHeight }) return {} } } }