Skip to content

Commit

Permalink
! gradient calculation if both values are in the same color range
Browse files Browse the repository at this point in the history
+ recommended temperature colors export
!! TypeScript `lib` field updated to `es2023`
  • Loading branch information
dzek69 committed May 3, 2024
1 parent 832eaa9 commit dd85b2a
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 35 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [UNRELEASED]
(nothing yet)

## [0.0.2] - 2024-05-03
### Fixed
- gradient calculation if both values are in the same color range
### Added
- recommended temperature colors export
### Breaking
- TypeScript `lib` field updated to `es2023`

## [0.0.1] - 2024-04-25
### Added
- first version
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ezez/temperature-gradient",
"version": "0.0.1",
"version": "0.0.2",
"repository": "git@github.com:dzek69/ezez-temperature-gradient.git",
"author": "Jacek Nowacki",
"license": "MIT",
Expand Down
35 changes: 11 additions & 24 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import must from "must";

import { getColor } from "./index";

const myColors = [
{
value: -30,
color: "#0046B9",
},
{
value: 0,
color: "#00FFFF",
},
{
value: 10,
color: "#01cc01",
},
{
value: 20,
color: "#FFFF00",
},
{
value: 30,
color: "#FF4D00",
},
];
import { getColor, getCSSGradient, recommendedTemperatureColors as myColors } from "./index";

// @TODO more tests

describe("getColor", () => {
it("should return first color if value less than the range", () => {
must(getColor(myColors, -40)).equal("#0046B9");
});

it("should return last color if value greater than the range", () => {
must(getColor(myColors, 40)).equal("#FF4D00");
});
});

describe("getCSSGradient", () => {
it("must work with values from a single entry", () => {
must(getCSSGradient(myColors, 21, 25)).equal("linear-gradient(to right, #ffed00 0%, #ffa600 100%)");
});
});
59 changes: 50 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ const rgbToHex = (r: number, g: number, b: number): `#${string}` => {

type Colors = { value: number; color: `#${string}` }[];

// eslint-disable-next-line max-statements
const getColor = (colors: Colors, temperature: number) => {
/**
* Returns a hex color based on the value and the provided colors.
* @param colors
* @param value
*/
const getColor = (colors: Colors, value: number) => { // eslint-disable-line max-statements
if (colors.length === 0) {
throw new TypeError("Colors array is empty");
}
Expand All @@ -30,29 +34,29 @@ const getColor = (colors: Colors, temperature: number) => {
return colors[0]!.color;
}

if (temperature <= colors[0]!.value) {
if (value <= colors[0]!.value) {
return colors[0]!.color;
}

if (temperature >= colors.at(-1)!.value) {
if (value >= colors.at(-1)!.value) {
return colors.at(-1)!.color;
}

const exactMatch = colors.find(color => color.value === temperature);
const exactMatch = colors.find(color => color.value === value);
if (exactMatch) {
return exactMatch.color;
}

const lowerColorIdx = colors.findIndex((color, index) => {
return temperature >= color.value && temperature < colors[index + 1]!.value;
return value >= color.value && value < colors[index + 1]!.value;
});

const higherColorIdx = lowerColorIdx + 1;
const lowerColor = colors[lowerColorIdx]!;
const higherColor = colors[higherColorIdx]!;

const distance = higherColor.value - lowerColor.value;
const progress = (temperature - lowerColor.value) / distance;
const progress = (value - lowerColor.value) / distance;

const lowerColorRGB = hexToRgb(lowerColor.color);
const higherColorRGB = hexToRgb(higherColor.color);
Expand All @@ -69,8 +73,18 @@ const round = (num: number, precision = 0) => {
return Math.round(num * factor) / factor;
};

/**
* Returns a CSS gradient based on the from-to values and the provided colors.
* @param colors
* @param from
* @param to
*/
const getCSSGradient = (colors: Colors, from: number, to: number) => {
const filteredColors = colors.filter(color => color.value >= from && color.value <= to);
const fromIndex = colors.findLastIndex(color => color.value <= from);
const toIndex = colors.findIndex(color => color.value >= to) - 1;

const filteredColors = colors.slice(fromIndex, toIndex + 1);

if (filteredColors.length === 0) {
throw new TypeError("No colors in the range");
}
Expand All @@ -86,16 +100,43 @@ const getCSSGradient = (colors: Colors, from: number, to: number) => {
const gradient = filteredColors.map(color => {
const distance = lastValue - firstValue;
const progressPerc = ((color.value - firstValue) / distance) * 100;
if (progressPerc < 0) {
return "";
}

return `${color.color} ${round(progressPerc, 2)}%`;
}).join(", ");
}).filter(Boolean).join(", ");

return `linear-gradient(to right, ${gradient})`;
};

const recommendedTemperatureColors: Colors = [
{
value: -30,
color: "#0046B9",
},
{
value: 0,
color: "#00FFFF",
},
{
value: 10,
color: "#01cc01",
},
{
value: 20,
color: "#FFFF00",
},
{
value: 30,
color: "#FF4D00",
},
];

export {
getColor,
getCSSGradient,
recommendedTemperatureColors,
};

export type {
Expand Down
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<article style="width: 610px; height: 40px; background: linear-gradient(to right, #0046B9 0%, #00FFFF 50%, #01cc01 66.67%, #FFFF00 83.33%, #FF4D00 100%)"></article>
<article style="margin-left: 150px; width: 460px; height: 40px; background: linear-gradient(to right, #00a3dc 0%, #00FFFF 33.33%, #01cc01 55.56%, #FFFF00 77.78%, #FF4D00 100%)"></article>
<article style="margin-left: 150px; width: 410px; height: 40px; background: linear-gradient(to right, #00a3dc 0%, #00FFFF 37.5%, #01cc01 62.5%, #FFFF00 87.5%, #ffa600 100%)"></article>
<article style="margin-left: 520px; width: 40px; height: 40px; background: linear-gradient(to right, #ffed00 0%, #ffa600 100%)"></article>

<script>
// Generate color value for given temperature, from given colors
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"isolatedModules": true,
"jsx": "react-jsx",
"lib": [
"es2022",
"es2023",
"dom"
],
"mapRoot": null,
Expand Down

0 comments on commit dd85b2a

Please sign in to comment.