import type { CSSProperties, ReactNode } from 'react'; import { useMemo } from 'react'; import { useBBoxObserver } from '../hooks/useBBoxObserver.js'; export type Align = 'start' | 'middle' | 'end' | 'none'; export interface AlignGroupProps { x?: number; y?: number; style?: CSSProperties; verticalAlign?: Align; horizontalAlign?: Align; children: ReactNode | ReactNode[]; } function calculatePosition( start: number, align: Align, space: number, value: number, ) { switch (align) { case 'start': { return start; } case 'end': { return start - space; } case 'middle': { return start - space / 2; } case 'none': { return value; } default: { throw new Error(`Unkwnown alignment ${JSON.stringify(align)}`); } } } export function AlignGroup(props: AlignGroupProps) { const { x = 0, y = 0, verticalAlign = 'start', horizontalAlign = 'start', children, style = {}, } = props; const observed = useBBoxObserver(); const xPosition = useMemo( () => calculatePosition( x - observed.x, horizontalAlign, observed.width || 0, x, ), [x, observed.x, observed.width, horizontalAlign], ); const yPosition = useMemo( () => calculatePosition(y - observed.y, verticalAlign, observed.height || 0, y), [y, observed.y, observed.height, verticalAlign], ); return ( {children} ); }