Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
6388d7e
add decimals per entity, decimals_secondary
ildar170975 Apr 23, 2025
b8f265a
add decimals per entity, decimals_secondary
ildar170975 Apr 23, 2025
4c38959
Merge branch 'dev' into decimals
ildar170975 Apr 29, 2025
545f81f
Merge branch 'dev' into decimals
ildar170975 Apr 29, 2025
b58e3bc
clarifications about a "default presentation"
ildar170975 Mar 6, 2026
67f03b2
Merge branch 'dev' into decimals
ildar170975 Mar 6, 2026
cb02955
clarification about HA number format settings
ildar170975 Mar 6, 2026
5d146ae
rename: decimals_secondary -> decimals_secondary_labels
ildar170975 Mar 6, 2026
bbdfd1c
correction for attrs
ildar170975 Mar 6, 2026
ed17f05
remark about extrema & avg
ildar170975 Mar 6, 2026
3e442e9
add decimals_primary_labels option
ildar170975 Mar 6, 2026
2e615d3
remove unused eslint directives
ildar170975 Mar 7, 2026
6b813bf
remove unused eslint directives
ildar170975 Mar 7, 2026
8edc24e
remove unused eslint directives
ildar170975 Mar 7, 2026
16ee968
restore eslint directive
ildar170975 Mar 7, 2026
6b0382b
restore eslint directivejs
ildar170975 Mar 7, 2026
8cfb6aa
use default accuracy settings
ildar170975 Mar 7, 2026
e429c5e
add locale.js
ildar170975 Mar 7, 2026
3e68e8e
remove debug code
ildar170975 Mar 7, 2026
2444866
Update README.md
ildar170975 Mar 7, 2026
8b406df
Update .eslintrc.yaml
ildar170975 Mar 8, 2026
eeb3d5c
Update .eslintrc.yaml
ildar170975 Mar 8, 2026
0613849
Update .eslintrc.yaml
ildar170975 Mar 8, 2026
afeff57
Update .eslintrc.yaml
ildar170975 Mar 8, 2026
ff11afd
do not use "?."
ildar170975 Mar 8, 2026
675853f
do not use "?."
ildar170975 Mar 8, 2026
7f86d62
do not use "?."
ildar170975 Mar 8, 2026
3880d21
linter
ildar170975 Mar 8, 2026
ed3ac08
" -> '
ildar170975 Mar 8, 2026
904ce52
linter
ildar170975 Mar 8, 2026
6eb5231
Update locale.js
ildar170975 Mar 8, 2026
b5567ac
Update locale.js
ildar170975 Mar 8, 2026
861734e
linter
ildar170975 Mar 8, 2026
1e3660c
linter
ildar170975 Mar 8, 2026
1802c3f
Update locale.js
ildar170975 Mar 8, 2026
25276c6
Update .eslintrc.yaml
ildar170975 Mar 8, 2026
28a3797
stupid lint
ildar170975 Mar 8, 2026
f6e119e
linter
ildar170975 Mar 8, 2026
5dd56fe
Update main.js
ildar170975 Mar 8, 2026
48fe639
Update main.js
ildar170975 Mar 8, 2026
4c6b350
Update main.js
ildar170975 Mar 8, 2026
3d7b886
Update main.js
ildar170975 Mar 8, 2026
8b11f33
avoid conflicts with 1349
ildar170975 Mar 9, 2026
d1b27b2
fixes for "unavailable" & "object attributes"
ildar170975 Mar 10, 2026
1b21158
do not use "?."
ildar170975 Mar 10, 2026
909e941
linter
ildar170975 Mar 10, 2026
146616d
styling
ildar170975 Mar 10, 2026
04cb992
edit a commentary
ildar170975 Mar 10, 2026
65f9a1c
correct descriptions
ildar170975 Mar 12, 2026
eb1d6b9
styling
ildar170975 Mar 12, 2026
144ade0
added description for "NumberFormat" const
ildar170975 Mar 12, 2026
972beb8
typo
ildar170975 Mar 12, 2026
d562a0c
some remark
ildar170975 Mar 12, 2026
1b344c9
Correct descriptions
ildar170975 Mar 13, 2026
affc8d4
correct descriptions
ildar170975 Mar 13, 2026
16e2c21
prettier
ildar170975 Mar 13, 2026
0cc09b0
correct descriptions
ildar170975 Mar 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ rules:
class-methods-use-this: 0
no-nested-ternary: 0
camelcase: 0
import/prefer-default-export: 0
globals:
window: true
Event: true
Expand Down
40 changes: 35 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ We recommend looking at the [Example usage section](#example-usage) to understan
| line_color | string/list | `var(--accent-color)` | v0.0.1 | Set a custom color for the graph line, provide a list of colors for multiple graph entries.
| color_thresholds | list | | v0.2.3 | Set thresholds for dynamic graph colors, see [Line color object](#line-color-object).
| color_thresholds_transition | string | `smooth` | v0.4.3 | Color threshold transition, `smooth` or `hard`.
| decimals | integer | | v0.0.9 | Specify the exact number of decimals to show for states.
| decimals | integer | | v0.0.9 | Specify the exact number of decimals to show for number values, see [Number format](#number-format).
| decimals_primary_labels | integer | | v0.14.0 | Specify the exact number of decimals to show for primary Y-axis labels, see [Number format](#number-format).
| decimals_secondary_labels | integer | | v0.14.0 | Specify the exact number of decimals to show for secondary Y-axis labels, see [Number format](#number-format).
| hour24 | boolean | `false` | v0.2.1 | Set to `true` to display times in 24-hour format.
| font_size | number | `100` | v0.0.3 | Adjust the font size of the state, as percentage of the original size.
| font_size_header | number | `14` | v0.3.1 | Adjust the font size of the header, size in pixels.
Expand Down Expand Up @@ -132,6 +134,7 @@ properties of the Entity object detailed in the following table (as per `sensor.
| color | string | | Set a custom color, overrides all other color options including thresholds.
| unit | string | | Set a custom unit of measurement, overrides `unit` set in base config (`''` value for an empty unit).
| aggregate_func | string | | Override for aggregate function used to calculate point on the graph, `avg`, `median`, `min`, `max`, `first`, `last`, `sum`.
| decimals | integer | | Override the exact number of decimals to show for number values, see [Number format](#number-format).
| show_state | boolean | | Display the current state.
| show_legend_state | boolean | false | Display the current state as part of the legend.
| show_indicator | boolean | | Display a color indicator next to the state, (only when more than two states are visible).
Expand All @@ -141,7 +144,7 @@ properties of the Entity object detailed in the following table (as per `sensor.
| show_points | boolean | | Set to false to hide the points.
| show_legend | boolean | | Set to false to turn hide from the legend.
| state_adaptive_color | boolean | | Make the color of the state adapt to the entity color.
| y_axis | string | | If 'secondary', displays using the secondary y-axis on the right.
| y_axis | string | | If 'secondary', displays using the secondary Y-axis on the right.
| fixed_value | boolean | | Set to true to graph the entity's current state as a fixed value instead of graphing its state history.
| smoothing | boolean | | Override for a flag indicating whether to make graph line smooth.

Expand Down Expand Up @@ -258,6 +261,32 @@ These buckets are converted later to single point/bar on the graph. Aggregate fu
| `delta` | v0.9.4 | Calculates difference between max and min value
| `diff` | v0.11.0 | Calculates difference between first and last value

### Number format

Options `decimals` defined "card-wide" and/or for some entity are used to set an exact number of decimals according to the following rules:
1. For state & attribute values:
- if none `decimals` option is defined - a default presentation (see a note below) is used;
- if "card-wide" `decimals` is defined - this value is used;
- if `decimals` for some entity is defined - this value is used for this entity.
2. For extrema & average values (supported for the 1st entity only):
- if none `decimals` option is defined - a default presentation is used;
- if "card-wide" `decimals` is defined - this value is used;
- if `decimals` is defined for the 1st entity - this value is used.
3. For primary Y-axis labels:
- if "card-wide" `decimals` & `decimals_primary_labels` options are not defined - a default presentation is used;
- if "card-wide" `decimals` option is defined - this value is used;
- if "card-wide" `decimals_primary_labels` option is defined - this value is used.
4. For secondary Y-axis labels:
- if "card-wide" `decimals` & `decimals_secondary_labels` options are not defined - a default presentation is used;
- if "card-wide" `decimals` option is defined - this value is used;
- if "card-wide" `decimals_secondary_labels` option is defined - this value is used.

A "default presentation" refers to a default look in HA:
1. For a state value (also for extrema & average): if accuracy settings are defined for an entity - these settings are used, otherwise some default HA settings (depend on many factors incl. a `device_class`; for template sensors - a user-defined accuracy set in jinja templates is used).
2. For an attribute value (also for extrema & average): default HA settings are used (for template sensors - a user-defined accuracy set in jinja templates is used).
3. For Y-axis labels: "maximum 2 decimals" accuracy is used.
And for all values, HA number format settings (like `xxxx.xx` or `x xxx.x` or `x,xxx.x`) are used.

### Theme variables
The following theme variables can be set in your HA theme to customize the appearance of the card.

Expand Down Expand Up @@ -396,11 +425,11 @@ color_thresholds:
color: "#c0392b"
```

#### Alternate y-axis
Have one or more series plot on a separate y-axis, which appears on the right side of the graph. This example also
#### Alternate Y-axis
Have one or more series plot on a separate Y-axis, which appears on the right side of the graph. This example also
shows turning off the line, points and legend.

![Alternate y-axis](https://user-images.githubusercontent.com/373079/60764115-63cf2780-a0c6-11e9-8b9a-97fc47161180.png)
![Alternate Y-axis](https://user-images.githubusercontent.com/373079/60764115-63cf2780-a0c6-11e9-8b9a-97fc47161180.png)

```yaml
type: custom:mini-graph-card
Expand Down Expand Up @@ -499,6 +528,7 @@ state_map:
label: Detected
```


#### Showing additional info on the card

![изображение](https://user-images.githubusercontent.com/71872483/170584118-ef826b60-dce3-42ec-a005-0f467616cd37.png)
Expand Down
182 changes: 182 additions & 0 deletions src/locale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/**
* HA Frontend number format settings
*/
const NumberFormat = Object.freeze({
language: 'language',
system: 'system',
comma_decimal: 'comma_decimal',
decimal_comma: 'decimal_comma',
quote_decimal: 'quote_decimal',
space_comma: 'space_comma',
none: 'none',
});

/* these types are used in FrontendLocaleData
Added here for a future need; now - for understaning what FrontendLocaleData is

export enum TimeZone {
local = 'local',
server = 'server',
}

export enum DateFormat {
language = 'language',
system = 'system',
DMY = 'DMY',
MDY = 'MDY',
YMD = 'YMD',
}

export enum FirstWeekday {
language = 'language',
monday = 'monday',
tuesday = 'tuesday',
wednesday = 'wednesday',
thursday = 'thursday',
friday = 'friday',
saturday = 'saturday',
sunday = 'sunday',
}
*/

/* this type is used for hass.locale
export interface FrontendLocaleData {
language: string;
number_format: NumberFormat;
time_format: TimeFormat;
date_format: DateFormat;
first_weekday: FirstWeekday;
time_zone: TimeZone;
}
*/

/**
* Returns a possible language/languages based on a number format
* @param {FrontendLocaleData} localeOptions Object containing
* a user-selected language and formatting settings
* @returns {string | string[] | undefined} Possible language/languages
*/
const numberFormatToLocale = (localeOptions) => {
switch (localeOptions.number_format) {
case NumberFormat.comma_decimal:
return ['en-US', 'en']; // Use United States with fallback to English formatting 1,234,567.89
case NumberFormat.decimal_comma:
return ['de', 'es', 'it']; // Use German with fallback to Spanish then Italian formatting 1.234.567,89
case NumberFormat.space_comma:
return ['fr', 'sv', 'cs']; // Use French with fallback to Swedish and Czech formatting 1 234 567,89
case NumberFormat.quote_decimal:
return ['de-CH']; // Use German (Switzerland) formatting 1'234'567.89
case NumberFormat.system:
return undefined;
default:
return localeOptions.language;
}
};

/**
* Generates default options for Intl.NumberFormat
* @param {string | number} num Number to format
* @param {Intl.NumberFormatOptions} options Intl.NumberFormatOptions
* that should be included in the returned options
* @returns {Intl.NumberFormatOptions} Default options for Intl.NumberFormat
*/
const getDefaultFormatOptions = (
num,
options,
) => {
const defaultOptions = {
maximumFractionDigits: 2,
...options,
};

if (typeof num !== 'string') {
return defaultOptions;
}

// Keep decimal trailing zeros if they are present in a string numeric value
if (
!options
|| (options.minimumFractionDigits === undefined
&& options.maximumFractionDigits === undefined)
) {
const digits = num.indexOf('.') > -1 ? num.split('.')[1].length : 0;
defaultOptions.minimumFractionDigits = digits;
defaultOptions.maximumFractionDigits = digits;
}

return defaultOptions;
};

/**
* Returns an array of objects containing the formatted number in parts.
* Similar to Intl.NumberFormat.prototype.formatToParts()
* @param {string | number} num Number to format
* @param {FrontendLocaleData} localeOptions Object containing
* a user-selected language and formatting settings
* @param {Intl.NumberFormatOptions} options Intl.NumberFormatOptions to use
*/
const formatNumberToParts = (
num,
localeOptions,
options,
) => {
const locale = localeOptions
? numberFormatToLocale(localeOptions)
: undefined;

// Polyfill for Number.isNaN, which is more reliable than the global isNaN()
Number.isNaN = Number.isNaN
|| function isNaN(input) {
return typeof input === 'number' && isNaN(input);
};

if (
localeOptions
&& localeOptions.number_format !== NumberFormat.none
&& !Number.isNaN(Number(num))
) {
return new Intl.NumberFormat(
locale,
getDefaultFormatOptions(num, options),
).formatToParts(Number(num));
}

if (
!Number.isNaN(Number(num))
&& num !== ''
&& localeOptions
&& localeOptions.number_format === NumberFormat.none
) {
// If NumberFormat is none, use en-US format without grouping.
return new Intl.NumberFormat(
'en-US',
getDefaultFormatOptions(num, {
...options,
useGrouping: false,
}),
).formatToParts(Number(num));
}

return [{ type: 'literal', value: num }];
};

/**
* Formats a number based on the user's preference with thousands separator(s)
* and decimal character for better legibility.
* @param {string | number} num Number to format
* @param {FrontendLocaleData} localeOptions Object containing
* a user-selected language and formatting settings
* @param {Intl.NumberFormatOptions} options Intl.NumberFormatOptions to use
* @returns {string} Formatted number
*/
const formatNumber = (
num,
localeOptions,
options,
) => formatNumberToParts(num, localeOptions, options)
.map(part => part.value)
.join('');

export {
formatNumber,
};
Loading
Loading