Skip to content

Commit

Permalink
✨ initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
astoilkov committed Nov 23, 2023
1 parent cbd99a6 commit 190e4dd
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 16 deletions.
10 changes: 10 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// core
export { default as getContentBox } from "./src/getContentBox";
export { default as getPaddingBox } from "./src/getPaddingBox";
export { default as getBorderBox } from "./src/getBorderBox";
export { default as getMarginBox } from "./src/getMarginBox";

// extra
export { default as getWindowBox } from "./src/getWindowBox";
export { default as getElementBox } from "./src/getElementBox";
export type { ElementBoxOptions } from "./src/getElementBox";
26 changes: 21 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
{
"name": "{{data.name}}",
"name": "element-box",
"version": "0.1.0",
"description": "{{data.description}}",
"description": "Work with elements dimension and position more easily",
"license": "MIT",
"repository": "astoilkov/{{data.name}}",
"repository": "astoilkov/element-box",
"funding": "https://github.com/sponsors/astoilkov",
"author": {
"name": "Antonio Stoilkov",
"email": "[email protected]",
"url": "https://astoilkov.com"
},
"keywords": [
"{{data.keywords}}"
"Element",
"HTMLElement",
"DOM",
"getBoundingClientRect()",
"rect",
"offsetWidth",
"offsetHeight",
"border",
"padding",
"margin",
"width",
"height",
"top",
"left",
"bottom",
"right"
],
"type": "module",
"exports": {
Expand All @@ -34,7 +49,8 @@
"src/*.d.ts"
],
"devDependencies": {
"@vitest/coverage-c8": "^0.33.0",
"@vitest/coverage-v8": "^0.33.0",
"jsdom": "^22.1.0",
"np": "^8.0.4",
"prettier": "^3.0.3",
"typescript": "^5.2.2",
Expand Down
55 changes: 47 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,61 @@
# `{{data.name}}`
# element-box

> {{data.description}}
> Work with elements dimension and position more easily
[![Gzipped Size](https://img.shields.io/bundlephobia/minzip/{{data.name}})](https://bundlephobia.com/result?p={{data.name}})
[![Build Status](https://img.shields.io/github/actions/workflow/status/astoilkov/{{data.name}}/main.yml?branch=main)](https://github.com/astoilkov/{{data.name}}/actions/workflows/main.yml)
[![Gzipped Size](https://img.shields.io/bundlephobia/minzip/element-box)](https://bundlephobia.com/result?p=element-box)
[![Build Status](https://img.shields.io/github/actions/workflow/status/astoilkov/element-box/main.
yml?branch=main)](https://github.com/astoilkov/element-box/actions/workflows/main.yml)

## Install

```bash
npm install {{data.name}}
npm install element-box
```

## Why

## Usage
I work with elements' dimension and position rarely enough to forget the details but often enough to frustrate me that it takes away my flow/productivity.

It's hard to recall what the difference between `clientWidth` and `offsetWidth` and does `element.getBoundingClientRect()` include the borders or not.

This library provides a friendly API that let's you think about the topic more easily while adding functions that are otherwise hard to

## API

## Alternatives
### `getContentBox(element: HTMLElement): DOMRect`

Element's dimensions without border, padding, and margin — `element.getBoundingClientRect() - border - padding`.

### `getPaddingBox(element: HTMLElement): DOMRect`

Element's dimensions with padding but without border and margin — `element.getBoundingClientRect() - border`.

### `getBorderBox(element: HTMLElement): DOMRect`

Equivalent to `element.getBoundingClientRect()`.

## Related
### `getMarginBox(element: HTMLElement): DOMRect`

Element's dimensions with padding, border, and margin — `element.getBoundingClientRect() + margin`.

### `getWindowBox(): DOMRect`

Something like `window.getBoundingClientRect()` if it existed. If you are wondering, `document.documentElement.getBoundingClientRect()` won't probably do what you want.

### `getElementBox(element: HTMLElement, options): DOMRect`

Would be easier to show you examples:
```ts
// like that:
getElementBox(element, {
includePadding: true,
includeBorder: false,
includeMargin: false
})

// or like that:
getElementBox(element, 'content-box')
getElementBox(element, 'padding-box')
getElementBox(element, 'border-box')
getElementBox(element, 'margin-box')
```
3 changes: 3 additions & 0 deletions src/getBorderBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function getBorderBox(element: Element): DOMRect {
return element.getBoundingClientRect();
}
22 changes: 22 additions & 0 deletions src/getContentBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default function getContentBox(element: Element): DOMRect {
const clientRect = element.getBoundingClientRect();
const computedStyle = getComputedStyle(element);
return new DOMRect(
clientRect.x +
Number.parseFloat(computedStyle.borderLeftWidth) +
Number.parseFloat(computedStyle.paddingLeft),
clientRect.y +
Number.parseFloat(computedStyle.borderTopWidth) +
Number.parseFloat(computedStyle.paddingTop),
clientRect.width -
Number.parseFloat(computedStyle.borderLeftWidth) -
Number.parseFloat(computedStyle.borderRightWidth) -
Number.parseFloat(computedStyle.paddingLeft) -
Number.parseFloat(computedStyle.paddingRight),
clientRect.height -
Number.parseFloat(computedStyle.borderTopWidth) -
Number.parseFloat(computedStyle.borderBottomWidth) -
Number.parseFloat(computedStyle.paddingTop) -
Number.parseFloat(computedStyle.paddingBottom),
);
}
68 changes: 68 additions & 0 deletions src/getElementBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import getMarginBox from "./getMarginBox";
import getBorderBox from "./getBorderBox";
import getPaddingBox from "./getPaddingBox";
import getContentBox from "./getContentBox";

export type ElementBoxOptions =
| "content-box"
| {
includeMargin: false;
includeBorder: false;
includePadding: false;
}
| "padding-box"
| {
includeMargin: false;
includeBorder: false;
includePadding: true;
}
| "border-box" // (what getBoundingClientRect() returns)
| {
includeMargin: false;
includeBorder: true;
includePadding: true;
}
| "margin-box"
| {
includeMargin: true;
includeBorder: true;
includePadding: true;
};

export default function getElementBox(
element: Element,
options: ElementBoxOptions = "border-box",
) {
const boxType =
typeof options === "string"
? options
: options.includeMargin === false &&
options.includeBorder === false &&
options.includePadding === false
? "content-box"
: options.includeMargin === false &&
options.includeBorder === false &&
options.includePadding === true
? "padding-box"
: options.includeMargin === false &&
options.includeBorder === true &&
options.includePadding === true
? "border-box"
: options.includeMargin === true &&
options.includeBorder === true &&
options.includePadding === true
? "margin-box"
: "border-box";

if (boxType === "content-box") {
return getContentBox(element);
} else if (boxType === "padding-box") {
return getPaddingBox(element);
} else if (boxType === "border-box") {
return getBorderBox(element);
} else if (boxType === "margin-box") {
return getMarginBox(element);
}

return getBorderBox(element);
}
14 changes: 14 additions & 0 deletions src/getMarginBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function getMarginBox(element: Element): DOMRect {
const clientRect = element.getBoundingClientRect();
const computedStyle = getComputedStyle(element);
return new DOMRect(
clientRect.x - Number.parseFloat(computedStyle.marginLeft),
clientRect.y - Number.parseFloat(computedStyle.marginTop),
clientRect.width +
Number.parseFloat(computedStyle.marginLeft) +
Number.parseFloat(computedStyle.marginRight),
clientRect.height +
Number.parseFloat(computedStyle.marginTop) +
Number.parseFloat(computedStyle.marginBottom),
);
}
16 changes: 16 additions & 0 deletions src/getPaddingBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default function getPaddingBox(element: Element): DOMRect {
const clientRect = element.getBoundingClientRect();
const computedStyle = getComputedStyle(element);
return new DOMRect(
clientRect.x + Number.parseFloat(computedStyle.borderLeftWidth),
clientRect.y + Number.parseFloat(computedStyle.borderTopWidth),

clientRect.width -
Number.parseFloat(computedStyle.borderLeftWidth) -
Number.parseFloat(computedStyle.borderRightWidth),

clientRect.height -
Number.parseFloat(computedStyle.borderTopWidth) -
Number.parseFloat(computedStyle.borderBottomWidth),
);
}
3 changes: 3 additions & 0 deletions src/getWindowBox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function getWindowBox(): DOMRect {
return new DOMRect(0, 0, window.innerWidth, window.innerHeight);
}
79 changes: 76 additions & 3 deletions test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,80 @@
import { describe, expect, test } from "vitest";
import {
getBorderBox,
getContentBox,
getElementBox,
getMarginBox,
getPaddingBox,
getWindowBox,
} from "./index";

describe("{{data.name}}", () => {
test("", () => {
expect(true).toBe(true);
describe("element-box", () => {
const div = document.createElement("div");

test("getContentBox()", () => {
expect(() => getContentBox(div)).not.toThrow();
});

test("getPaddingBox()", () => {
expect(() => getPaddingBox(div)).not.toThrow();
});

test("getBorderBox()", () => {
expect(() => getBorderBox(div)).not.toThrow();
});

test("getMarginBox()", () => {
expect(() => getMarginBox(div)).not.toThrow();
});

test("getElementBox(), content-box", () => {
expect(() =>
getElementBox(div, {
includeMargin: false,
includeBorder: false,
includePadding: false,
}),
).not.toThrow();
});

test("getElementBox(), padding-box", () => {
expect(() =>
getElementBox(div, {
includeMargin: false,
includeBorder: false,
includePadding: true,
}),
).not.toThrow();
});

test("getElementBox(), border-box", () => {
expect(() =>
getElementBox(div, {
includeMargin: false,
includeBorder: true,
includePadding: true,
}),
).not.toThrow();
});

test("getElementBox(), margin-box", () => {
expect(() =>
getElementBox(div, {
includeMargin: true,
includeBorder: true,
includePadding: true,
}),
).not.toThrow();
});

test("getElementBox(), string", () => {
expect(() => getElementBox(div, "border-box")).not.toThrow();
expect(() => getElementBox(div, "content-box")).not.toThrow();
expect(() => getElementBox(div, "padding-box")).not.toThrow();
expect(() => getElementBox(div, "margin-box")).not.toThrow();
});

test("getWindowBox()", () => {
expect(() => getWindowBox()).not.toThrow();
});
});

0 comments on commit 190e4dd

Please sign in to comment.