From 3a15db2b79eb0377b244387e8895eb871e2e35d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20W?= Date: Tue, 26 Jan 2021 10:27:16 +0100 Subject: [PATCH] feat(color): Define your own `color` option for each `serie` (#7) * feat(color): Define your own `color` option for each `serie` * Missing color example type in documentation Fixes #4 --- .devcontainer/ui-lovelace.yaml | 1 + README.md | 1 + package-lock.json | 30 +++++++++++++++++++++++++++++- package.json | 2 ++ src/apex-layouts.ts | 3 +-- src/apexcharts-card.ts | 11 ++++++++++- src/const.ts | 2 +- src/types-config-ti.ts | 1 + src/types-config.ts | 1 + src/utils.ts | 16 ++++++++++++++++ 10 files changed, 63 insertions(+), 5 deletions(-) diff --git a/.devcontainer/ui-lovelace.yaml b/.devcontainer/ui-lovelace.yaml index 451adf5..5e7bea7 100644 --- a/.devcontainer/ui-lovelace.yaml +++ b/.devcontainer/ui-lovelace.yaml @@ -9,6 +9,7 @@ views: name: Sensor 1 type: area curve: straight + color: yellow - entity: sensor.random_0_1000 name: Sensor 2 type: area diff --git a/README.md b/README.md index 124bf91..52ba8a6 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ The card stricly validates all the options available (but not for the `apex_conf | ---- | :--: | :-----: | :---: | ----------- | | :white_check_mark: `entity` | string | | v1.0.0 | The `entity_id` of the sensor to display | | `name` | string | | v1.0.0 | Override the name of the entity | +| `color` | string | | NEXT_VERSION | Color of the serie. Supported formats: `yellow`, `#aabbcc`, `rgb(128, 128, 128)` or `var(--css-color-variable)` | | `type` | string | `line` | v1.0.0 | `line`, `area` or `column` are supported for now | | `curve` | string | `smooth` | v1.0.0 | `smooth` (nice curve), `straight` (direct line between points) or `stepline` (flat line until next point then straight up or down) | | `extend_to_end` | boolean | `true` | v1.0.0 | If the last data is older than the end time displayed on the graph, setting to true will extend the value until the end of the timeline. Only works for `line` and `area` types. | diff --git a/package-lock.json b/package-lock.json index 12911b0..b21b69f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,10 @@ "requires": true, "packages": { "": { - "version": "1.0.2", + "version": "1.1.0-dev.1", "license": "MIT", "dependencies": { + "@ctrl/tinycolor": "^3.3.3", "apexcharts": "^3.23.1", "custom-card-helpers": "^1.6.6", "home-assistant-js-websocket": "^5.7.0", @@ -19,6 +20,7 @@ "moment-range": "^4.0.2", "parse-duration": "^0.4.4", "spark-md5": "^3.0.1", + "tinycolor": "^0.0.1", "ts-interface-checker": "^0.1.13" }, "devDependencies": { @@ -349,6 +351,14 @@ "to-fast-properties": "^2.0.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.3.3.tgz", + "integrity": "sha512-v75yutF4BDMv9weDQVM+K5XEfjiODhugSV729pnoxtBDO61ij2CsDnQa4N4E9xGaH3/FX5ASZjnajljT2F71tA==", + "engines": { + "node": ">=10" + } + }, "node_modules/@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -10960,6 +10970,14 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" }, + "node_modules/tinycolor": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz", + "integrity": "sha1-MgtaUtg6u1l42Bo+iH1K77FaYWQ=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -11570,6 +11588,11 @@ "to-fast-properties": "^2.0.0" } }, + "@ctrl/tinycolor": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.3.3.tgz", + "integrity": "sha512-v75yutF4BDMv9weDQVM+K5XEfjiODhugSV729pnoxtBDO61ij2CsDnQa4N4E9xGaH3/FX5ASZjnajljT2F71tA==" + }, "@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -19756,6 +19779,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" }, + "tinycolor": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tinycolor/-/tinycolor-0.0.1.tgz", + "integrity": "sha1-MgtaUtg6u1l42Bo+iH1K77FaYWQ=" + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", diff --git a/package.json b/package.json index d4f60fb..7eb7655 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ }, "homepage": "https://github.com/RomRider/apexcharts-card#readme", "dependencies": { + "@ctrl/tinycolor": "^3.3.3", "apexcharts": "^3.23.1", "custom-card-helpers": "^1.6.6", "home-assistant-js-websocket": "^5.7.0", @@ -40,6 +41,7 @@ "moment-range": "^4.0.2", "parse-duration": "^0.4.4", "spark-md5": "^3.0.1", + "tinycolor": "^0.0.1", "ts-interface-checker": "^0.1.13" }, "devDependencies": { diff --git a/src/apex-layouts.ts b/src/apex-layouts.ts index a70b58c..82259b8 100644 --- a/src/apex-layouts.ts +++ b/src/apex-layouts.ts @@ -1,5 +1,5 @@ import { HomeAssistant } from 'custom-card-helpers'; -import { DEFAULT_COLORS, moment } from './const'; +import { moment } from './const'; import { ChartCardConfig } from './types'; import { computeName, computeUom, mergeDeep } from './utils'; @@ -17,7 +17,6 @@ export function getLayoutConfig(config: ChartCardConfig, hass: HomeAssistant | u show: false, }, }, - colors: DEFAULT_COLORS, grid: { strokeDashArray: 3, }, diff --git a/src/apexcharts-card.ts b/src/apexcharts-card.ts index b49ee62..4f7d71a 100644 --- a/src/apexcharts-card.ts +++ b/src/apexcharts-card.ts @@ -4,7 +4,7 @@ import { ChartCardConfig, EntityEntryCache } from './types'; import { HomeAssistant } from 'custom-card-helpers'; import localForage from 'localforage'; import * as pjson from '../package.json'; -import { computeName, computeUom, decompress, getMilli, log, mergeDeep } from './utils'; +import { computeColors, computeName, computeUom, decompress, getMilli, log, mergeDeep } from './utils'; import ApexCharts from 'apexcharts'; import { styles } from './styles'; import { HassEntity } from 'home-assistant-js-websocket'; @@ -14,6 +14,7 @@ import { createCheckers } from 'ts-interface-checker'; import { ChartCardExternalConfig } from './types-config'; import exportedTypeSuite from './types-config-ti'; import { + DEFAULT_COLORS, DEFAULT_DURATION, DEFAULT_FUNC, DEFAULT_GROUP_BY_FILL, @@ -70,6 +71,8 @@ class ChartsCard extends LitElement { private _intervalTimeout?: NodeJS.Timeout; + private _colors?: string[]; + public connectedCallback() { super.connectedCallback(); if (this._config && this._hass && !this._loaded) { @@ -156,7 +159,12 @@ class ChartsCard extends LitElement { ); if (this._config) { + this._colors = [...DEFAULT_COLORS]; this._graphs = this._config.series.map((serie, index) => { + if (serie.color) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this._colors![index] = serie.color; + } serie.extend_to_end = serie.extend_to_end !== undefined ? serie.extend_to_end : true; serie.type = serie.type || DEFAULT_SERIE_TYPE; if (!serie.group_by) { @@ -292,6 +300,7 @@ class ChartsCard extends LitElement { min: start.getTime(), max: end.getTime(), }, + colors: computeColors(this._colors), }; this._apexChart?.updateOptions(graphData, false, false); } catch (err) { diff --git a/src/const.ts b/src/const.ts index 72fa35d..d660039 100644 --- a/src/const.ts +++ b/src/const.ts @@ -11,7 +11,7 @@ export const DEFAULT_FUNC = 'raw'; export const DEFAULT_GROUP_BY_FILL = 'last'; export const DEFAULT_COLORS = [ - '#ff9800', + 'var(--accent-color)', '#3498db', '#e74c3c', '#9b59b6', diff --git a/src/types-config-ti.ts b/src/types-config-ti.ts index 04d9335..fa5c48f 100644 --- a/src/types-config-ti.ts +++ b/src/types-config-ti.ts @@ -23,6 +23,7 @@ export const ChartCardSeriesExternalConfig = t.iface([], { "entity": "string", "name": t.opt("string"), "type": t.opt(t.union(t.lit('line'), t.lit('column'), t.lit('area'))), + "color": t.opt("string"), "curve": t.opt(t.union(t.lit('smooth'), t.lit('straight'), t.lit('stepline'))), "extend_to_end": t.opt("boolean"), "unit": t.opt("string"), diff --git a/src/types-config.ts b/src/types-config.ts index 36c7c63..0310df9 100644 --- a/src/types-config.ts +++ b/src/types-config.ts @@ -18,6 +18,7 @@ export interface ChartCardSeriesExternalConfig { entity: string; name?: string; type?: 'line' | 'column' | 'area'; + color?: string; curve?: 'smooth' | 'straight' | 'stepline'; extend_to_end?: boolean; unit?: string; diff --git a/src/utils.ts b/src/utils.ts index 554fd48..dd5543f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,7 @@ import { HassEntities, HassEntity } from 'home-assistant-js-websocket'; import { compress as lzStringCompress, decompress as lzStringDecompress } from 'lz-string'; import { ChartCardConfig } from './types'; +import { TinyColor } from '@ctrl/tinycolor'; export function compress(data: unknown): string { return lzStringCompress(JSON.stringify(data)); @@ -88,3 +89,18 @@ export function computeUom( } return ''; } + +export function computeColors(colors: string[] | undefined): string[] { + if (!colors) return []; + return colors.map((color) => { + if (color[0] === '#') { + return color; + } else if (color.substring(0, 3) === 'var') { + return new TinyColor( + window.getComputedStyle(document.documentElement).getPropertyValue(color.substring(4).slice(0, -1)).trim(), + ).toHexString(); + } else { + return new TinyColor(color).toHexString(); + } + }); +}