import { Fun, type Optional } from '@ephox/katamari'; import type { SugarElement } from '@ephox/sugar'; import type { Bounds } from '../../alien/Boxes'; import type { AnchorOverrides, MaxHeightFunction, MaxWidthFunction } from '../mode/Anchoring'; import * as Callouts from '../view/Callouts'; import type { Transition } from '../view/Transitions'; import type { Anchor } from './Anchor'; import type { Bubble } from './Bubble'; import type { PlacerResult } from './LayoutTypes'; import type * as LayoutTypes from './LayoutTypes'; import * as MaxHeight from './MaxHeight'; import * as Origins from './Origins'; export interface ReparteeOptions { readonly bounds: Bounds; readonly origin: Origins.OriginAdt; readonly preference: LayoutTypes.AnchorLayout[]; readonly maxHeightFunction: MaxHeightFunction; readonly maxWidthFunction: MaxWidthFunction; readonly lastPlacement: Optional; readonly transition: Optional; } const defaultOr = (options: AnchorOverrides, key: K, dephault: NonNullable): NonNullable => options[key] === undefined ? dephault : options[key] as NonNullable; // This takes care of everything when you are positioning UI that can go anywhere on the screen const simple = ( anchor: Anchor, element: SugarElement, bubble: Bubble, layouts: LayoutTypes.AnchorLayout[], lastPlacement: Optional, optBounds: Optional, overrideOptions: AnchorOverrides, transition: Optional ): PlacerResult => { // the only supported override at the moment. Once relative has been deleted, maybe this can be optional in the bag const maxHeightFunction: MaxHeightFunction = defaultOr(overrideOptions, 'maxHeightFunction', MaxHeight.anchored()); const maxWidthFunction: MaxWidthFunction = defaultOr(overrideOptions, 'maxWidthFunction', Fun.noop); const anchorBox = anchor.anchorBox; const origin = anchor.origin; const options: ReparteeOptions = { bounds: Origins.viewport(origin, optBounds), origin, preference: layouts, maxHeightFunction, maxWidthFunction, lastPlacement, transition }; return go(anchorBox, element, bubble, options); }; // This is the old public API. If we ever need full customisability again, this is how to expose it const go = (anchorBox: LayoutTypes.AnchorBox, element: SugarElement, bubble: Bubble, options: ReparteeOptions): PlacerResult => { const decision = Callouts.layout(anchorBox, element, bubble, options); Callouts.position(element, decision, options); Callouts.setPlacement(element, decision); Callouts.setClasses(element, decision); Callouts.setHeight(element, decision, options); Callouts.setWidth(element, decision, options); return { layout: decision.layout, placement: decision.placement }; }; export { simple };