@svg-fns/layout
Version:
Lightweight SVG layout utilities — viewBox parsing, scaling, cropping, and trimming for precise content-aware rendering.
209 lines (204 loc) • 6.46 kB
text/typescript
/**
* Axis-aligned rectangle.
* - `x`, `y`: top-left corner coordinates
* - `width`, `height`: rectangle dimensions
*/
type Rect = { x: number; y: number; width: number; height: number };
/**
* Padding specification for layout or box-model operations.
* - Single number applies to all sides
* - Object form allows per-side values
*/
type Padding =
| number
| { top: number; right: number; bottom: number; left: number };
/**
* Affine transformation matrix tuple.
* Matches SVGMatrix `[a b c d e f]`, representing:
*
* [ a c e ]
* [ b d f ]
* [ 0 0 1 ]
*
* Used for scale, rotate, skew, and translate operations.
*/
type Matrix = [number, number, number, number, number, number];
/**
* Parse a `viewBox` string into a rect.
*
* @param vb viewBox attribute string
* @returns Rect or null if invalid
* @link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
*/
declare const parseViewBox: (vb: string | null) => Rect | null;
/**
* Read current viewBox of an SVG.
*
* @param svg SVG element
* @returns Rect or null
*/
declare const getViewBox: (svg: SVGSVGElement) => Rect | null;
/**
* Set SVG viewBox (and optionally preserveAspectRatio).
*
* @param svg SVG element
* @param rect Rect to set
* @param opts Options (round, preserveAspectRatio)
*/
declare const setViewBox: (svg: SVGSVGElement, { x, y, height, width }: Rect, opts?: {
preserveAspectRatio?: string;
round?: boolean;
}) => void;
/**
* Parse dimension string into pixels where possible.
* - Supports: unitless, px, vh, vw (requires `window`)
* - Supports: em, rem (requires optional `fontSize` context)
* - Throws on unsupported units or missing context
*
* @param v Attribute string
* @param context Optional: { fontSize?: number } for em/rem
* @returns number in px, or null if empty
*/
declare const parseDimension: (v: string | null, context?: {
fontSize?: number;
}) => number | null;
/**
* Read width/height attributes.
*
* @param svg SVG element
* @returns { width, height } or nulls
*/
declare const getDimensions: (svg: SVGSVGElement, context?: {
fontSize?: number;
}) => {
width: number | null;
height: number | null;
};
/**
* Update width/height attributes.
*
* @param svg SVG element
* @param width New width (optional)
* @param height New height (optional)
*/
declare const updateDimensions: (svg: SVGSVGElement, width?: number | null, height?: number | null) => void;
/**
* Compute the bounding box of an SVG element with its current transform matrix applied.
*
* Unlike `element.getBBox()`, which ignores transforms (scale, rotate, translate),
* this function projects the element's local bounding box into the SVG's coordinate
* system by applying the element's `CTM` (current transformation matrix).
*
* @param el - Any SVGGraphicsElement (e.g., <path>, <text>, <rect>, <g>, <image>, …)
* @returns The transformed bounding box as { x, y, width, height }
*
* @example
* ```ts
* const svg = document.querySelector("svg")!;
* const text = svg.querySelector("text")!;
* const box = getBBoxWithTransform(text);
* console.log(box); // Correct bounds, accounting for transform="scale(.1)"
* ```
*
* @remarks
* - Throws if the element does not support `getBBox()`.
* - Returns the raw transformed box; if you need union across multiple elements,
* compose with a `unionRects` utility.
*/
declare const getBBoxWithTransform: (el: SVGGraphicsElement) => Rect;
/**
* Compute a tight bounding box of SVG content.
* - Starts with root <svg> getBBox()
* - Optionally expands to children that extend beyond root
*
* @param svg The SVG element to compute content bounds for
* @param clipToViewBox If true, only use root <svg> bbox
* @returns Rect bounding all visible graphics
* @see https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement/getBBox
*/
declare const getContentBBox: (svg: SVGSVGElement, clipToViewBox?: boolean) => Rect;
/**
* Compute trim box (tight content box + padding).
*
* @param svg SVG element
* @param padding Padding
* @returns @link {Rect}
*/
declare const computeTrimBox: (svg: SVGSVGElement, padding?: Padding, clipToViewBox?: boolean) => Rect;
/**
* Tightly crop an SVG to content.
*
* @param svg SVG element
* @param opts Options (padding, mutate, preserveDimensions, round)
* @returns { box, apply } where apply() applies crop
*/
declare const tightlyCropSvg: (svg: SVGSVGElement, opts?: {
padding?: Padding;
mutate?: boolean;
preserveDimensions?: boolean;
round?: boolean;
clipToViewBox?: boolean;
}) => {
box: Rect;
apply: (target?: SVGSVGElement) => SVGSVGElement;
};
/**
* Translate current viewBox.
*
* @param svg SVG element
* @param dx Delta x
* @param dy Delta y
* @param opts Options (mutate, round)
*/
declare const translateViewBox: (svg: SVGSVGElement, dx: number, dy: number, opts?: {
mutate?: boolean;
round?: boolean;
}) => Rect | null;
/**
* Scale (zoom) current viewBox.
*
* @param svg SVG element
* @param factor Zoom factor (>0)
* @param cx Optional center x
* @param cy Optional center y
* @param opts Options (mutate, round)
*/
declare const scaleViewBox: (svg: SVGSVGElement, factor: number, cx?: number, cy?: number, opts?: {
mutate?: boolean;
round?: boolean;
}) => Rect | null;
/**
* Apply matrix transform to viewBox.
*
* @param svg SVG element
* @param matrix Affine matrix
* @param opts Options (mutate, round)
*/
declare const setViewBoxTransform: (svg: SVGSVGElement, matrix: Matrix, opts?: {
mutate?: boolean;
round?: boolean;
}) => Rect | null;
/**
* Center viewBox around content center.
*
* @param svg SVG element
* @param opts Options (mutate, round)
*/
declare const centerSvg: (svg: SVGSVGElement, opts?: {
mutate?: boolean;
round?: boolean;
}) => Rect | null;
/**
* Fit content into target rect (preserve aspect ratio).
*
* @param svg SVG element
* @param targetW Target width
* @param targetH Target height
* @param opts Options (mutate, padding, round)
*/
declare const fitSvg: (svg: SVGSVGElement, targetW: number, targetH: number, opts?: {
mutate?: boolean;
padding?: Padding;
round?: boolean;
}) => Rect | null;
export { centerSvg, computeTrimBox, fitSvg, getBBoxWithTransform, getContentBBox, getDimensions, getViewBox, parseDimension, parseViewBox, scaleViewBox, setViewBox, setViewBoxTransform, tightlyCropSvg, translateViewBox, updateDimensions };