From f1c3a9a4c92657149e2a71c251478b1e0e8d29a3 Mon Sep 17 00:00:00 2001 From: Treshank Date: Mon, 1 Sep 2025 13:22:58 +0530 Subject: [PATCH 1/5] feat: add force units. --- .../unit-conversion/src/constants/labels.ts | 11 ++++++- .../unit-conversion/src/constants/units.ts | 10 ++++-- packages/unit-conversion/src/index.ts | 1 + packages/unit-conversion/src/utils/common.ts | 1 + .../src/utils/conversion-factors.ts | 28 ++++++++++++++++ .../unit-conversion/tests/conversion.spec.ts | 33 +++++++++++++++++-- 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/packages/unit-conversion/src/constants/labels.ts b/packages/unit-conversion/src/constants/labels.ts index 3fa5133..6422d15 100644 --- a/packages/unit-conversion/src/constants/labels.ts +++ b/packages/unit-conversion/src/constants/labels.ts @@ -112,11 +112,20 @@ export const LABELS = { fahrenheit: "°F", rankine: "°R", delisle: "°De", - newton: "°N", + "newton-degree": "°N", réaumur: "°Ré", rømer: "°Rø", // luminous intensity candela: "cd", stilb: "sb", + + // Force + newton: "N", + dyne: "dyn", + poundal: "pdl", + "pound-force": "lbf", + "kilogram-force": "kgf", + + } as const; diff --git a/packages/unit-conversion/src/constants/units.ts b/packages/unit-conversion/src/constants/units.ts index 163c333..8c024bb 100644 --- a/packages/unit-conversion/src/constants/units.ts +++ b/packages/unit-conversion/src/constants/units.ts @@ -20,7 +20,9 @@ export type TimeUnits = "millisecond" | "second" | "minute" | "hour" | "day" | " export type NumberUnits = "binary" | "decimal" | "hexadecimal" | "base8"; -export type AllUnits = TemperatureUnits | LengthUnits | WeightUnits | VolumeUnits | TimeUnits | NumberUnits; +export type ForceUnits = "newton" | "dyne" | "pound-force" | "kilogram-force" | "poundal"; + +export type AllUnits = TemperatureUnits | LengthUnits | WeightUnits | VolumeUnits | TimeUnits | NumberUnits | ForceUnits; export type UnitCategory = T extends TemperatureUnits ? TemperatureUnits @@ -34,7 +36,9 @@ export type UnitCategory = T extends TemperatureUnits ? TimeUnits : T extends NumberUnits ? NumberUnits - : never; + : T extends ForceUnits + ? ForceUnits + : never; export type ALL_UNIT_CATEGORIES = { temperature: TemperatureUnits[]; @@ -43,6 +47,7 @@ export type ALL_UNIT_CATEGORIES = { volume: VolumeUnits[]; time: TimeUnits[]; number: NumberUnits[]; + force: ForceUnits[]; }; /** @@ -76,6 +81,7 @@ export const UNITS: ALL_UNIT_CATEGORIES = { ], time: ["millisecond", "second", "minute", "hour", "day", "week", "month", "year"], number: ["decimal", "binary", "hexadecimal", "base8"], + force: ["newton", "dyne", "pound-force", "kilogram-force", "poundal"], }; export const NO_UNITS_CATEGORIES = ["number"]; diff --git a/packages/unit-conversion/src/index.ts b/packages/unit-conversion/src/index.ts index d0f7de0..475816a 100644 --- a/packages/unit-conversion/src/index.ts +++ b/packages/unit-conversion/src/index.ts @@ -10,6 +10,7 @@ export type { UnitCategory, VolumeUnits, WeightUnits, + ForceUnits } from "./constants/units"; export { UNITS } from "./constants/units"; export { Conversion } from "./main"; diff --git a/packages/unit-conversion/src/utils/common.ts b/packages/unit-conversion/src/utils/common.ts index f88af85..7e88490 100644 --- a/packages/unit-conversion/src/utils/common.ts +++ b/packages/unit-conversion/src/utils/common.ts @@ -27,6 +27,7 @@ export function getUnitCategory(unit: AllUnits): keyof typeof CONVERSION_FACTORS if (isUnitInCategory(unit, "volume")) return "volume"; if (isUnitInCategory(unit, "time")) return "time"; if (isUnitInCategory(unit, "number")) return "number"; + if (isUnitInCategory(unit, "force")) return "force"; throw new Error(`Unknown unit: ${unit}`); } diff --git a/packages/unit-conversion/src/utils/conversion-factors.ts b/packages/unit-conversion/src/utils/conversion-factors.ts index fdee717..71c3995 100644 --- a/packages/unit-conversion/src/utils/conversion-factors.ts +++ b/packages/unit-conversion/src/utils/conversion-factors.ts @@ -51,6 +51,7 @@ interface ConversionFactorGroups { * @property {Object} weight - Weight conversions with gram as base unit * @property {Object} volume - Volume conversions with liter as base unit * @property {Object} time - Time conversions with second as base unit + * @property {Object} force - Force conversions with Newton as base unit */ export const CONVERSION_FACTORS: ConversionFactorGroups = { // Temperature (base: Kelvin) @@ -339,4 +340,31 @@ export const CONVERSION_FACTORS: ConversionFactorGroups = { }, }, }, + + // Force (base: newton) + force: { + newton: { + isBaseUnit: true, + toBase: (v: number) => v, + fromBase: (v: number) => v, + }, + dyne: { + toBase: (v: number) => v * 1e-5, + fromBase: (v: number) => v / 1e-5, + }, + poundal: { + toBase: (v: number) => v * 0.138255, + fromBase: (v: number) => v / 0.138255, + }, + "pound-force": { + toBase: (v: number) => v * 4.44822, + fromBase: (v: number) => v / 4.44822, + }, + "kilogram-force": { + toBase: (v: number) => v / 0.1019716213, + fromBase: (v: number) => v * 0.1019716213, + }, + }, + + }; diff --git a/packages/unit-conversion/tests/conversion.spec.ts b/packages/unit-conversion/tests/conversion.spec.ts index 1b84e06..759af16 100644 --- a/packages/unit-conversion/tests/conversion.spec.ts +++ b/packages/unit-conversion/tests/conversion.spec.ts @@ -1,6 +1,5 @@ import { describe, expect, test } from "vitest"; -import type { AllUnits } from "../src"; -import { Conversion } from "../src/main"; +import { type AllUnits, Conversion } from "../src"; type TestValues = { value: number; @@ -294,3 +293,33 @@ describe("Test number conversions", () => { }); }); }); + +describe("Test force conversions", () => { + const forceTests: Array = [ + { value: 1, from: "newton", to: "pound-force", expected: "0.2248lbf" }, + { value: 1, from: "newton", to: "kilogram-force", expected: "0.1019kgf" }, + { value: 1, from: "newton", to: "dyne", expected: "100000dyn" }, + { value: 1, from: "newton", to: "poundal", expected: "7.2330pdl" }, + { value: 1, from: "dyne", to: "newton", expected: "0.00001N" }, + { value: 1, from: "dyne", to: "pound-force", expected: "0lbf" }, + { value: 1, from: "dyne", to: "kilogram-force", expected: "0kgf" }, + { value: 1, from: "dyne", to: "poundal", expected: "0.0001pdl" }, + { value: 1, from: "poundal", to: "newton", expected: "0.1383N" }, + { value: 1, from: "poundal", to: "dyne", expected: "13825.5dyn" }, + { value: 1, from: "poundal", to: "pound-force", expected: "0.03108lbf" }, + { value: 1, from: "poundal", to: "kilogram-force", expected: "0.01409kgf" }, + { value: 1, from: "pound-force", to: "newton", expected: "4.4482N" }, + { value: 1, from: "pound-force", to: "kilogram-force", expected: "0.4536kgf" }, + { value: 1, from: "kilogram-force", to: "newton", expected: "9.8066N" }, + { value: 1, from: "kilogram-force", to: "pound-force", expected: "2.2046lbf" }, + ]; + const convert = new Conversion({ + decimals: 4, + }); + + forceTests.forEach(({ value, from, to, expected }) => { + test(`Converts ${value} ${from} to ${to}`, () => { + expect(convert.value(value).from(from).to(to)).toBe(expected); + }); + }); +}); From b41811f805b06feddf71fd6cf9d4cfd9f9479194 Mon Sep 17 00:00:00 2001 From: Treshank Date: Thu, 11 Sep 2025 13:55:44 +0530 Subject: [PATCH 2/5] fix: post merge test format. --- .../unit-conversion/src/constants/labels.ts | 2 - .../unit-conversion/src/constants/units.ts | 8 ++-- .../unit-conversion/tests/conversion.spec.ts | 38 ++++++++++--------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/packages/unit-conversion/src/constants/labels.ts b/packages/unit-conversion/src/constants/labels.ts index 07fb603..d91fb29 100644 --- a/packages/unit-conversion/src/constants/labels.ts +++ b/packages/unit-conversion/src/constants/labels.ts @@ -126,8 +126,6 @@ export const LABELS = { "pound-force": "lbf", "kilogram-force": "kgf", - - // pressure pascal: "Pa", kilopascal: "kPa", diff --git a/packages/unit-conversion/src/constants/units.ts b/packages/unit-conversion/src/constants/units.ts index eb3dc14..bcb4c7f 100644 --- a/packages/unit-conversion/src/constants/units.ts +++ b/packages/unit-conversion/src/constants/units.ts @@ -27,7 +27,7 @@ export type EnergyUnits = | "kilowatt-hour" | "electron-volt"; export type AngleUnits = "radian" | "degree" | "gradian" | "arcminute" | "arcsecond"; - +export type ForceUnits = "newton" | "dyne" | "pound-force" | "kilogram-force" | "poundal"; export type AllUnits = | TemperatureUnits | LengthUnits @@ -37,10 +37,8 @@ export type AllUnits = | NumberUnits | PressureUnits | EnergyUnits - | AngleUnits; -export type ForceUnits = "newton" | "dyne" | "pound-force" | "kilogram-force" | "poundal"; - -export type AllUnits = TemperatureUnits | LengthUnits | WeightUnits | VolumeUnits | TimeUnits | NumberUnits | ForceUnits; + | AngleUnits + | ForceUnits; export type UnitCategory = T extends TemperatureUnits ? TemperatureUnits diff --git a/packages/unit-conversion/tests/conversion.spec.ts b/packages/unit-conversion/tests/conversion.spec.ts index fe4322b..844e33a 100644 --- a/packages/unit-conversion/tests/conversion.spec.ts +++ b/packages/unit-conversion/tests/conversion.spec.ts @@ -476,30 +476,32 @@ describe("Test energy conversions", () => { describe("Test force conversions", () => { const forceTests: Array = [ - { value: 1, from: "newton", to: "pound-force", expected: "0.2248lbf" }, - { value: 1, from: "newton", to: "kilogram-force", expected: "0.1019kgf" }, - { value: 1, from: "newton", to: "dyne", expected: "100000dyn" }, - { value: 1, from: "newton", to: "poundal", expected: "7.2330pdl" }, - { value: 1, from: "dyne", to: "newton", expected: "0.00001N" }, - { value: 1, from: "dyne", to: "pound-force", expected: "0lbf" }, - { value: 1, from: "dyne", to: "kilogram-force", expected: "0kgf" }, - { value: 1, from: "dyne", to: "poundal", expected: "0.0001pdl" }, - { value: 1, from: "poundal", to: "newton", expected: "0.1383N" }, - { value: 1, from: "poundal", to: "dyne", expected: "13825.5dyn" }, - { value: 1, from: "poundal", to: "pound-force", expected: "0.03108lbf" }, - { value: 1, from: "poundal", to: "kilogram-force", expected: "0.01409kgf" }, - { value: 1, from: "pound-force", to: "newton", expected: "4.4482N" }, - { value: 1, from: "pound-force", to: "kilogram-force", expected: "0.4536kgf" }, - { value: 1, from: "kilogram-force", to: "newton", expected: "9.8066N" }, - { value: 1, from: "kilogram-force", to: "pound-force", expected: "2.2046lbf" }, + { value: 1, from: "newton", to: "pound-force", expected: "0.2248", unit: "lbf" }, + { value: 1, from: "newton", to: "kilogram-force", expected: "0.1019", unit: "kgf" }, + { value: 1, from: "newton", to: "dyne", expected: "100000", unit: "dyn" }, + { value: 1, from: "newton", to: "poundal", expected: "7.2330", unit: "pdl" }, + { value: 1, from: "dyne", to: "newton", expected: "0.00001", unit: "N" }, + { value: 1, from: "dyne", to: "pound-force", expected: "0", unit: "lbf" }, + { value: 1, from: "dyne", to: "kilogram-force", expected: "0", unit: "kgf" }, + { value: 1, from: "dyne", to: "poundal", expected: "0.00001", unit: "pdl" }, + { value: 1, from: "poundal", to: "newton", expected: "0.1383", unit: "N" }, + { value: 1, from: "poundal", to: "dyne", expected: "13825.5", unit: "dyn" }, + { value: 1, from: "poundal", to: "pound-force", expected: "0.03108", unit: "lbf" }, + { value: 1, from: "poundal", to: "kilogram-force", expected: "0.01409", unit: "kgf" }, + { value: 1, from: "pound-force", to: "newton", expected: "4.4482", unit: "N" }, + { value: 1, from: "pound-force", to: "kilogram-force", expected: "0.4536", unit: "kgf" }, + { value: 1, from: "kilogram-force", to: "newton", expected: "9.8066", unit: "N" }, + { value: 1, from: "kilogram-force", to: "pound-force", expected: "2.2046", unit: "lbf" }, ]; const convert = new Conversion({ decimals: 4, }); - forceTests.forEach(({ value, from, to, expected }) => { + forceTests.forEach(({ value, from, to, expected, unit }) => { test(`Converts ${value} ${from} to ${to}`, () => { - expect(convert.value(value).from(from).to(to)).toBe(expected); + const result = convert.value(value).from(from).to(to); + expect(isApproximatelyEqual(+result.value, +expected)).toBe(true); + expect(result.unit).toBe(unit) }); }); }); From 427d57c91a754c1e71b5d2e79ac3f908769cca60 Mon Sep 17 00:00:00 2001 From: Treshank Date: Wed, 17 Sep 2025 00:08:19 +0530 Subject: [PATCH 3/5] feat: add documentation for force unit conversions --- .../src/content/docs/conversions/force.mdx | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 apps/docs/src/content/docs/conversions/force.mdx diff --git a/apps/docs/src/content/docs/conversions/force.mdx b/apps/docs/src/content/docs/conversions/force.mdx new file mode 100644 index 0000000..a0fbee1 --- /dev/null +++ b/apps/docs/src/content/docs/conversions/force.mdx @@ -0,0 +1,38 @@ +--- +title: "Force" +template: doc +--- + +The **force** category supports conversions between Newton, Dyne, Poundal, Pound-Force, and Kilogram-Force. + +## Supported Units + +- Newton `N` +- Dyne `dyn` +- Poundal `pdl` +- Pound-Force `lbf` +- Kilogram-Force `kgf` + +## Quick Example + +```ts +import { Conversion } from "@devhaven/unit-conversion"; + +const convert = new Conversion(); + +convert.value(10).from("newton").to("dyne"); +convert.value(5000).from("dyne").to("newton"); +``` + +## Common Conversions +### Newton ↔ Kilogram-Force +```ts +convert.value(1).from("newton").to("kilogram-force"); +convert.value(1).from("kilogram-force").to("newton"); +``` + +### Newton ↔ Pound-Force +```ts +convert.value(1).from("newton").to("pound-force"); +convert.value(1).from("pound-force").to("newton"); +``` \ No newline at end of file From f612232e5c7de842d13398f7f1149354514fc0f5 Mon Sep 17 00:00:00 2001 From: Treshank Date: Sat, 20 Sep 2025 11:08:33 +0530 Subject: [PATCH 4/5] fix: code quality checks. --- packages/unit-conversion/src/index.ts | 2 +- packages/unit-conversion/src/utils/conversion-factors.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/unit-conversion/src/index.ts b/packages/unit-conversion/src/index.ts index 475816a..30a5034 100644 --- a/packages/unit-conversion/src/index.ts +++ b/packages/unit-conversion/src/index.ts @@ -3,6 +3,7 @@ export { LABELS } from "./constants/labels"; export type { ALL_UNIT_CATEGORIES, AllUnits, + ForceUnits, LengthUnits, NumberUnits, TemperatureUnits, @@ -10,7 +11,6 @@ export type { UnitCategory, VolumeUnits, WeightUnits, - ForceUnits } from "./constants/units"; export { UNITS } from "./constants/units"; export { Conversion } from "./main"; diff --git a/packages/unit-conversion/src/utils/conversion-factors.ts b/packages/unit-conversion/src/utils/conversion-factors.ts index 562cf9b..5a80282 100644 --- a/packages/unit-conversion/src/utils/conversion-factors.ts +++ b/packages/unit-conversion/src/utils/conversion-factors.ts @@ -413,6 +413,4 @@ export const CONVERSION_FACTORS: ConversionFactorGroups = { fromBase: (v: number) => v * 0.1019716213, }, }, - - }; From 2ad68f97870ce2e7b34ea4ed1c1cfc0138fa6add Mon Sep 17 00:00:00 2001 From: Treshank Date: Sat, 20 Sep 2025 11:19:47 +0530 Subject: [PATCH 5/5] fix: add missing semicolon. --- packages/unit-conversion/tests/conversion.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/unit-conversion/tests/conversion.spec.ts b/packages/unit-conversion/tests/conversion.spec.ts index 844e33a..d13b928 100644 --- a/packages/unit-conversion/tests/conversion.spec.ts +++ b/packages/unit-conversion/tests/conversion.spec.ts @@ -501,7 +501,7 @@ describe("Test force conversions", () => { test(`Converts ${value} ${from} to ${to}`, () => { const result = convert.value(value).from(from).to(to); expect(isApproximatelyEqual(+result.value, +expected)).toBe(true); - expect(result.unit).toBe(unit) + expect(result.unit).toBe(unit); }); }); });