/** * Pure geometry for the anatomy overlay's callouts: which labels go where, * and the leader line from each to its region. It knows nothing of the DOM, * only rectangles, so the overlay measures, calls in here, and draws. * * Labels sit in two gutters, left and right of the host, each region's label * on the side its centre leans to. A gutter that would leave the viewport * gives way to the other; when neither fits, the labels line up in a row * above the host (below it when there is no room above). Within a column or * row the labels are packed so none overlap, as close to their regions as * that allows. Regions that share a label text share one label. */ export interface Box { left: number; top: number; right: number; bottom: number; } export interface Point { x: number; y: number; } export type Side = 'left' | 'right' | 'above' | 'below'; /** One drawn region and the label text it answers to. */ export interface Region { key: string; text: string; color: string; box: Box; } /** Regions with the same label text, which get one label between them. */ export interface Group { text: string; color: string; regions: Region[]; } export interface Viewport { width: number; height: number; } export interface Placement { left: number; top: number; width: number; height: number; side: Side; } /** Space kept between a label and the host, and between stacked labels. */ export declare const GUTTER = 24; /** * How far a column label sits above the height its leader lands at, so * every leader bends rather than running flat. */ export declare const LABEL_RISE = 12; /** Groups regions by label text, in order of first appearance. */ export declare const groupRegions: (regions: Region[]) => Group[]; /** What a group's label says: its text, and how many regions it covers. */ export declare const groupLabel: (g: Group) => string; /** The mean of a group's region centres, where its label would like to be. */ export declare const anchorOf: (g: Group) => Point; /** The gutter a group's label goes to: the side its centre leans to. */ export declare const sideFor: (g: Group, host: Box) => 'left' | 'right'; interface Item { /** Where the item would start along the axis if nothing were in its way. */ want: number; size: number; } /** * Where each item starts along an axis so none overlap, with `gap` between * neighbours, in the input's order. Items keep the order of their `want`; * each cluster that has to spread out is centred on what its members * wanted. The result is pulled inside `[min, max]` when the items fit. */ export declare const pack: (items: Item[], gap: number, min: number, max: number) => number[]; /** The side each group's label goes to, or a row when no gutter fits. */ export declare const assignSides: (groups: Group[], widths: number[], host: Box, view: Viewport) => ('left' | 'right' | 'row')[]; /** Where each group's label goes, in the order of `groups`. */ export declare const layoutLabels: (groups: Group[], widths: number[], height: number, host: Box, view: Viewport) => Placement[]; /** * The point of `box` nearest `from`, on its edge: the facing edge at the * height of the label, or its corner when the label sits past the box's * vertical range. A point inside the box goes to the nearest edge. */ export declare const edgePoint: (box: Box, from: Point) => Point; export interface Leader { /** * SVG path data: a stub out of the label, then a 45° bend into the * region, or a curve for one of a grouped label's several leaders. */ d: string; end: Point; } /** * The leader from a label to the region `box`: angled, or curved when * `fan` says the label leads to several regions. */ export declare const leaderTo: (p: Placement, box: Box, fan?: boolean) => Leader; export {}; //# sourceMappingURL=anatomy-layout.d.ts.map