TypeScript utility library for rectangle and point manipulation.
npm install rect-utils- RectOps: Creation, validation, and conversion operations
- RectCompare: Comparison, intersection, and containment checks
- RectTransform: Inflate, deflate, offset, and alignment transformations
- RectGeometry: Center and corner point calculations
- RectBorder: Side extraction, cutting, and expansion operations
- RectSplit: Horizontal and vertical splitting into cells
import {
Rectangle,
Point,
ContentAlignment,
RectOps,
RectCompare,
RectTransform,
RectGeometry,
RectBorder,
RectSplit
} from 'rect-utils';
// Create rectangles
const rect: Rectangle = { x: 10, y: 20, width: 100, height: 50 };
const rect2 = RectOps.create(0, 0, 100, 100);
const rect3 = RectOps.fromPoints({ x: 50, y: 50 }, { x: 150, y: 100 });
// Calculate center
const center = RectGeometry.center(rect);
console.log(center); // { x: 60, y: 45 }
// Check intersection
const rect4 = { x: 50, y: 30, width: 80, height: 60 };
if (RectCompare.intersects(rect, rect4)) {
console.log('Rectangles intersect');
}
// Check containment
const smallRect = { x: 20, y: 25, width: 30, height: 20 };
if (RectCompare.contains(rect, smallRect)) {
console.log('rect contains smallRect');
}
// Align rectangle
const baseRect = { x: 0, y: 0, width: 200, height: 200 };
const aligned = RectTransform.align(
{ x: 0, y: 0, width: 50, height: 50 },
baseRect,
ContentAlignment.MiddleCenter
);
console.log(aligned); // { x: 75, y: 75, width: 50, height: 50 }
// Split into cells
const cells = RectSplit.horizontal(rect, 3);
console.log(cells.length); // 3
// Transform operations
const inflated = RectTransform.inflate(rect, 5, 5, 5, 5);
const deflated = RectTransform.deflate(rect, 10, 10, 10, 10);
const moved = RectTransform.offset(rect, 20, 30);
// Border operations
const topPart = RectBorder.getTopSide(rect, 10);
const withoutTop = RectBorder.cutFromTop(rect, 10);
const expanded = RectBorder.expandToBottom(rect, 20);ceiling(size)- Round up size dimensionsvalidate(rect)- Normalize rectangle with positive dimensionscreate(x1, y1, x2, y2)- Create from coordinatesfromPoints(pt1, pt2)- Create from two pointsinflateToInteger(rect)- Expand to integer boundssnap(rect, dpi, snapDpi)- Snap to pixel grid
equals(rect1, rect2, epsilon?)- Compare with toleranceisEmpty(rect, epsilon?)- Check if completely emptyisEmptySize(rect, epsilon?)- Check if size is zerointersects(rect1, rect2, epsilon?)- Check intersectioncontains(rect1, rect2, epsilon?)- Check containmentcontainsPoint(rect, point, digits?)- Check point containmentcontainsX(rect, x)- Check X coordinatecontainsY(rect, y)- Check Y coordinateintersect(rect1, rect2)- Compute intersectionunionNonEmpty(rect1, rect2)- Union ignoring emptyisEqualArray(arr1, arr2)- Compare rectangle arrays
inflate(rect, left, top, right, bottom)- Expand rectangleinflateWithMargins(rect, margins)- Expand with marginsdeflate(rect, left, top, right, bottom)- Shrink rectangledeflateWithMargins(rect, margins)- Shrink with marginsoffset(rect, x, y)- Move rectangleoffsetByPoint(rect, point)- Move by pointalign(rect, baseRect, alignment)- Align within basecalcCropping(bounds, rect)- Calculate cropping padding
center(rect)- Get center pointtopLeft(rect)- Get top-left cornertopRight(rect)- Get top-right cornerbottomLeft(rect)- Get bottom-left cornerbottomRight(rect)- Get bottom-right corner
getTopSide(rect, size)- Extract top bordergetBottomSide(rect, size)- Extract bottom bordergetLeftSide(rect, size)- Extract left bordergetRightSide(rect, size)- Extract right bordersetLeft(rect, value)- Set left boundarysetRight(rect, value)- Set right boundarycutFromTop/Bottom/Left/Right(rect, size)- Remove from sideexpandToTop/Bottom/Left/Right(rect, value)- Expand to side
horizontal(bounds, cellCount, isRightToLeft?)- Split horizontallyvertical(bounds, cellCount)- Split vertically
interface Point {
x: number;
y: number;
}
interface Rectangle {
x: number;
y: number;
width: number;
height: number;
}
interface Size {
width: number;
height: number;
}
interface Margins {
left: number;
top: number;
right: number;
bottom: number;
}
enum ContentAlignment {
TopLeft,
TopCenter,
TopRight,
MiddleLeft,
MiddleCenter,
MiddleRight,
BottomLeft,
BottomCenter,
BottomRight
}const container = { x: 0, y: 0, width: 300, height: 300 };
const rows = RectSplit.vertical(container, 3);
const grid = rows.map(row => RectSplit.horizontal(row, 3));
grid.forEach((row, i) => {
console.log(`Row ${i}:`, row);
});const panel = { x: 10, y: 10, width: 400, height: 300 };
const headerHeight = 40;
const padding = 10;
const header = RectBorder.getTopSide(panel, headerHeight);
const contentArea = RectBorder.cutFromTop(panel, headerHeight);
const content = RectTransform.deflate(contentArea, padding, padding, padding, padding);
console.log('Header:', header);
console.log('Content:', content);The library is organized into focused modules:
src/
├── types.ts # Type definitions
├── ops.ts # RectOps - creation & validation
├── compare.ts # RectCompare - comparison operations
├── transform.ts # RectTransform - transformations
├── geometry.ts # RectGeometry - geometric calculations
├── border.ts # RectBorder - border operations
├── split.ts # RectSplit - splitting operations
└── index.ts # Main entry point
Each namespace is self-contained and can be tree-shaken by modern bundlers.
For detailed architecture information, see docs/ARCHITECTURE.md.
- API Reference - Complete API documentation
- Examples - Practical usage examples
- Architecture - Project structure and design
sky3d
- GitHub: @sky3d
MIT License - see LICENSE file for details
Contributions are welcome! Please read CONTRIBUTING.md for details.
See CHANGELOG.md for release history.