Per element style config (#136)
* Fix brightness calculation * Own longpress was actually never used... * Style per element * Delete commented out functions * Updating documentation * Little doc update * Fix doc * Linting
This commit is contained in:
parent
56a8fac0fa
commit
7f10243f63
217
README.md
217
README.md
|
@ -54,7 +54,7 @@ Lovelace Button card for your entities.
|
|||
| `hold_action` | object | optional | See [Action](#Action) | Define the type of action on hold, if undefined, nothing happens. |
|
||||
| `name` | string | optional | `Air conditioner` | Define an optional text to show below the icon |
|
||||
| `label` | string | optional | Any string that you want | Display a label below the card. See [Layouts](#layout) for more information. |
|
||||
| `label_template` | string | optional | `states['light.mylight'].attributes.brightness` | See [templates](#templates). Any javascript code which returns a string. Overrides `label` |
|
||||
| `label_template` | string | optional | | See [templates](#templates). Any javascript code which returns a string. Overrides `label` |
|
||||
| `show_name` | boolean | `true` | `true` \| `false` | Wether to show the name or not. Will pick entity_id's name by default, unless redefined in the `name` property or in any state `name` property |
|
||||
| `show_state` | boolean | `false` | `true` \| `false` | Show the state on the card. defaults to false if not set |
|
||||
| `show_icon` | boolean | `true` | `true` \| `false` | Wether to show the icon or not. Unless redefined in `icon`, uses the default entity icon from hass |
|
||||
|
@ -63,8 +63,7 @@ Lovelace Button card for your entities.
|
|||
| `show_entity_picture` | boolean | `false` | `true` \| `false` | Replace the icon by the entity picture (if any) or the custom picture (if any). Falls back to using the icon if both are undefined |
|
||||
| `entity_picture` | string | optional | Can be any of `/local/*` file or a URL | Will override the icon/the default entity_picture with your own image. Best is to use a square image. You can also define one per state |
|
||||
| `units` | string | optional | `Kb/s`, `lux`, ... | Override or define the units to display after the state of the entity. If omitted, it's using the entity's units |
|
||||
| `style` | object list | optional | `- text-transform: none` | Define a list of css attribute and their value to apply to the card |
|
||||
| `entity_picture_style` | object list | optional | `- border-radius: 50%`, `- filter: grayscale(100%)`, ... | Style applied to the entity picture |
|
||||
| `styles` | object list | optional | | See [styles](#styles) |
|
||||
| `state` | object list | optional | See [State](#State) | State to use for the color, icon and style of the button. Multiple states can be defined |
|
||||
| `confirmation` | string | optional | Free-form text | Show a confirmation popup on tap with defined text |
|
||||
| `layout` | string | optional | See [Layout](#Layout) | The layout of the button can be modified using this option |
|
||||
|
@ -89,12 +88,11 @@ Lovelace Button card for your entities.
|
|||
| `name` | string | optional | Any string, `'Alert'`, `'My little switch is on'`, ... | if `show_name` is `true`, the name to display for this state. If undefined, uses the general config `name`, and if undefined uses the entity name |
|
||||
| `icon` | string | optional | `mdi:battery` | The icon to display for this state. Defaults to the entity icon. Hide with `show_icon: false` |
|
||||
| `color` | string | `var(--primary-text-color)` | Any color, eg: `rgb(28, 128, 199)` or `blue` | The color of the icon (if `color_type: icon`) or the background (if `color_type: card`) |
|
||||
| `style` | string | optional | Any CSS style. If nothing is specified, the main style is used unless undefined. If you want to override the default style of the main part of the config, use `style: []` | Define a list of css attribute and their value to apply to the card |
|
||||
| `styles` | string | optional | | See [styles](#styles) |
|
||||
| `spin` | boolean | `false` | `true` \| `false` | Should the icon spin for this state? |
|
||||
| `entity_picture` | string | optional | Can be any of `/local/*` file or a URL | Will override the icon/the default entity_picture with your own image for this state. Best is to use a square image |
|
||||
| `entity_picture_style` | object list | optional | `- border-radius: 50%`, `- filter: grayscale(100%)`, ... | Style applied to the entity picture for this state |
|
||||
| `label` | string | optional | Any string that you want | Display a label below the card. See [Layouts](#layout) for more information. |
|
||||
| `label_template` | string | optional | `states['light.mylight'].attributes.brightness` | See [templates](#templates). Any javascript code which returns a string. Overrides `label` |
|
||||
| `label_template` | string | optional | | See [templates](#templates). Any javascript code which returns a string. Overrides `label` |
|
||||
|
||||
### Available operators
|
||||
|
||||
|
@ -109,7 +107,7 @@ The order of your elements in the `state` object matters. The first one which is
|
|||
| `>` | `12` | Current state is superior to `value` |
|
||||
| `!=` | `'normal'` | Current state is not equal (`!=` javascript) to `value` |
|
||||
| `regex` | `'^norm.*$'` | `value` regex applied to current state does match |
|
||||
| `template` | `return states['input_select.light_mode'].state === 'night_mode'` | See [here](#state-templates) for examples. `value` needs to be a javascript expression which returns a boolean. If the boolean is true, it will match this state |
|
||||
| `template` | | See [templates](#templates) for examples. `value` needs to be a javascript expression which returns a boolean. If the boolean is true, it will match this state |
|
||||
| `default` | N/A | If nothing matches, this is used |
|
||||
|
||||
### Layout
|
||||
|
@ -132,8 +130,9 @@ Multiple values are possible, see the image below for examples:
|
|||
|
||||
### Templates
|
||||
|
||||
`label_template` supports templating.
|
||||
It will be interpreted as javascript code and the code should return a value.
|
||||
`label_template` supports templating as well as `value` for `state` when `operator: template`
|
||||
* `label_template`: It will be interpreted as javascript code and the code should return a string
|
||||
* `value` for `state` when `operator: template`: It will be interpreted as javascript code and the code should return a boolean (`true` or `false`)
|
||||
|
||||
Inside the javascript code, you'll have access to those variables:
|
||||
* `entity`: The current entity object, if the entity is defined in the card
|
||||
|
@ -141,7 +140,74 @@ Inside the javascript code, you'll have access to those variables:
|
|||
* `user`: The user object (equivalent to `hass.user`)
|
||||
* `hass`: The complete `hass` object
|
||||
|
||||
See [here](#playing-with-label-templates) for some examples.
|
||||
The value shouldn't be enclosed in quotes:
|
||||
```yaml
|
||||
label_template: >
|
||||
return states['light.mylight'].attributes.brightness
|
||||
```
|
||||
or
|
||||
```yaml
|
||||
state:
|
||||
- operator: template
|
||||
value: >
|
||||
return states['input_select.light_mode'].state === 'night_mode'
|
||||
```
|
||||
|
||||
See [here](#templates-support) for some examples.
|
||||
|
||||
### Styles
|
||||
|
||||
For each element in the card, styles can be defined in 2 places:
|
||||
* in the main part of the config
|
||||
* in each state
|
||||
|
||||
Styles defined in each state are **additive** with the ones defined in the main part of the config. In the `state` part, just define the ones specific to your current state and keep the common ones in the main part of the config.
|
||||
|
||||
The `style` object members are:
|
||||
* `card`: styles for the card itself. Styles that are defined here will be applied to the whole card and it's content, unless redefined in elements below.
|
||||
* `icon`: styles for the icon
|
||||
* `entity_picture`: styles for the picture (if any)
|
||||
* `name`: styles for the name
|
||||
* `state`: styles for the state
|
||||
* `label`: styles for the label
|
||||
|
||||
```yaml
|
||||
- type: custom:button-card
|
||||
[...]
|
||||
styles:
|
||||
card:
|
||||
- xxxx: value
|
||||
icon:
|
||||
- xxxx: value
|
||||
entity_picture:
|
||||
- xxxx: value
|
||||
name:
|
||||
- xxxx: value
|
||||
state:
|
||||
- xxxx: value
|
||||
label:
|
||||
- xxxx: value
|
||||
state:
|
||||
- value: 'on'
|
||||
styles:
|
||||
card:
|
||||
- yyyy: value
|
||||
icon:
|
||||
- yyyy: value
|
||||
entity_picture:
|
||||
- yyyy: value
|
||||
name:
|
||||
- yyyy: value
|
||||
state:
|
||||
- yyyy: value
|
||||
label:
|
||||
- yyyy: value
|
||||
```
|
||||
This will render:
|
||||
* The `card` with the styles `xxxx: value` **and** `yyyy: value` applied
|
||||
* Same for all the others.
|
||||
|
||||
See [styling](#styling) for a complete example.
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -242,9 +308,10 @@ Light card with card color type, name, and automatic color:
|
|||
tap_action:
|
||||
action: more-info
|
||||
name: Home
|
||||
style:
|
||||
- font-size: 12px
|
||||
- font-weight: bold
|
||||
styles:
|
||||
card:
|
||||
- font-size: 12px
|
||||
- font-weight: bold
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -389,8 +456,9 @@ The definition order matters, the first item to match will be the one selected.
|
|||
- operator: 'default' # used if nothing matches
|
||||
color: yellow
|
||||
icon: mdi: thermometer
|
||||
style:
|
||||
- opacity: 0.5
|
||||
styles:
|
||||
card:
|
||||
- opacity: 0.5
|
||||
```
|
||||
|
||||
#### `tap_action` Navigate
|
||||
|
@ -424,8 +492,9 @@ You can make the whole button blink:
|
|||
- value: "on"
|
||||
color: red
|
||||
icon: mdi:alert
|
||||
style:
|
||||
- animation: blink 2s ease infinite
|
||||
styles:
|
||||
card:
|
||||
- animation: blink 2s ease infinite
|
||||
- operator: default
|
||||
color: green
|
||||
icon: mdi:shield-check
|
||||
|
@ -446,48 +515,54 @@ If you specify a width for the card, it has to be in `px`. All the cards without
|
|||
entity: light.test_light
|
||||
color: auto
|
||||
name: s:default h:200px
|
||||
style:
|
||||
- height: 200px
|
||||
styles:
|
||||
card:
|
||||
- height: 200px
|
||||
- type: "custom:button-card"
|
||||
entity: light.test_light
|
||||
color_type: card
|
||||
color: auto
|
||||
name: s:100% h:200px
|
||||
size: 100%
|
||||
style:
|
||||
- height: 200px
|
||||
styles:
|
||||
card:
|
||||
- height: 200px
|
||||
- type: "custom:button-card"
|
||||
entity: light.test_light
|
||||
color_type: card
|
||||
color: auto
|
||||
size: 10%
|
||||
name: s:10% h:200px
|
||||
style:
|
||||
- height: 200px
|
||||
styles:
|
||||
card:
|
||||
- height: 200px
|
||||
- type: horizontal-stack
|
||||
cards:
|
||||
- type: "custom:button-card"
|
||||
entity: light.test_light
|
||||
color: auto
|
||||
name: 60px
|
||||
style:
|
||||
- height: 60px
|
||||
- width: 60px
|
||||
styles:
|
||||
card:
|
||||
- height: 60px
|
||||
- width: 60px
|
||||
- type: "custom:button-card"
|
||||
entity: light.test_light
|
||||
color_type: card
|
||||
color: auto
|
||||
name: 80px
|
||||
style:
|
||||
- height: 80px
|
||||
- width: 30px
|
||||
styles:
|
||||
card:
|
||||
- height: 80px
|
||||
- width: 30px
|
||||
- type: "custom:button-card"
|
||||
entity: light.test_light
|
||||
color_type: card
|
||||
color: auto
|
||||
name: 300px
|
||||
style:
|
||||
- height: 300px
|
||||
styles:
|
||||
card:
|
||||
- height: 300px
|
||||
```
|
||||
### Templates Support
|
||||
|
||||
|
@ -504,8 +579,9 @@ If you specify a width for the card, it has to be in `px`. All the cards without
|
|||
return 'Brightness: ' + (bri ? bri : '0') + '%';
|
||||
show_label: true
|
||||
size: 15%
|
||||
style:
|
||||
- height: 100px
|
||||
styles:
|
||||
card:
|
||||
- height: 100px
|
||||
- type: "custom:button-card"
|
||||
color_type: icon
|
||||
entity: light.test_light
|
||||
|
@ -514,8 +590,9 @@ If you specify a width for the card, it has to be in `px`. All the cards without
|
|||
return 'Other State: ' + states['switch.skylight'].state;
|
||||
show_label: true
|
||||
show_name: false
|
||||
style:
|
||||
- height: 100px
|
||||
styles:
|
||||
card:
|
||||
- height: 100px
|
||||
```
|
||||
|
||||
#### State Templates
|
||||
|
@ -552,6 +629,76 @@ Example with `template`:
|
|||
label: Day Mode
|
||||
```
|
||||
|
||||
### Styling
|
||||
|
||||
![per-style-config](examples/per-style-config.gif)
|
||||
|
||||
```yaml
|
||||
- type: "custom:button-card"
|
||||
color_type: icon
|
||||
entity: light.test_light
|
||||
label_template: >
|
||||
var bri = states['light.test_light'].attributes.brightness;
|
||||
return 'Brightness: ' + (bri ? bri : '0') + '%';
|
||||
show_label: true
|
||||
show_state: true
|
||||
size: 10%
|
||||
styles:
|
||||
card:
|
||||
- height: 100px
|
||||
label:
|
||||
- color: gray
|
||||
- font-size: 9px
|
||||
- justify-self: start
|
||||
- padding: 0px 5px
|
||||
name:
|
||||
- text-transform: uppercase
|
||||
- letter-spacing: 0.5em
|
||||
- font-familly: cursive
|
||||
- justify-self: start
|
||||
- padding: 0px 5px
|
||||
state:
|
||||
- justify-self: start
|
||||
- font-size: 10px
|
||||
- padding: 0px 5px
|
||||
state:
|
||||
- value: 'on'
|
||||
styles:
|
||||
state:
|
||||
- color: green
|
||||
- value: 'off'
|
||||
styles:
|
||||
state:
|
||||
- color: red
|
||||
card:
|
||||
- filter: brightness(40%)
|
||||
- type: "custom:button-card"
|
||||
color_type: icon
|
||||
entity: light.test_light
|
||||
layout: icon_label
|
||||
label_template: >
|
||||
return 'Other State: ' + states['switch.skylight'].state;
|
||||
show_label: true
|
||||
show_name: false
|
||||
size: 100%
|
||||
styles:
|
||||
card:
|
||||
- height: 200px
|
||||
label:
|
||||
- font-weight: bold
|
||||
- writing-mode: vertical-rl
|
||||
- text-orientation: mixed
|
||||
state:
|
||||
- value: 'on'
|
||||
styles:
|
||||
label:
|
||||
- color: red
|
||||
- value: 'off'
|
||||
styles:
|
||||
label:
|
||||
- color: green
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
- [ciotlosm](https://github.com/ciotlosm) for the readme template and the awesome examples
|
||||
|
|
|
@ -3330,7 +3330,7 @@ function buildNameStateConcat(name, stateString) {
|
|||
function applyBrightnessToColor(color, brightness) {
|
||||
const colorObj = new TinyColor(getColorFromVariable(color));
|
||||
if (colorObj.isValid) {
|
||||
const validColor = colorObj.darken(100 - brightness).toString();
|
||||
const validColor = colorObj.mix('black', 100 - brightness).toString();
|
||||
if (validColor) return validColor;
|
||||
}
|
||||
return color;
|
||||
|
@ -3614,10 +3614,10 @@ class LongPress extends HTMLElement {
|
|||
customElements.define("long-press-button-card", LongPress);
|
||||
const getLongPress = () => {
|
||||
const body = document.body;
|
||||
if (body.querySelector("long-press")) {
|
||||
return body.querySelector("long-press");
|
||||
if (body.querySelector("long-press-button-card")) {
|
||||
return body.querySelector("long-press-button-card");
|
||||
}
|
||||
const longpress = document.createElement("long-press");
|
||||
const longpress = document.createElement("long-press-button-card");
|
||||
body.appendChild(longpress);
|
||||
return longpress;
|
||||
};
|
||||
|
@ -3955,9 +3955,7 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
shouldUpdate(changedProps) {
|
||||
const state = this.config.entity ? this.hass.states[this.config.entity] : undefined;
|
||||
const configState = this._getMatchingConfigState(state);
|
||||
const forceUpdate = this.config.show_label && (configState && configState.label_template || this.config.label_template) || this.config.state && this.config.state.find(elt => {
|
||||
return elt.operator === 'template';
|
||||
}) ? true : false;
|
||||
const forceUpdate = this.config.show_label && (configState && configState.label_template || this.config.label_template) || this.config.state && this.config.state.find(elt => elt.operator === 'template') ? true : false;
|
||||
return hasConfigOrEntityChanged(this, changedProps, forceUpdate);
|
||||
}
|
||||
_getMatchingConfigState(state) {
|
||||
|
@ -4078,39 +4076,17 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
}
|
||||
return entityPicture;
|
||||
}
|
||||
_buildStyle(state, configState) {
|
||||
let cardStyle = {};
|
||||
let styleArray;
|
||||
if (state) {
|
||||
if (configState && configState.style) {
|
||||
styleArray = configState.style;
|
||||
} else if (this.config.style) {
|
||||
styleArray = this.config.style;
|
||||
}
|
||||
} else if (this.config.style) {
|
||||
styleArray = this.config.style;
|
||||
_buildStyleGeneric(configState, styleType) {
|
||||
let style = {};
|
||||
if (this.config.styles[styleType]) {
|
||||
style = Object.assign(style, ...this.config.styles[styleType]);
|
||||
}
|
||||
if (styleArray) {
|
||||
cardStyle = Object.assign(cardStyle, ...styleArray);
|
||||
if (configState && configState.styles[styleType]) {
|
||||
let configStateStyle = {};
|
||||
configStateStyle = Object.assign(configStateStyle, ...configState.styles[styleType]);
|
||||
style = Object.assign({}, style, configStateStyle);
|
||||
}
|
||||
return cardStyle;
|
||||
}
|
||||
_buildEntityPictureStyle(state, configState) {
|
||||
let entityPictureStyle = {};
|
||||
let styleArray;
|
||||
if (state) {
|
||||
if (configState && configState.entity_picture_style) {
|
||||
styleArray = configState.entity_picture_style;
|
||||
} else if (this.config.entity_picture_style) {
|
||||
styleArray = this.config.entity_picture_style;
|
||||
}
|
||||
} else if (this.config.entity_picture_style) {
|
||||
styleArray = this.config.entity_picture_style;
|
||||
}
|
||||
if (styleArray) {
|
||||
entityPictureStyle = Object.assign(entityPictureStyle, ...styleArray);
|
||||
}
|
||||
return entityPictureStyle;
|
||||
return style;
|
||||
}
|
||||
_buildName(state, configState) {
|
||||
if (this.config.show_name === false) {
|
||||
|
@ -4215,7 +4191,7 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
const color = this._buildCssColorAttribute(state, configState);
|
||||
let buttonColor = color;
|
||||
let cardStyle = {};
|
||||
const configCardStyle = this._buildStyle(state, configState);
|
||||
const configCardStyle = this._buildStyleGeneric(configState, 'card');
|
||||
if (configCardStyle.width) {
|
||||
this.style.setProperty('flex', '0 0 auto');
|
||||
this.style.setProperty('max-width', 'fit-content');
|
||||
|
@ -4260,6 +4236,9 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
const iconTemplate = this._getIconHtml(state, configState, color);
|
||||
const itemClass = ['container', containerClass];
|
||||
const label = this._buildLabel(state, configState);
|
||||
const nameStyleFromConfig = this._buildStyleGeneric(configState, 'name');
|
||||
const stateStyleFromConfig = this._buildStyleGeneric(configState, 'state');
|
||||
const labelStyleFromConfig = this._buildStyleGeneric(configState, 'label');
|
||||
if (!iconTemplate) itemClass.push('no-icon');
|
||||
if (!name) itemClass.push('no-name');
|
||||
if (!stateString) itemClass.push('no-state');
|
||||
|
@ -4267,21 +4246,18 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
return html`
|
||||
<div class=${itemClass.join(' ')}>
|
||||
${iconTemplate ? iconTemplate : ''}
|
||||
${name ? html`<div class="name">${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state">${stateString}</div>` : ''}
|
||||
${label ? html`<div class="label">${label}</div>` : ''}
|
||||
${name ? html`<div class="name" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label ? html`<div class="label" style=${styleMap(labelStyleFromConfig)}>${label}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
_getIconHtml(state, configState, color) {
|
||||
const icon = this._buildIcon(state, configState);
|
||||
const entityPicture = this._buildEntityPicture(state, configState);
|
||||
const entityPictureStyleFromConfig = this._buildEntityPictureStyle(state, configState);
|
||||
const haIconStyle = {
|
||||
color,
|
||||
width: this.config.size,
|
||||
'min-width': this.config.size
|
||||
};
|
||||
const entityPictureStyleFromConfig = this._buildStyleGeneric(configState, 'entity_picture');
|
||||
const haIconStyleFromConfig = this._buildStyleGeneric(configState, 'icon');
|
||||
const haIconStyle = Object.assign({ color, width: this.config.size, 'min-width': this.config.size }, haIconStyleFromConfig);
|
||||
const entityPictureStyle = Object.assign({}, haIconStyle, entityPictureStyleFromConfig);
|
||||
if (icon || entityPicture) {
|
||||
return html`
|
||||
|
@ -4308,6 +4284,30 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
this.config.color_off = 'var(--paper-item-icon-color)';
|
||||
}
|
||||
this.config.color_on = 'var(--paper-item-icon-active-color)';
|
||||
/* Temporary until we deprecate style and entity_picture_style config option */
|
||||
if (!this.config.styles) {
|
||||
this.config.styles = {};
|
||||
}
|
||||
if (this.config.style && !this.config.styles.card) {
|
||||
this.config.styles.card = this.config.style;
|
||||
}
|
||||
if (this.config.entity_picture_style && !this.config.styles.entity_picture) {
|
||||
this.config.styles.entity_picture = this.config.entity_picture_style;
|
||||
}
|
||||
if (this.config.state) {
|
||||
/* eslint no-param-reassign: ["error", { "props": false }] */
|
||||
this.config.state.forEach(s => {
|
||||
if (!s.styles) {
|
||||
s.styles = {};
|
||||
}
|
||||
if (s.entity_picture_style && !s.styles.entity_picture) {
|
||||
s.styles.entity_picture = s.entity_picture_style;
|
||||
}
|
||||
if (s.style && !s.styles.card) {
|
||||
s.styles.card = s.style;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// The height of your card. Home Assistant uses this to automatically
|
||||
// distribute all cards over the available columns.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 647 KiB |
|
@ -56,7 +56,7 @@ class ButtonCard extends LitElement {
|
|||
|| this.config!.label_template)
|
||||
)
|
||||
|| this.config!.state
|
||||
&& this.config!.state.find((elt) => { return elt.operator === 'template'; })
|
||||
&& this.config!.state.find(elt => elt.operator === 'template')
|
||||
? true : false;
|
||||
return hasConfigOrEntityChanged(this, changedProps, forceUpdate);
|
||||
}
|
||||
|
@ -196,44 +196,23 @@ class ButtonCard extends LitElement {
|
|||
return entityPicture;
|
||||
}
|
||||
|
||||
private _buildStyle(
|
||||
state: HassEntity | undefined, configState: StateConfig | undefined,
|
||||
private _buildStyleGeneric(
|
||||
configState: StateConfig | undefined,
|
||||
styleType: string,
|
||||
): StyleInfo {
|
||||
let cardStyle: StyleInfo = {};
|
||||
let styleArray: CssStyleConfig[] | undefined;
|
||||
if (state) {
|
||||
if (configState && configState.style) {
|
||||
styleArray = configState.style;
|
||||
} else if (this.config!.style) {
|
||||
styleArray = this.config!.style;
|
||||
}
|
||||
} else if (this.config!.style) {
|
||||
styleArray = this.config!.style;
|
||||
let style: StyleInfo = {};
|
||||
if (this.config!.styles[styleType]) {
|
||||
style = Object.assign(style, ...this.config!.styles[styleType]);
|
||||
}
|
||||
if (styleArray) {
|
||||
cardStyle = Object.assign(cardStyle, ...styleArray);
|
||||
if (configState && configState.styles[styleType]) {
|
||||
let configStateStyle: StyleInfo = {};
|
||||
configStateStyle = Object.assign(configStateStyle, ...configState.styles[styleType]);
|
||||
style = {
|
||||
...style,
|
||||
...configStateStyle,
|
||||
};
|
||||
}
|
||||
return cardStyle;
|
||||
}
|
||||
|
||||
private _buildEntityPictureStyle(
|
||||
state: HassEntity | undefined, configState: StateConfig | undefined,
|
||||
): StyleInfo {
|
||||
let entityPictureStyle: StyleInfo = {};
|
||||
let styleArray: CssStyleConfig[] | undefined;
|
||||
if (state) {
|
||||
if (configState && configState.entity_picture_style) {
|
||||
styleArray = configState.entity_picture_style;
|
||||
} else if (this.config!.entity_picture_style) {
|
||||
styleArray = this.config!.entity_picture_style;
|
||||
}
|
||||
} else if (this.config!.entity_picture_style) {
|
||||
styleArray = this.config!.entity_picture_style;
|
||||
}
|
||||
if (styleArray) {
|
||||
entityPictureStyle = Object.assign(entityPictureStyle, ...styleArray);
|
||||
}
|
||||
return entityPictureStyle;
|
||||
return style;
|
||||
}
|
||||
|
||||
private _buildName(
|
||||
|
@ -361,7 +340,7 @@ class ButtonCard extends LitElement {
|
|||
const color = this._buildCssColorAttribute(state, configState);
|
||||
let buttonColor = color;
|
||||
let cardStyle: StyleInfo = {};
|
||||
const configCardStyle = this._buildStyle(state, configState);
|
||||
const configCardStyle = this._buildStyleGeneric(configState, 'card');
|
||||
|
||||
if (configCardStyle.width) {
|
||||
this.style.setProperty('flex', '0 0 auto');
|
||||
|
@ -423,6 +402,9 @@ class ButtonCard extends LitElement {
|
|||
const iconTemplate = this._getIconHtml(state, configState, color);
|
||||
const itemClass: string[] = ['container', containerClass];
|
||||
const label = this._buildLabel(state, configState);
|
||||
const nameStyleFromConfig = this._buildStyleGeneric(configState, 'name');
|
||||
const stateStyleFromConfig = this._buildStyleGeneric(configState, 'state');
|
||||
const labelStyleFromConfig = this._buildStyleGeneric(configState, 'label');
|
||||
if (!iconTemplate) itemClass.push('no-icon');
|
||||
if (!name) itemClass.push('no-name');
|
||||
if (!stateString) itemClass.push('no-state');
|
||||
|
@ -431,9 +413,9 @@ class ButtonCard extends LitElement {
|
|||
return html`
|
||||
<div class=${itemClass.join(' ')}>
|
||||
${iconTemplate ? iconTemplate : ''}
|
||||
${name ? html`<div class="name">${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state">${stateString}</div>` : ''}
|
||||
${label ? html`<div class="label">${label}</div>` : ''}
|
||||
${name ? html`<div class="name" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label ? html`<div class="label" style=${styleMap(labelStyleFromConfig)}>${label}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -445,12 +427,14 @@ class ButtonCard extends LitElement {
|
|||
): TemplateResult | undefined {
|
||||
const icon = this._buildIcon(state, configState);
|
||||
const entityPicture = this._buildEntityPicture(state, configState);
|
||||
const entityPictureStyleFromConfig = this._buildEntityPictureStyle(state, configState);
|
||||
const entityPictureStyleFromConfig = this._buildStyleGeneric(configState, 'entity_picture');
|
||||
const haIconStyleFromConfig = this._buildStyleGeneric(configState, 'icon');
|
||||
|
||||
const haIconStyle = {
|
||||
color,
|
||||
width: this.config!.size,
|
||||
'min-width': this.config!.size,
|
||||
...haIconStyleFromConfig,
|
||||
};
|
||||
const entityPictureStyle = {
|
||||
...haIconStyle,
|
||||
|
@ -497,6 +481,31 @@ class ButtonCard extends LitElement {
|
|||
this.config!.color_off = 'var(--paper-item-icon-color)';
|
||||
}
|
||||
this.config!.color_on = 'var(--paper-item-icon-active-color)';
|
||||
|
||||
/* Temporary until we deprecate style and entity_picture_style config option */
|
||||
if (!this.config.styles) {
|
||||
this.config.styles = {};
|
||||
}
|
||||
if (this.config.style && !this.config.styles.card) {
|
||||
this.config.styles.card = this.config.style;
|
||||
}
|
||||
if (this.config.entity_picture_style && !this.config.styles.entity_picture) {
|
||||
this.config.styles.entity_picture = this.config.entity_picture_style;
|
||||
}
|
||||
if (this.config.state) {
|
||||
/* eslint no-param-reassign: ["error", { "props": false }] */
|
||||
this.config.state.forEach((s) => {
|
||||
if (!s.styles) {
|
||||
s.styles = {};
|
||||
}
|
||||
if (s.entity_picture_style && !s.styles.entity_picture) {
|
||||
s.styles.entity_picture = s.entity_picture_style;
|
||||
}
|
||||
if (s.style && !s.styles.card) {
|
||||
s.styles.card = s.style;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// The height of your card. Home Assistant uses this to automatically
|
||||
|
|
|
@ -51,7 +51,7 @@ export function applyBrightnessToColor(
|
|||
): string {
|
||||
const colorObj = new TinyColor(getColorFromVariable(color));
|
||||
if (colorObj.isValid) {
|
||||
const validColor = colorObj.darken(100 - brightness).toString();
|
||||
const validColor = colorObj.mix('black', 100 - brightness).toString();
|
||||
if (validColor) return validColor;
|
||||
}
|
||||
return color;
|
||||
|
|
|
@ -164,11 +164,11 @@ customElements.define("long-press-button-card", LongPress);
|
|||
|
||||
const getLongPress = (): LongPress => {
|
||||
const body = document.body;
|
||||
if (body.querySelector("long-press")) {
|
||||
return body.querySelector("long-press") as LongPress;
|
||||
if (body.querySelector("long-press-button-card")) {
|
||||
return body.querySelector("long-press-button-card") as LongPress;
|
||||
}
|
||||
|
||||
const longpress = document.createElement("long-press");
|
||||
const longpress = document.createElement("long-press-button-card");
|
||||
body.appendChild(longpress);
|
||||
|
||||
return longpress as LongPress;
|
||||
|
@ -184,4 +184,4 @@ export const longPressBind = (element: LongPressElement) => {
|
|||
|
||||
export const longPress = directive(() => (part: PropertyPart) => {
|
||||
longPressBind(part.committer.element);
|
||||
});
|
||||
});
|
||||
|
|
11
src/types.ts
11
src/types.ts
|
@ -30,6 +30,7 @@ export interface ButtonCardConfig {
|
|||
units?: string;
|
||||
style?: CssStyleConfig[];
|
||||
state?: StateConfig[];
|
||||
styles: StylesConfig;
|
||||
confirmation?: string;
|
||||
layout: Layout;
|
||||
entity_picture_style?: CssStyleConfig[];
|
||||
|
@ -57,11 +58,21 @@ export interface StateConfig {
|
|||
style?: CssStyleConfig[];
|
||||
entity_picture_style?: CssStyleConfig[];
|
||||
entity_picture?: string;
|
||||
styles: StylesConfig;
|
||||
spin?: boolean;
|
||||
label?: string;
|
||||
label_template?: string;
|
||||
}
|
||||
|
||||
export interface StylesConfig {
|
||||
card?: CssStyleConfig[];
|
||||
entity_picture?: CssStyleConfig[];
|
||||
icon?: CssStyleConfig[];
|
||||
name?: CssStyleConfig[];
|
||||
state?: CssStyleConfig[];
|
||||
label?: CssStyleConfig[];
|
||||
}
|
||||
|
||||
export interface CssStyleConfig {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue