diff --git a/README.md b/README.md index c375333..e9a8a33 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,10 @@ stats: - attribute: motor_speed unit: RPM subtitle: Motor Speed + - value_template: >- + {{ (states('sensor.purifier_filter_life') | float(0) / 3600) | round(1) }} + unit: hours + subtitle: Filter Life shortcuts: - name: Silent icon: 'mdi:weather-night' @@ -126,12 +130,13 @@ Here is what every option means: You can use any attribute of purifier or even any entity by `entity_id` to display by stats section: -| Name | Type | Default | Description | -| ----------- | :------: | -------- | ---------------------------------------------------- | -| `entity_id` | `string` | Optional | An entity_id with state, i.e. `sensor.purifier_aqi`. | -| `attribute` | `string` | Optional | Attribute name of the stat, i.e. `filter_left`. | -| `unit` | `string` | Optional | Unit of measure, i.e. `hours`. | -| `subtitle` | `string` | Optional | Friendly name of the stat, i.e. `Filter`. | +| Name | Type | Default | Description | +| ---------------- | :------: | -------- | ---------------------------------------------------- | +| `entity_id` | `string` | Optional | An entity_id with state, i.e. `sensor.purifier_aqi`. | +| `attribute` | `string` | Optional | Attribute name of the stat, i.e. `filter_left`. | +| `value_template` | `string` | Optional | Jinja2 template returning a value. | +| `unit` | `string` | Optional | Unit of measure, i.e. `hours`. | +| `subtitle` | `string` | Optional | Friendly name of the stat, i.e. `Filter`. | ### `shortcuts` object @@ -152,6 +157,48 @@ The card will automatically try to figure out which one of shortcuts is currentl 2. `entity`'s `percentage` attribute is equal to `shortcut`'s `percentage`. 3. `entity`'s `preset_mode` attribute is equal to `shortcut`'s `preset_mode`. +## Theming + +This card can be styled by changing the values of these CSS properties (globally or per-card via [`card-mod`][card-mod]): + +| Variable | Default value | Description | +| --------------------------- | ---------------------------------------------------------------- | ------------------------------------ | +| `--pc-background` | `var(--ha-card-background, var(--card-background-color, white))` | Background of the card | +| `--pc-primary-text-color` | `var(--primary-text-color)` | Vacuum name, stats values, etc | +| `--pc-secondary-text-color` | `var(--secondary-text-color)` | Status, stats units and titles, etc | +| `--pc-icon-color` | `var(--secondary-text-color)` | Colors of icons | +| `--pc-slider-path-color` | `var(--round-slider-path-color)` | Color of the slider path | +| `--pc-slider-bar-color` | `var(--round-slider-bar-color)` | Color of the slider bar | +| `--pc-toolbar-background` | `var(--vc-background)` | Background of the toolbar | +| `--pc-toolbar-text-color` | `var(--secondary-text-color)` | Color of the toolbar texts | +| `--pc-toolbar-icon-color` | `var(--secondary-text-color)` | Color of the toolbar icons | +| `--pc-divider-color` | `var(--entities-divider-color, var(--divider-color))` | Color of dividers | +| `--pc-spacing` | `10px` | Paddings and margins inside the card | + +### Styling via theme + +Here is an example of customization via theme. Read more in the [Frontend documentation](https://www.home-assistant.io/integrations/frontend/). + +```yaml +my-custom-theme: + pc-background: '#17A8F4' + pc-spacing: 5px +``` + +### Styling via card-mod + +You can use [`card-mod`][card-mod] to customize the card on per-card basis, like this: + +```yaml +type: 'custom:purifier-card' +style: | + ha-card { + --pc-background: #17A8F4; + --pc-spacing: 5px; + } + ... +``` + ## Animations I've added an animation for this card to make it alive: @@ -241,7 +288,7 @@ MIT © [Denys Dovhan][denysdovhan] [home-assistant]: https://www.home-assistant.io/ [hacs]: https://hacs.xyz -[preview-image]: https://user-images.githubusercontent.com/3459374/144429511-23d91a48-e296-4d68-a46c-48f3649bdcda.png +[preview-image]: https://user-images.githubusercontent.com/3459374/164275676-504d92aa-2c61-4451-ae9b-23dad113ce14.png [latest-release]: https://github.com/denysdovhan/purifier-card/releases/latest [ha-scripts]: https://www.home-assistant.io/docs/scripts/ [xiaomi-miio-favorite-levels]: https://www.home-assistant.io/integrations/xiaomi_miio/#service-xiaomi_miiofan_set_favorite_level-air-purifiers-only diff --git a/src/purifier-card.js b/src/purifier-card.js index e9591aa..cf70c03 100644 --- a/src/purifier-card.js +++ b/src/purifier-card.js @@ -1,11 +1,14 @@ -import { LitElement, html } from 'lit-element'; +import { LitElement, html, nothing } from 'lit'; import { hasConfigOrEntityChanged, fireEvent } from 'custom-card-helpers'; -import './purifier-card-editor'; +import registerTemplates from 'ha-template'; import localize from './localize'; -import styles from './styles'; +import styles from './styles.css'; import { version } from '../package.json'; import workingImg from './images/purifier-working.gif'; import standbyImg from './images/purifier-standby.png'; +import './purifier-card-editor'; + +registerTemplates(); console.info( `%c PURIFIER-CARD %c ${version} `, @@ -131,15 +134,15 @@ class PurifierCard extends LitElement { } } - handleMore() { + handleMore(entityId = this.entity.entity_id) { fireEvent( this, 'hass-more-info', { - entityId: this.entity.entity_id, + entityId, }, { - bubbles: true, + bubbles: false, composed: true, } ); @@ -178,31 +181,33 @@ class PurifierCard extends LitElement { !preset_modes || !(supported_features & SUPPORT_PRESET_MODE) ) { - return html``; + return nothing; } const selected = preset_modes.indexOf(preset_mode); return html` - - - - - ${localize(`preset_mode.${preset_mode}`) || preset_mode} - - - - ${preset_modes.map( - (item, index) => - html` this.handlePresetMode(e)} - > - ${localize(`preset_mode.${item}`) || item} - ` - )} - +
+ + + + + ${localize(`preset_mode.${preset_mode}`) || preset_mode} + + + + ${preset_modes.map( + (item, index) => + html` this.handlePresetMode(e)} + > + ${localize(`preset_mode.${item}`) || item} + ` + )} + +
`; } @@ -271,7 +276,7 @@ class PurifierCard extends LitElement { } = this.entity; if (!this.showName) { - return html``; + return nothing; } return html`
${friendly_name}
`; @@ -282,7 +287,7 @@ class PurifierCard extends LitElement { const localizedState = localize(`state.${state}`) || state; if (!this.showState) { - return html``; + return nothing; } return html` @@ -290,10 +295,10 @@ class PurifierCard extends LitElement { ${localizedState} - + `; } @@ -303,23 +308,33 @@ class PurifierCard extends LitElement { const statsList = stats || []; - return statsList.map(({ entity_id, attribute, unit, subtitle }) => { - if (!entity_id && !attribute) { - return html``; - } - - const value = entity_id - ? this.hass.states[entity_id].state - : this.entity.attributes[attribute]; + return statsList.map( + ({ entity_id, attribute, value_template, unit, subtitle }) => { + if (!entity_id && !attribute && !value_template) { + return nothing; + } + + const state = entity_id + ? this.hass.states[entity_id].state + : this.entity.attributes[attribute]; + + const value = html` + + `; - return html` -
- ${value} - ${unit} -
${subtitle}
-
- `; - }); + return html` +
+ ${value} + ${unit} +
${subtitle}
+
+ `; + } + ); } renderToolbar() { @@ -327,7 +342,7 @@ class PurifierCard extends LitElement { const { state, attributes } = this.entity; if (!this.showToolbar) { - return html``; + return nothing; } const buttons = shortcuts.map( @@ -401,7 +416,7 @@ class PurifierCard extends LitElement {
-
+
${this.renderPresetMode()}