import type { Graph } from "./graph";
import { type LayoutResult, type NodeSize, type Rankdir } from "./layout";
/**
 * a function to tweak a graph layout
 *
 * {@link Tweak}s allow abstracting over general modifications to graph
 * layouts. There are several built in:
 * - {@link tweakSize} - This tweak scales the graph so that its final size is
 *   a specified constant size.
 * - {@link tweakFlip} - This tweak allows flipping the graph in various ways,
 *   so you could make a layout bottom up, or horizontal.
 * - {@link tweakGrid} - Tweaks {@link grid} layout link points to make
 *   pleasing links easier to render.
 * - {@link tweakShape} - Given the current {@link NodeSize}, sets the final
 *   control points of each link so that they end on the edge of the given
 *   shape. For simple layouts, this should prevent needing to render links
 *   behind nodes. In complex cases, it allows consistently rendering arrows or
 *   other link terminal icons at the edge of a shape.
 * - {@link tweakSugiyama} - Adds control points inside the bounding box of
 *   source/target nodes, preventing edges from crossing over nodes.
 * - {@link tweakGridHandles} - Moves grid edge bend points to the midpoint of
 *   the gap between rows, producing smoother edges for handle-based frameworks.
 * - {@link tweakDirection} - Converts the default top-to-bottom layout to a
 *   specified direction (BT, LR, RL).
 *
 * You can also implement your own tweak. There's not a reason to give an
 * example, as tweaks are pretty unbounded. As input you get a laidout graph,
 * and the dimensions of that layout. Modify the graph arbitrarily, and return
 * the new dimensions after tweaking the layout.
 */
export type Tweak<in N = never, in L = never> = (graph: Graph<N, L>, res: Readonly<LayoutResult>) => LayoutResult;
/**
 * tweak the laidout dag by resizing it
 *
 * The x and y coordinates of everything are rescaled to fit within the specified size.
 */
export declare function tweakSize(size: Readonly<LayoutResult>): Tweak<unknown, unknown>;
/**
 * This tweak adds extra control points to the grid layout
 *
 * The grid layout often looks best with rounded corners. This tweak adds extra
 * control points to edges so that `d3.curveBasis` curves produce nice rounded
 * edges.
 *
 * rounding should be set somewhere between 0 and nodeSize.
 */
export declare function tweakGrid(rounding: readonly [number, number]): Tweak<unknown, unknown>;
/**
 * Tweak to flip the layout in several ways
 *
 * - `diagonal` : flips x and y coordinates turning x into y
 * - `horizontal` : inverts x
 * - `vertical` : inverts y
 */
export declare function tweakFlip(style?: "diagonal" | "horizontal" | "vertical"): Tweak<unknown, unknown>;
/**
 * a shape callable used to truncate an edge path at a node
 *
 * This represents how to tweak the edge of a link conditioned on the shape of
 * the node. This is useful for adding endings to an link (like arrows) that
 * will align with a node well.
 */
export type Shape = (center: readonly [number, number], nodeSize: readonly [number, number], start: readonly [number, number], end: readonly [number, number]) => [number, number];
/**
 * a bounding box shape for the full rectangle
 *
 * Useful with [`tweakShape`].
 */
export declare function shapeRect(center: readonly [number, number], nodeSize: readonly [number, number], start: readonly [number, number], end: readonly [number, number]): [number, number];
/**
 * a bounding box shape for an ellipse
 *
 * Useful with [`tweakShape`].
 */
export declare function shapeEllipse(center: readonly [number, number], nodeSize: readonly [number, number], start: readonly [number, number], end: readonly [number, number]): [number, number];
/**
 * a shape that aligns edges with the centered top or bottom of a node
 *
 * Useful with [`tweakShape`].
 */
export declare function shapeTopBottom(center: readonly [number, number], nodeSize: readonly [number, number], start: readonly [number, number], end: readonly [number, number]): [number, number];
/**
 * tweak the layout by truncating edges early
 *
 * This tweak truncates edges at the extent of a node shape sized by a bounding
 * box. After applying this tweak, edge endings like arrows can be easily
 * rendered in the appropriate place.
 *
 * There are three built in {@link Shape}s:
 * - {@link shapeRect} - a simple rectangle
 * - {@link shapeEllipse} - an ellipse (circle for square node sizes)
 * - {@link shapeTopBottom} - to center edges into the top or bottom of a node
 */
export declare function tweakShape<N, L>(nodeSize: NodeSize<N, L>, shape?: Shape): Tweak<N, L>;
/**
 * tweak the sugiyama layout by add a control point inside the bounding box
 *
 * This tweak adds a control point to the edge (top / bottom) of the bounding
 * box. This prevents edges from crossing over nodes when nodes are very far
 * apart horizontally.
 *
 * @remarks
 *
 * If using in conjunction with {@link tweakShape}, this should occur first,
 * although it shouldn't be strictly necessary.
 */
export declare function tweakSugiyama<N, L>(nodeSize: NodeSize<N, L>): Tweak<N, L>;
/**
 * tweak grid edge bend points to the midpoint of the gap between rows
 *
 * Grid layouts place bend points at source or target y-levels, which can
 * cause edges to kink when rendered with handle-based frameworks like React
 * Flow. This tweak moves interior bend points to the midpoint of the gap
 * between rows (bottom of node + half of y gap), producing smoother edges.
 *
 * @remarks
 *
 * This should be applied before flip tweaks.
 */
export declare function tweakGridHandles<N, L>(nodeSize: NodeSize<N, L>, gap: readonly [number, number]): Tweak<N, L>;
/**
 * tweak the layout to apply a direction
 *
 * Layouts produce top-to-bottom (TB) output by default. This tweak converts
 * the layout to the given direction by composing the appropriate flips.
 *
 * @remarks
 *
 * This should be applied after all other tweaks.
 */
export declare function tweakDirection(direction: Rankdir): Tweak<unknown, unknown>;
