/** * Utility used to transform the `auto` placement to the placement with more * available space. */ import { getBoundaries } from './getBoundaries'; import { Offsets, PlacementForBs5 } from '../models'; import { getBsVer } from 'ngx-bootstrap/utils'; function getArea({ width, height }: { width: number; height: number }) { return width * height; } export function computeAutoPlacement( placement: string, refRect: Offsets, target: HTMLElement, host: HTMLElement, allowedPositions = ['top', 'bottom', 'right', 'left'], boundariesElement = 'viewport', padding = 0 ) { if (placement.indexOf('auto') === -1) { return placement; } const boundaries = getBoundaries(target, host, padding, boundariesElement); type Rects = { top: Offsets; right: Offsets; bottom: Offsets; left: Offsets }; const rects: Rects = { top: { width: boundaries?.width ?? 0, height: (refRect?.top ?? 0) - (boundaries?.top ?? 0) }, right: { width: (boundaries?.right ?? 0) - (refRect?.right ?? 0), height: boundaries?.height ?? 0 }, bottom: { width: boundaries?.width ?? 0, height: (boundaries?.bottom ?? 0) - (refRect?.bottom ?? 0) }, left: { width: (refRect.left ?? 0) - (boundaries?.left ?? 0), height: boundaries?.height ?? 0 } }; const sortedAreas = Object.keys(rects) .map((key) => ({ position: key, ...rects[key as keyof Rects], area: getArea(rects[key as keyof Rects] as { width: number; height: number }) })) .sort((a, b) => b.area - a.area); let filteredAreas = sortedAreas.filter(({ width, height }) => { return width >= target.clientWidth && height >= target.clientHeight; }); filteredAreas = filteredAreas.filter(({ position }) => { return allowedPositions.some((allowedPosition: string) => { return allowedPosition === position; }); }); const computedPlacement: string = filteredAreas.length > 0 ? filteredAreas[0].position : sortedAreas[0].position; const variation = placement.split(' ')[1]; // for tooltip on auto position target.className = target.className.replace( /bs-tooltip-auto/g, `bs-tooltip-${ getBsVer().isBs5 ? PlacementForBs5[computedPlacement as keyof typeof PlacementForBs5] : computedPlacement }` ); return computedPlacement + (variation ? `-${variation}` : ''); }