import { Rect } from "@monstermann/geometry";
const anchorElement = document.querySelector(".anchor");
const popoverElement = document.querySelector(".popover");
const boundaryRect = pipe(Rect.fromWindow(), Rect.shrink(20));
const anchorRect = Rect.fromElement(anchorElement);
const popoverRect = pipe(
Rect.fromElement(popoverElement),
Rect.alignTop(anchorRect),
Rect.placeRightOf(anchorRect, 10),
Rect.clamp(boundaryRect),
);
Object.assign(popoverElement.style, {
position: "absolute",
translate: `transform(${popoverRect.left}px, ${popoverRect.top}px)`,
maxHeight: `${boundaryRect.height}px`,
maxWidth: `${boundaryRect.width}px`,
});npm install @monstermann/geometrypnpm add @monstermann/geometryyarn add @monstermann/geometrybun add @monstermann/geometrynpm install -D @monstermann/unplugin-geometrypnpm -D add @monstermann/unplugin-geometryyarn -D add @monstermann/unplugin-geometrybun -D add @monstermann/unplugin-geometry// vite.config.ts
import geometry from "@monstermann/unplugin-geometry/vite";
export default defineConfig({
plugins: [geometry()],
});// rollup.config.js
import geometry from "@monstermann/unplugin-geometry/rollup";
export default {
plugins: [geometry()],
};// rolldown.config.js
import geometry from "@monstermann/unplugin-geometry/rolldown";
export default {
plugins: [geometry()],
};// webpack.config.js
const geometry = require("@monstermann/unplugin-geometry/webpack");
module.exports = {
plugins: [geometry()],
};// rspack.config.js
const geometry = require("@monstermann/unplugin-geometry/rspack");
module.exports = {
plugins: [geometry()],
};// esbuild.config.js
import { build } from "esbuild";
import geometry from "@monstermann/unplugin-geometry/esbuild";
build({
plugins: [geometry()],
});function Rect.alignBottom(target: Rect, source: Rect): RectAligns the bottom edge of the target rectangle to the bottom edge of the source rectangle by moving the target rectangle vertically.
Rect.alignBottom(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 10, top: 20, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignBottom({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 10, top: 20, width: 100, height: 50 }function Rect.alignCenter(target: Rect, source: Rect): RectAligns the center point of the target rectangle to the center point of the source rectangle by moving the target rectangle both horizontally and vertically.
Rect.alignCenter(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 50, top: 40, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignCenter({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 50, top: 40, width: 100, height: 50 }function Rect.alignCenterX(target: Rect, source: Rect): RectAligns the horizontal center of the target rectangle to the horizontal center of the source rectangle by moving the target rectangle horizontally only.
Rect.alignCenterX(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 50, top: 10, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignCenterX({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 50, top: 10, width: 100, height: 50 }function Rect.alignCenterY(target: Rect, source: Rect): RectAligns the vertical center of the target rectangle to the vertical center of the source rectangle by moving the target rectangle vertically only.
Rect.alignCenterY(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 10, top: 25, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignCenterY({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 10, top: 25, width: 100, height: 50 }function Rect.alignLeft(target: Rect, source: Rect): RectAligns the left edge of the target rectangle to the left edge of the source rectangle by moving the target rectangle horizontally.
Rect.alignLeft(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 50, top: 10, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignLeft({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 50, top: 10, width: 100, height: 50 }function Rect.alignRight(target: Rect, source: Rect): RectAligns the right edge of the target rectangle to the right edge of the source rectangle by moving the target rectangle horizontally.
Rect.alignRight(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 30, top: 10, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignRight({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 30, top: 10, width: 100, height: 50 }function Rect.alignTop(target: Rect, source: Rect): RectAligns the top edge of the target rectangle to the top edge of the source rectangle by moving the target rectangle vertically.
Rect.alignTop(
{ left: 10, top: 10, width: 100, height: 50 },
{ left: 50, top: 30, width: 80, height: 40 },
);
// { left: 10, top: 30, width: 100, height: 50 }pipe(
{ left: 10, top: 10, width: 100, height: 50 },
Rect.alignTop({ left: 50, top: 30, width: 80, height: 40 }),
);
// { left: 10, top: 30, width: 100, height: 50 }function Rect.area(rect: Rect): numberCalculates the area of a rectangle by multiplying its width and height.
Rect.area({ left: 10, top: 20, width: 100, height: 50 });
// 5000pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.area());
// 5000function Rect.bottom(rect: Rect): numberGets the bottom y-coordinate of a rectangle.
Rect.bottom({ left: 10, top: 20, width: 100, height: 50 });
// 70pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.bottom());
// 70function Rect.centerX(rect: Rect): numberGets the horizontal center x-coordinate of a rectangle.
Rect.centerX({ left: 10, top: 20, width: 100, height: 50 });
// 60pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.centerX());
// 60function Rect.centerY(rect: Rect): numberGets the vertical center y-coordinate of a rectangle.
Rect.centerY({ left: 10, top: 20, width: 100, height: 50 });
// 45pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.centerY());
// 45function Rect.clamp(target: Rect, source: Rect): RectConstrains the target rectangle to fit within the boundaries of the source rectangle, adjusting position and size as needed.
Rect.clamp(
{ left: 50, top: 60, width: 200, height: 100 },
{ left: 0, top: 0, width: 150, height: 120 },
);
// { left: 0, top: 0, width: 150, height: 100 }pipe(
{ left: 50, top: 60, width: 200, height: 100 },
Rect.clamp({ left: 0, top: 0, width: 150, height: 120 }),
);
// { left: 0, top: 0, width: 150, height: 100 }function Rect.contain(target: Rect, source: Rect): RectScales the target rectangle down proportionally so it fits entirely within the source rectangle while maintaining its aspect ratio, then centers it within the source.
Rect.contain(
{ left: 10, top: 20, width: 200, height: 100 },
{ left: 0, top: 0, width: 150, height: 120 },
);
// { left: 37.5, top: 30, width: 75, height: 60 }pipe(
{ left: 10, top: 20, width: 200, height: 100 },
Rect.contain({ left: 0, top: 0, width: 150, height: 120 }),
);
// { left: 37.5, top: 30, width: 75, height: 60 }function Rect.contains(a: Rect, b: Rect): booleanChecks if rectangle a completely contains rectangle b within its boundaries.
Rect.contains(
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 10, top: 20, width: 50, height: 30 },
);
// truepipe(
{ left: 0, top: 0, width: 100, height: 100 },
Rect.contains({ left: 10, top: 20, width: 50, height: 30 }),
);
// truefunction Rect.cover(target: Rect, source: Rect): RectScales the target rectangle up proportionally so it completely covers the source rectangle while maintaining its aspect ratio, then centers it within the source.
Rect.cover(
{ left: 10, top: 20, width: 100, height: 50 },
{ left: 0, top: 0, width: 150, height: 120 },
);
// { left: -75, top: -30, width: 300, height: 150 }pipe(
{ left: 10, top: 20, width: 100, height: 50 },
Rect.cover({ left: 0, top: 0, width: 150, height: 120 }),
);
// { left: -75, top: -30, width: 300, height: 150 }function Rect.distance(a: Rect, b: Rect): numberCalculates the shortest distance between two rectangles. Returns 0 if the rectangles intersect.
Rect.distance(
{ left: 0, top: 0, width: 50, height: 50 },
{ left: 100, top: 0, width: 50, height: 50 },
);
// 50pipe(
{ left: 0, top: 0, width: 50, height: 50 },
Rect.distance({ left: 100, top: 0, width: 50, height: 50 }),
);
// 50function Rect.dropBottomPct(rect: Rect, amount: number): RectRemoves a percentage of the rectangle's height from the bottom edge. The amount should be between 0 and 1.
Rect.dropBottomPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 10, top: 20, width: 100, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropBottomPct(0.25));
// { left: 10, top: 20, width: 100, height: 60 }function Rect.dropBottomPx(rect: Rect, amount: number): RectRemoves a specified number of pixels from the rectangle's height at the bottom edge.
Rect.dropBottomPx({ left: 10, top: 20, width: 100, height: 80 }, 20);
// { left: 10, top: 20, width: 100, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropBottomPx(20));
// { left: 10, top: 20, width: 100, height: 60 }function Rect.dropLeftPct(rect: Rect, amount: number): RectRemoves a percentage of the rectangle's width from the left edge, moving the left position rightward. The amount should be between 0 and 1.
Rect.dropLeftPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 35, top: 20, width: 75, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropLeftPct(0.25));
// { left: 35, top: 20, width: 75, height: 80 }function Rect.dropLeftPx(rect: Rect, amount: number): RectRemoves a specified number of pixels from the rectangle's width at the left edge, moving the left position rightward.
Rect.dropLeftPx({ left: 10, top: 20, width: 100, height: 80 }, 25);
// { left: 35, top: 20, width: 75, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropLeftPx(25));
// { left: 35, top: 20, width: 75, height: 80 }function Rect.dropRightPct(rect: Rect, amount: number): RectRemoves a percentage of the rectangle's width from the right edge. The amount should be between 0 and 1.
Rect.dropRightPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 10, top: 20, width: 75, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropRightPct(0.25));
// { left: 10, top: 20, width: 75, height: 80 }function Rect.dropRightPx(rect: Rect, amount: number): RectRemoves a specified number of pixels from the rectangle's width at the right edge.
Rect.dropRightPx({ left: 10, top: 20, width: 100, height: 80 }, 25);
// { left: 10, top: 20, width: 75, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropRightPx(25));
// { left: 10, top: 20, width: 75, height: 80 }function Rect.dropTopPct(rect: Rect, amount: number): RectRemoves a percentage of the rectangle's height from the top edge, moving the top position downward. The amount should be between 0 and 1.
Rect.dropTopPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 10, top: 40, width: 100, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropTopPct(0.25));
// { left: 10, top: 40, width: 100, height: 60 }function Rect.dropTopPx(rect: Rect, amount: number): RectRemoves a specified number of pixels from the rectangle's height at the top edge, moving the top position downward.
Rect.dropTopPx({ left: 10, top: 20, width: 100, height: 80 }, 20);
// { left: 10, top: 40, width: 100, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.dropTopPx(20));
// { left: 10, top: 40, width: 100, height: 60 }function Rect.expand(rect: Rect, amount: number): RectExpands the rectangle in all directions by the specified amount.
Rect.expand({ left: 10, top: 20, width: 100, height: 50 }, 10);
// { left: 0, top: 10, width: 120, height: 70 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.expand(10));
// { left: 0, top: 10, width: 120, height: 70 }function Rect.expandX(rect: Rect, amount: number): RectExpands the rectangle horizontally by the specified amount.
Rect.expandX({ left: 10, top: 20, width: 100, height: 50 }, 10);
// { left: 0, top: 20, width: 120, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.expandX(10));
// { left: 0, top: 20, width: 120, height: 50 }function Rect.expandY(rect: Rect, amount: number): RectExpands the rectangle vertically by the specified amount.
Rect.expandY({ left: 10, top: 20, width: 100, height: 50 }, 10);
// { left: 10, top: 10, width: 100, height: 70 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.expandY(10));
// { left: 10, top: 10, width: 100, height: 70 }function Rect.fromDOMRect(rect: DOMRectReadOnly): RectConverts a DOMRectReadOnly object (from getBoundingClientRect or similar) into a Rect.
const domRect = element.getBoundingClientRect();
Rect.fromDOMRect(domRect);
// { left: 10, top: 20, width: 100, height: 50 }const domRect = element.getBoundingClientRect();
pipe(domRect, Rect.fromDOMRect());
// { left: 10, top: 20, width: 100, height: 50 }function Rect.fromEdges(edges: { bottom: number, left: number, right: number, top: number }): RectCreates a rectangle from edge coordinates.
Rect.fromEdges({ left: 10, top: 20, right: 110, bottom: 70 });
// { left: 10, top: 20, width: 100, height: 50 }pipe({ left: 10, top: 20, right: 110, bottom: 70 }, Rect.fromEdges());
// { left: 10, top: 20, width: 100, height: 50 }function Rect.fromElement(element: HTMLElement): RectCreates a rectangle from an HTML element's bounding client rectangle.
const div = document.querySelector("div");
Rect.fromElement(div);
// { left: 10, top: 20, width: 100, height: 50 }const div = document.querySelector("div");
pipe(div, Rect.fromElement());
// { left: 10, top: 20, width: 100, height: 50 }function Rect.fromWindow(): RectCreates a rectangle representing the browser window's viewport dimensions.
Rect.fromWindow();
// { left: 0, top: 0, width: 1920, height: 1080 }pipe(Rect.fromWindow());
// { left: 0, top: 0, width: 1920, height: 1080 }function Rect.height(rect: Rect): numberGets the height of a rectangle.
Rect.height({ left: 10, top: 20, width: 100, height: 50 });
// 50pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.height());
// 50function Rect.intersection(a: Rect, b: Rect): RectCalculates the intersection rectangle of two rectangles. Returns the origin rectangle if they don't intersect.
Rect.intersection(
{ left: 0, top: 0, width: 50, height: 50 },
{ left: 25, top: 25, width: 50, height: 50 },
);
// { left: 25, top: 25, width: 25, height: 25 }pipe(
{ left: 0, top: 0, width: 50, height: 50 },
Rect.intersection({ left: 25, top: 25, width: 50, height: 50 }),
);
// { left: 25, top: 25, width: 25, height: 25 }function Rect.intersects(a: Rect, b: Rect): booleanChecks if two rectangles intersect or overlap with each other.
Rect.intersects(
{ left: 0, top: 0, width: 50, height: 50 },
{ left: 25, top: 25, width: 50, height: 50 },
);
// truepipe(
{ left: 0, top: 0, width: 50, height: 50 },
Rect.intersects({ left: 25, top: 25, width: 50, height: 50 }),
);
// truefunction Rect.isEmpty(rect: Rect): booleanChecks if a rectangle is empty (has zero width or zero height).
Rect.isEmpty({ left: 10, top: 20, width: 0, height: 50 });
// truepipe({ left: 10, top: 20, width: 0, height: 50 }, Rect.isEmpty());
// truefunction Rect.isEqual(a: Rect, b: Rect): booleanChecks if two rectangles are equal by comparing their position and dimensions.
Rect.isEqual(
{ left: 10, top: 20, width: 100, height: 50 },
{ left: 10, top: 20, width: 100, height: 50 },
);
// truepipe(
{ left: 10, top: 20, width: 100, height: 50 },
Rect.isEqual({ left: 10, top: 20, width: 100, height: 50 }),
);
// truefunction Rect.isOrigin(rect: Rect): booleanChecks if a rectangle is the origin rectangle (positioned at 0,0 with zero width and height).
Rect.isOrigin({ left: 0, top: 0, width: 0, height: 0 });
// truepipe({ left: 0, top: 0, width: 0, height: 0 }, Rect.isOrigin());
// truefunction Rect.left(rect: Rect): numberGets the left x-coordinate of a rectangle.
Rect.left({ left: 10, top: 20, width: 100, height: 50 });
// 10pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.left());
// 10function Rect.map(rect: Rect, transform: (rect: Rect) => Partial<Rect>): RectApplies a transformation function to a rectangle, merging the returned partial rectangle with the original.
Rect.map({ left: 10, top: 20, width: 100, height: 50 }, (r) => ({
width: r.width * 2,
}));
// { left: 10, top: 20, width: 200, height: 50 }pipe(
{ left: 10, top: 20, width: 100, height: 50 },
Rect.map((r) => ({ width: r.width * 2 })),
);
// { left: 10, top: 20, width: 200, height: 50 }function Rect.merge(target: Rect, source: Partial<Rect>): RectMerges a partial rectangle into a target rectangle, creating a new rectangle with updated properties.
Rect.merge(
{ left: 10, top: 20, width: 100, height: 50 },
{ width: 150, height: 75 },
);
// { left: 10, top: 20, width: 150, height: 75 }pipe(
{ left: 10, top: 20, width: 100, height: 50 },
Rect.merge({ width: 150, height: 75 }),
);
// { left: 10, top: 20, width: 150, height: 75 }function Rect.moveBottomTo(rect: Rect, bottom: number): RectMoves the rectangle so its bottom edge is positioned at the specified y-coordinate.
Rect.moveBottomTo({ left: 10, top: 20, width: 100, height: 50 }, 100);
// { left: 10, top: 50, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.moveBottomTo(100));
// { left: 10, top: 50, width: 100, height: 50 }function Rect.moveLeftTo(rect: Rect, left: number): RectMoves the rectangle so its left edge is positioned at the specified x-coordinate.
Rect.moveLeftTo({ left: 10, top: 20, width: 100, height: 50 }, 50);
// { left: 50, top: 20, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.moveLeftTo(50));
// { left: 50, top: 20, width: 100, height: 50 }function Rect.moveRightTo(rect: Rect, right: number): RectMoves the rectangle so its right edge is positioned at the specified x-coordinate.
Rect.moveRightTo({ left: 10, top: 20, width: 100, height: 50 }, 150);
// { left: 50, top: 20, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.moveRightTo(150));
// { left: 50, top: 20, width: 100, height: 50 }function Rect.moveTopTo(rect: Rect, top: number): RectMoves the rectangle so its top edge is positioned at the specified y-coordinate.
Rect.moveTopTo({ left: 10, top: 20, width: 100, height: 50 }, 50);
// { left: 10, top: 50, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.moveTopTo(50));
// { left: 10, top: 50, width: 100, height: 50 }function Rect.normalize(rect: Rect): RectNormalizes a rectangle by ensuring positive width and height, adjusting position as needed if dimensions were negative.
Rect.normalize({ left: 50, top: 60, width: -30, height: -40 });
// { left: 20, top: 20, width: 30, height: 40 }pipe({ left: 50, top: 60, width: -30, height: -40 }, Rect.normalize());
// { left: 20, top: 20, width: 30, height: 40 }const Rect.origin: RectA constant representing the origin rectangle (positioned at 0,0 with zero width and height).
Rect.origin;
// { left: 0, top: 0, width: 0, height: 0 }function Rect.placeAboveBy(target: Rect, source: Rect, distance: number): RectPositions a target rectangle above a source rectangle with a specified distance between them. The target rectangle is moved so its bottom edge is positioned above the source rectangle's top edge by the given distance.
Rect.placeAboveBy(
{ left: 50, top: 100, width: 40, height: 30 },
{ left: 0, top: 60, width: 100, height: 20 },
10,
);
// { left: 50, top: 30, width: 40, height: 30 }pipe(
{ left: 50, top: 100, width: 40, height: 30 },
Rect.placeAboveBy({ left: 0, top: 60, width: 100, height: 20 }, 10),
);
// { left: 50, top: 30, width: 40, height: 30 }function Rect.placeBelowBy(target: Rect, source: Rect, distance: number): RectPositions a target rectangle below a source rectangle with a specified distance between them. The target rectangle is moved so its top edge is positioned below the source rectangle's top edge by the given distance.
Rect.placeBelowBy(
{ left: 50, top: 10, width: 40, height: 30 },
{ left: 0, top: 20, width: 100, height: 20 },
10,
);
// { left: 50, top: 30, width: 40, height: 30 }pipe(
{ left: 50, top: 10, width: 40, height: 30 },
Rect.placeBelowBy({ left: 0, top: 20, width: 100, height: 20 }, 10),
);
// { left: 50, top: 30, width: 40, height: 30 }function Rect.placeLeftOfBy(target: Rect, source: Rect, distance: number): RectPositions a target rectangle to the left of a source rectangle with a specified distance between them. The target rectangle is moved so its right edge is positioned to the left of the source rectangle's left edge by the given distance.
Rect.placeLeftOfBy(
{ left: 100, top: 50, width: 40, height: 30 },
{ left: 60, top: 20, width: 100, height: 20 },
10,
);
// { left: 10, top: 50, width: 40, height: 30 }pipe(
{ left: 100, top: 50, width: 40, height: 30 },
Rect.placeLeftOfBy({ left: 60, top: 20, width: 100, height: 20 }, 10),
);
// { left: 10, top: 50, width: 40, height: 30 }function Rect.placeRightOfBy(target: Rect, source: Rect, distance: number): RectPositions a target rectangle to the right of a source rectangle with a specified distance between them. The target rectangle is moved so its left edge is positioned to the right of the source rectangle's right edge by the given distance.
Rect.placeRightOfBy(
{ left: 10, top: 50, width: 40, height: 30 },
{ left: 20, top: 20, width: 100, height: 20 },
10,
);
// { left: 130, top: 50, width: 40, height: 30 }pipe(
{ left: 10, top: 50, width: 40, height: 30 },
Rect.placeRightOfBy({ left: 20, top: 20, width: 100, height: 20 }, 10),
);
// { left: 130, top: 50, width: 40, height: 30 }function Rect.right(rect: Rect): numberGets the right x-coordinate of a rectangle.
Rect.right({ left: 10, top: 20, width: 100, height: 50 });
// 110pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.right());
// 110function Rect.scale(rect: Rect, factor: number): RectScales the rectangle by the specified factor in both dimensions while keeping it centered at the same position.
Rect.scale({ left: 10, top: 20, width: 100, height: 50 }, 1.5);
// { left: -15, top: 7.5, width: 150, height: 75 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.scale(1.5));
// { left: -15, top: 7.5, width: 150, height: 75 }function Rect.scaleX(rect: Rect, factor: number): RectScales the rectangle horizontally by the specified factor while keeping it horizontally centered.
Rect.scaleX({ left: 10, top: 20, width: 100, height: 50 }, 1.5);
// { left: -15, top: 20, width: 150, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.scaleX(1.5));
// { left: -15, top: 20, width: 150, height: 50 }function Rect.scaleY(rect: Rect, factor: number): RectScales the rectangle vertically by the specified factor while keeping it vertically centered.
Rect.scaleY({ left: 10, top: 20, width: 100, height: 50 }, 1.5);
// { left: 10, top: 7.5, width: 100, height: 75 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.scaleY(1.5));
// { left: 10, top: 7.5, width: 100, height: 75 }function Rect.setBottom(rect: Rect, bottom: number): RectSets the bottom edge of a rectangle to a specific y-coordinate. The rectangle's height is adjusted to reach the new bottom position while keeping the top edge fixed.
Rect.setBottom({ left: 10, top: 20, width: 100, height: 50 }, 80);
// { left: 10, top: 20, width: 100, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setBottom(80));
// { left: 10, top: 20, width: 100, height: 60 }function Rect.setCenter(rect: Rect, x: number, y: number): RectSets the center point of the rectangle to the specified coordinates.
Rect.setCenter({ left: 10, top: 20, width: 100, height: 50 }, 75, 60);
// { left: 25, top: 35, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setCenter(75, 60));
// { left: 25, top: 35, width: 100, height: 50 }function Rect.setCenterX(rect: Rect, x: number): RectSets the horizontal center position of the rectangle to the specified x-coordinate.
Rect.setCenterX({ left: 10, top: 20, width: 100, height: 50 }, 75);
// { left: 25, top: 20, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setCenterX(75));
// { left: 25, top: 20, width: 100, height: 50 }function Rect.setCenterY(rect: Rect, y: number): RectSets the vertical center position of the rectangle to the specified y-coordinate.
Rect.setCenterY({ left: 10, top: 20, width: 100, height: 50 }, 60);
// { left: 10, top: 35, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setCenterY(60));
// { left: 10, top: 35, width: 100, height: 50 }function Rect.setHeight(rect: Rect, height: number): RectSets the height of the rectangle to the specified value. Negative values are clamped to 0.
Rect.setHeight({ left: 10, top: 20, width: 100, height: 50 }, 80);
// { left: 10, top: 20, width: 100, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setHeight(80));
// { left: 10, top: 20, width: 100, height: 80 }function Rect.setLeft(rect: Rect, left: number): RectSets the left edge of a rectangle to a specific x-coordinate. The rectangle's width is adjusted to maintain the right edge position while moving the left edge to the new position.
Rect.setLeft({ left: 20, top: 10, width: 100, height: 50 }, 30);
// { left: 30, top: 10, width: 90, height: 50 }pipe({ left: 20, top: 10, width: 100, height: 50 }, Rect.setLeft(30));
// { left: 30, top: 10, width: 90, height: 50 }function Rect.setRight(rect: Rect, right: number): RectSets the right edge of a rectangle to a specific x-coordinate. The rectangle's width is adjusted to reach the new right position while keeping the left edge fixed.
Rect.setRight({ left: 10, top: 20, width: 100, height: 50 }, 130);
// { left: 10, top: 20, width: 120, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setRight(130));
// { left: 10, top: 20, width: 120, height: 50 }function Rect.setTop(rect: Rect, top: number): RectSets the top edge of a rectangle to a specific y-coordinate. The rectangle's height is adjusted to maintain the bottom edge position while moving the top edge to the new position.
Rect.setTop({ left: 10, top: 20, width: 100, height: 50 }, 30);
// { left: 10, top: 30, width: 100, height: 40 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setTop(30));
// { left: 10, top: 30, width: 100, height: 40 }function Rect.setWidth(rect: Rect, width: number): RectSets the width of the rectangle to the specified value. Negative values are clamped to 0.
Rect.setWidth({ left: 10, top: 20, width: 100, height: 50 }, 150);
// { left: 10, top: 20, width: 150, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.setWidth(150));
// { left: 10, top: 20, width: 150, height: 50 }function Rect.shrink(rect: Rect, amount: number): RectShrinks a rectangle by moving all edges inward by the specified amount.
Rect.shrink({ left: 10, top: 20, width: 100, height: 60 }, 15);
// { left: 25, top: 35, width: 70, height: 30 }pipe({ left: 10, top: 20, width: 100, height: 60 }, Rect.shrink(15));
// { left: 25, top: 35, width: 70, height: 30 }function Rect.shrinkX(rect: Rect, amount: number): RectShrinks a rectangle horizontally by moving the left and right edges inward by the specified amount.
Rect.shrinkX({ left: 10, top: 20, width: 100, height: 60 }, 15);
// { left: 25, top: 20, width: 70, height: 60 }pipe({ left: 10, top: 20, width: 100, height: 60 }, Rect.shrinkX(15));
// { left: 25, top: 20, width: 70, height: 60 }function Rect.shrinkY(rect: Rect, amount: number): RectShrinks a rectangle vertically by moving the top and bottom edges inward by the specified amount.
Rect.shrinkY({ left: 10, top: 20, width: 100, height: 60 }, 10);
// { left: 10, top: 30, width: 100, height: 40 }pipe({ left: 10, top: 20, width: 100, height: 60 }, Rect.shrinkY(10));
// { left: 10, top: 30, width: 100, height: 40 }function Rect.snapAbove(target: Rect, source: Rect): RectPositions a target rectangle directly above a source rectangle with no gap between them. The target rectangle's bottom edge is aligned with the source rectangle's top edge.
Rect.snapAbove(
{ left: 50, top: 100, width: 40, height: 30 },
{ left: 0, top: 60, width: 100, height: 20 },
);
// { left: 50, top: 30, width: 40, height: 30 }pipe(
{ left: 50, top: 100, width: 40, height: 30 },
Rect.snapAbove({ left: 0, top: 60, width: 100, height: 20 }),
);
// { left: 50, top: 30, width: 40, height: 30 }function Rect.snapBelow(target: Rect, source: Rect): RectPositions a target rectangle directly below a source rectangle with no gap between them. The target rectangle's top edge is aligned with the source rectangle's top edge (same as placeBelowBy with distance 0).
Rect.snapBelow(
{ left: 50, top: 10, width: 40, height: 30 },
{ left: 0, top: 20, width: 100, height: 20 },
);
// { left: 50, top: 20, width: 40, height: 30 }pipe(
{ left: 50, top: 10, width: 40, height: 30 },
Rect.snapBelow({ left: 0, top: 20, width: 100, height: 20 }),
);
// { left: 50, top: 20, width: 40, height: 30 }function Rect.snapLeftOf(target: Rect, source: Rect): RectPositions a target rectangle directly to the left of a source rectangle with no gap between them. The target rectangle's right edge is aligned with the source rectangle's left edge.
Rect.snapLeftOf(
{ left: 100, top: 50, width: 40, height: 30 },
{ left: 60, top: 20, width: 100, height: 20 },
);
// { left: 20, top: 50, width: 40, height: 30 }pipe(
{ left: 100, top: 50, width: 40, height: 30 },
Rect.snapLeftOf({ left: 60, top: 20, width: 100, height: 20 }),
);
// { left: 20, top: 50, width: 40, height: 30 }function Rect.snapRightOf(target: Rect, source: Rect): RectPositions a target rectangle directly to the right of a source rectangle with no gap between them. The target rectangle's left edge is aligned with the source rectangle's right edge.
Rect.snapRightOf(
{ left: 10, top: 50, width: 40, height: 30 },
{ left: 20, top: 20, width: 100, height: 20 },
);
// { left: 120, top: 50, width: 40, height: 30 }pipe(
{ left: 10, top: 50, width: 40, height: 30 },
Rect.snapRightOf({ left: 20, top: 20, width: 100, height: 20 }),
);
// { left: 120, top: 50, width: 40, height: 30 }function Rect.takeBottomPct(rect: Rect, amount: number): RectTakes a percentage of the rectangle from the bottom. Returns a new rectangle that represents the bottom portion of the original rectangle, with the height calculated as a percentage (0-1) of the original height.
Rect.takeBottomPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 10, top: 80, width: 100, height: 20 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.takeBottomPct(0.25));
// { left: 10, top: 80, width: 100, height: 20 }function Rect.takeBottomPx(rect: Rect, amount: number): RectTakes a specified number of pixels from the bottom of the rectangle, creating a new rectangle that represents only the bottom portion.
Rect.takeBottomPx({ left: 10, top: 20, width: 100, height: 80 }, 30);
// { left: 10, top: 70, width: 100, height: 30 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.takeBottomPx(30));
// { left: 10, top: 70, width: 100, height: 30 }function Rect.takeLeftPct(rect: Rect, amount: number): RectTakes a percentage of the rectangle from the left. Returns a new rectangle that represents the left portion of the original rectangle, with the width calculated as a percentage (0-1) of the original width.
Rect.takeLeftPct({ left: 10, top: 20, width: 100, height: 50 }, 0.3);
// { left: 10, top: 20, width: 30, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.takeLeftPct(0.3));
// { left: 10, top: 20, width: 30, height: 50 }function Rect.takeLeftPx(rect: Rect, amount: number): RectTakes a specified number of pixels from the left side of the rectangle, creating a new rectangle that represents only the left portion.
Rect.takeLeftPx({ left: 10, top: 20, width: 100, height: 80 }, 40);
// { left: 10, top: 20, width: 40, height: 80 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.takeLeftPx(40));
// { left: 10, top: 20, width: 40, height: 80 }function Rect.takeRightPct(rect: Rect, amount: number): RectTakes a percentage of the rectangle from the right. Returns a new rectangle that represents the right portion of the original rectangle, with the width calculated as a percentage (0-1) of the original width.
Rect.takeRightPct({ left: 10, top: 20, width: 100, height: 50 }, 0.4);
// { left: 70, top: 20, width: 40, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.takeRightPct(0.4));
// { left: 70, top: 20, width: 40, height: 50 }function Rect.takeRightPx(rect: Rect, amount: number): RectTakes a specific number of pixels from the right side of the rectangle. Returns a new rectangle that represents the rightmost portion of the original rectangle with the specified pixel width.
Rect.takeRightPx({ left: 10, top: 20, width: 100, height: 50 }, 30);
// { left: 80, top: 20, width: 30, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.takeRightPx(30));
// { left: 80, top: 20, width: 30, height: 50 }function Rect.takeTopPct(rect: Rect, amount: number): RectTakes a percentage of the rectangle from the top. Returns a new rectangle that represents the top portion of the original rectangle, with the height calculated as a percentage (0-1) of the original height.
Rect.takeTopPct({ left: 10, top: 20, width: 100, height: 80 }, 0.25);
// { left: 10, top: 20, width: 100, height: 20 }pipe({ left: 10, top: 20, width: 100, height: 80 }, Rect.takeTopPct(0.25));
// { left: 10, top: 20, width: 100, height: 20 }function Rect.top(rect: Rect): numberGets the top y-coordinate of a rectangle.
Rect.top({ left: 10, top: 20, width: 100, height: 50 });
// 20pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.top());
// 20function Rect.transform(rect: Rect, transform: (value: number, key: keyof Rect, rect: Rect) => number): RectApplies a transformation function to each numeric property of the rectangle.
Rect.transform({ left: 10, top: 20, width: 100, height: 50 }, (value, key) =>
key === "left" || key === "top" ? value * 2 : value,
);
// { left: 20, top: 40, width: 100, height: 50 }pipe(
{ left: 10, top: 20, width: 100, height: 50 },
Rect.transform((value, key) =>
key === "left" || key === "top" ? value * 2 : value,
),
);
// { left: 20, top: 40, width: 100, height: 50 }function Rect.translate(rect: Rect, amount: number): RectTranslates (moves) the rectangle by the specified amount in both horizontal and vertical directions.
Rect.translate({ left: 10, top: 20, width: 100, height: 50 }, 15);
// { left: 25, top: 35, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.translate(15));
// { left: 25, top: 35, width: 100, height: 50 }function Rect.translateX(rect: Rect, amount: number): RectTranslates (moves) the rectangle horizontally by the specified amount.
Rect.translateX({ left: 10, top: 20, width: 100, height: 50 }, 15);
// { left: 25, top: 20, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.translateX(15));
// { left: 25, top: 20, width: 100, height: 50 }function Rect.translateY(rect: Rect, amount: number): RectTranslates (moves) the rectangle vertically by the specified amount.
Rect.translateY({ left: 10, top: 20, width: 100, height: 50 }, 15);
// { left: 10, top: 35, width: 100, height: 50 }pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.translateY(15));
// { left: 10, top: 35, width: 100, height: 50 }function Rect.union(a: Rect, b: Rect): RectCalculates the union of two rectangles, returning the smallest rectangle that contains both rectangles.
Rect.union(
{ left: 0, top: 0, width: 50, height: 50 },
{ left: 25, top: 25, width: 50, height: 50 },
);
// { left: 0, top: 0, width: 75, height: 75 }pipe(
{ left: 0, top: 0, width: 50, height: 50 },
Rect.union({ left: 25, top: 25, width: 50, height: 50 }),
);
// { left: 0, top: 0, width: 75, height: 75 }function Rect.width(rect: Rect): numberGets the width of a rectangle.
Rect.width({ left: 10, top: 20, width: 100, height: 50 });
// 100pipe({ left: 10, top: 20, width: 100, height: 50 }, Rect.width());
// 100