Custom layout and refactor (#146)
* Fixes #145 * custom layout support * Some css fix * Documentation update * Doc update * Update TOC * Localization support
This commit is contained in:
parent
880e7e37e1
commit
c0f50ff675
123
README.md
123
README.md
|
@ -1,4 +1,4 @@
|
|||
# Button Card
|
||||
# Button Card <!-- omit in toc -->
|
||||
|
||||
[![GitHub Release][releases-shield]][releases]
|
||||
[![License][license-shield]](LICENSE.md)
|
||||
|
@ -13,28 +13,58 @@ Lovelace Button card for your entities.
|
|||
|
||||
![all](examples/all.gif)
|
||||
|
||||
## TOC <!-- omit in toc -->
|
||||
|
||||
- [Features](#features)
|
||||
- [Configuration](#configuration)
|
||||
- [Main Options](#main-options)
|
||||
- [Action](#action)
|
||||
- [State](#state)
|
||||
- [Available operators](#available-operators)
|
||||
- [Layout](#layout)
|
||||
- [Templates](#templates)
|
||||
- [Styles](#styles)
|
||||
- [Easy styling options](#easy-styling-options)
|
||||
- [ADVANCED styling options](#advanced-styling-options)
|
||||
- [Installation](#installation)
|
||||
- [Manual Installation](#manual-installation)
|
||||
- [Installation and tracking with `custom_updater`](#installation-and-tracking-with-custom_updater)
|
||||
- [Examples](#examples)
|
||||
- [Configuration with states](#configuration-with-states)
|
||||
- [Default behavior](#default-behavior)
|
||||
- [With Operator on state](#with-operator-on-state)
|
||||
- [`tap_action` Navigate](#tap_action-navigate)
|
||||
- [blink](#blink)
|
||||
- [Play with width, height and icon size](#play-with-width-height-and-icon-size)
|
||||
- [Templates Support](#templates-support)
|
||||
- [Playing with label templates](#playing-with-label-templates)
|
||||
- [State Templates](#state-templates)
|
||||
- [Styling](#styling)
|
||||
- [Lock](#lock)
|
||||
- [Credits](#credits)
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- works with any toggleable entity
|
||||
- 6 available actions on **tap** and/or **hold**: `none`, `toggle`, `more-info`, `navigate`, `url` and `call-service`
|
||||
- state display (optional)
|
||||
- custom color (optional), or based on light rgb value
|
||||
- custom color (optional), or based on light rgb value/temperature
|
||||
- custom state definition with customizable color, icon and style (optional)
|
||||
- [custom size of the icon, width and height](#Play-with-width-height-and-icon-size) (optional)
|
||||
- Support for [templates](#templates) in some fields
|
||||
- custom icon (optional)
|
||||
- custom css style (optional)
|
||||
- multiple [layout](#Layout) support
|
||||
- units can be redefined or hidden
|
||||
- multiple [layout](#Layout) support and [custom layout](#advanced-styling-options) support
|
||||
- units for sensors can be redefined or hidden
|
||||
- 2 color types
|
||||
- `icon` : apply color settings to the icon only
|
||||
- `card` : apply color settings to the card only
|
||||
- automatic font color if color_type is set to `card`
|
||||
- support unit of measurement
|
||||
- blank card and label card (for organization)
|
||||
- [blink](#blink) animation support
|
||||
- rotating animation support
|
||||
- confirmation popup for sensitive items (optional)
|
||||
- confirmation popup for sensitive items (optional) or [locking mecanism](#lock)
|
||||
- haptic support for the [Beta IOS App](http://home-assistant.io/ios/beta)
|
||||
- support for [custom_updater](https://github.com/custom-components/custom_updater)
|
||||
|
||||
|
@ -170,6 +200,8 @@ See [here](#templates-support) for some examples.
|
|||
|
||||
### Styles
|
||||
|
||||
#### Easy styling options
|
||||
|
||||
For each element in the card, styles can be defined in 2 places:
|
||||
* in the main part of the config
|
||||
* in each state
|
||||
|
@ -222,6 +254,85 @@ This will render:
|
|||
|
||||
See [styling](#styling) for a complete example.
|
||||
|
||||
#### ADVANCED styling options
|
||||
|
||||
For advanced styling, there are 2 other options in the `styles` config object:
|
||||
* `grid`: mainly layout for the grid
|
||||
* `img_cell`: mainly how you position your icon in it's cell
|
||||
|
||||
This is how the button is constructed (HTML elements):
|
||||
![elements in the button](examples/button-card-elements.png)
|
||||
|
||||
The `grid` element uses CSS grids to design the layout of the card:
|
||||
* `img_cell` element is going to the `grid-area: i` by default
|
||||
* `name` element is going to the `grid-area: n` by default
|
||||
* `state` element is going to the `grid-area: s` by default
|
||||
* `label` element is going to the `grid-area: l` by default
|
||||
|
||||
You can see how the default layouts are constructed [here](./src/styles.ts#L152) and inspire yourself with it. We'll not support advanced layout questions here, please use [home-assitant's community forum][forum] for that.
|
||||
|
||||
To learn more, please use Google and this [excellent guide about CSS Grids](https://css-tricks.com/snippets/css/complete-guide-grid/) :)
|
||||
|
||||
Some examples:
|
||||
* label on top:
|
||||
```yaml
|
||||
styles:
|
||||
grid:
|
||||
- grid-template-areas: '"l" "i" "n" "s"'
|
||||
- grid-template-rows: min-content 1fr min-content min-content
|
||||
- grid-template-columns: 1fr
|
||||
```
|
||||
* icon on the right side (by overloading an existing layout):
|
||||
```yaml
|
||||
- type: "custom:button-card"
|
||||
entity: sensor.sensor1
|
||||
layout: icon_state_name2nd
|
||||
show_state: true
|
||||
show_name: true
|
||||
show_label: true
|
||||
label: label
|
||||
styles:
|
||||
grid:
|
||||
- grid-template-areas: '"n i" "s i" "l i"'
|
||||
- grid-template-columns: 1fr 40%
|
||||
```
|
||||
|
||||
* Apple Homekit-like buttons:
|
||||
![apple-like-buttons](examples/apple_style.gif)
|
||||
```yaml
|
||||
- type: custom:button-card
|
||||
entity: switch.skylight
|
||||
name: <3 Apple
|
||||
icon: mdi:fire
|
||||
show_state: true
|
||||
styles:
|
||||
card:
|
||||
- width: 100px
|
||||
- height: 100px
|
||||
grid:
|
||||
- grid-template-areas: '"i" "n" "s"'
|
||||
- grid-template-columns: 1fr
|
||||
- grid-template-rows: 1fr min-content min-content
|
||||
img_cell:
|
||||
- align-self: start
|
||||
- text-align: start
|
||||
name:
|
||||
- justify-self: start
|
||||
- padding-left: 10px
|
||||
- font-weight: bold
|
||||
- text-transform: lowercase
|
||||
state:
|
||||
- justify-self: start
|
||||
- padding-left: 10px
|
||||
state:
|
||||
- value: 'off'
|
||||
styles:
|
||||
card:
|
||||
- filter: opacity(50%)
|
||||
icon:
|
||||
- filter: grayscale(100%)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### Manual Installation
|
||||
|
|
|
@ -3699,6 +3699,9 @@ const styles = css`
|
|||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
ha-card.disabled {
|
||||
pointer-events: none;
|
||||
|
@ -3718,7 +3721,7 @@ const styles = css`
|
|||
letter-spacing: normal;
|
||||
width: 100%;
|
||||
}
|
||||
div {
|
||||
.ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
@ -3792,34 +3795,36 @@ const styles = css`
|
|||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
.container {
|
||||
#container {
|
||||
display: grid;
|
||||
max-height: 100%;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
.img-cell {
|
||||
#img-cell {
|
||||
/* display: flex; */
|
||||
grid-area: i;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
ha-icon#icon, img#icon {
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
object-fit: scale;
|
||||
object-fit: contain;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.name {
|
||||
#name {
|
||||
grid-area: n;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
/* margin: auto; */
|
||||
}
|
||||
.state {
|
||||
#state {
|
||||
grid-area: s;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
|
@ -3827,211 +3832,243 @@ const styles = css`
|
|||
/* margin: auto; */
|
||||
}
|
||||
|
||||
.label {
|
||||
#label {
|
||||
grid-area: l;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.container.vertical {
|
||||
#container {
|
||||
width: 100%;
|
||||
}
|
||||
#container.vertical {
|
||||
grid-template-areas: "i" "n" "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content min-content min-content;
|
||||
}
|
||||
/* Vertical No Icon */
|
||||
.container.vertical.no-icon {
|
||||
#container.vertical.no-icon {
|
||||
grid-template-areas: "n" "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.vertical.no-icon .state {
|
||||
#container.vertical.no-icon #state {
|
||||
align-self: center;
|
||||
}
|
||||
.container.vertical.no-icon .name {
|
||||
#container.vertical.no-icon #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon .label {
|
||||
#container.vertical.no-icon #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Name */
|
||||
.container.vertical.no-icon.no-name {
|
||||
#container.vertical.no-icon.no-name {
|
||||
grid-template-areas: "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-name .state {
|
||||
#container.vertical.no-icon.no-name #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-name .label {
|
||||
#container.vertical.no-icon.no-name #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No State */
|
||||
.container.vertical.no-icon.no-state {
|
||||
#container.vertical.no-icon.no-state {
|
||||
grid-template-areas: "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-state .name {
|
||||
#container.vertical.no-icon.no-state #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-state .label {
|
||||
#container.vertical.no-icon.no-state #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Label */
|
||||
.container.vertical.no-icon.no-label {
|
||||
#container.vertical.no-icon.no-label {
|
||||
grid-template-areas: "n" "s";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label .name {
|
||||
#container.vertical.no-icon.no-label #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-label .state {
|
||||
#container.vertical.no-icon.no-label #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Label No Name */
|
||||
.container.vertical.no-icon.no-label.no-name {
|
||||
#container.vertical.no-icon.no-label.no-name {
|
||||
grid-template-areas: "s";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label.no-name .state {
|
||||
#container.vertical.no-icon.no-label.no-name #state {
|
||||
align-self: center;
|
||||
}
|
||||
/* Vertical No Icon No Label No State */
|
||||
.container.vertical.no-icon.no-label.no-state {
|
||||
#container.vertical.no-icon.no-label.no-state {
|
||||
grid-template-areas: "n";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label.no-state .name {
|
||||
#container.vertical.no-icon.no-label.no-state #name {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Name No State */
|
||||
.container.vertical.no-icon.no-name.no-state {
|
||||
#container.vertical.no-icon.no-name.no-state {
|
||||
grid-template-areas: "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-name.no-state .label {
|
||||
#container.vertical.no-icon.no-name.no-state #label {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.container.icon_name_state {
|
||||
#container.icon_name_state {
|
||||
grid-template-areas: "i n" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content;
|
||||
}
|
||||
|
||||
.container.icon_name {
|
||||
#container.icon_name {
|
||||
grid-template-areas: "i n" "s s" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
|
||||
.container.icon_state {
|
||||
#container.icon_state {
|
||||
grid-template-areas: "i s" "n n" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
|
||||
.container.name_state {
|
||||
#container.name_state {
|
||||
grid-template-areas: "i" "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
.container.name_state.no-icon {
|
||||
#container.name_state.no-icon {
|
||||
grid-template-areas: "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.name_state.no-icon .name {
|
||||
#container.name_state.no-icon #name {
|
||||
align-self: end
|
||||
}
|
||||
.container.name_state.no-icon .label {
|
||||
#container.name_state.no-icon #label {
|
||||
align-self: start
|
||||
}
|
||||
|
||||
.container.name_state.no-icon.no-label {
|
||||
#container.name_state.no-icon.no-label {
|
||||
grid-template-areas: "n";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.name_state.no-icon.no-label .name {
|
||||
#container.name_state.no-icon.no-label #name {
|
||||
align-self: center
|
||||
}
|
||||
|
||||
/* icon_name_state2nd default */
|
||||
.container.icon_name_state2nd {
|
||||
#container.icon_name_state2nd {
|
||||
grid-template-areas: "i n" "i s" "i l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.icon_name_state2nd .name {
|
||||
#container.icon_name_state2nd #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_name_state2nd .state {
|
||||
#container.icon_name_state2nd #state {
|
||||
align-self: center;
|
||||
}
|
||||
.container.icon_name_state2nd .label {
|
||||
#container.icon_name_state2nd #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_name_state2nd No Label */
|
||||
.container.icon_name_state2nd.no-label {
|
||||
#container.icon_name_state2nd.no-label {
|
||||
grid-template-areas: "i n" "i s";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.icon_name_state2nd .name {
|
||||
#container.icon_name_state2nd #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_name_state2nd .state {
|
||||
#container.icon_name_state2nd #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_state_name2nd Default */
|
||||
.container.icon_state_name2nd {
|
||||
#container.icon_state_name2nd {
|
||||
grid-template-areas: "i s" "i n" "i l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_state_name2nd .name {
|
||||
#container.icon_state_name2nd #name {
|
||||
align-self: center;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_state_name2nd No Label */
|
||||
.container.icon_state_name2nd.no-label {
|
||||
#container.icon_state_name2nd.no-label {
|
||||
grid-template-areas: "i s" "i n";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_state_name2nd .name {
|
||||
#container.icon_state_name2nd #name {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.container.icon_label {
|
||||
#container.icon_label {
|
||||
grid-template-areas: "i l" "n n" "s s";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
`;
|
||||
|
||||
var computeStateDisplay = (localize, stateObj) => {
|
||||
let display;
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
if (domain === 'binary_sensor') {
|
||||
// Try device class translation, then default binary sensor translation
|
||||
if (stateObj.attributes.device_class) {
|
||||
display = localize(`state.${domain}.${stateObj.attributes.device_class}.${stateObj.state}`);
|
||||
}
|
||||
if (!display) {
|
||||
display = localize(`state.${domain}.default.${stateObj.state}`);
|
||||
}
|
||||
} else if (stateObj.attributes.unit_of_measurement && !['unknown', 'unavailable'].includes(stateObj.state)) {
|
||||
display = stateObj.state;
|
||||
} else if (domain === 'zwave') {
|
||||
if (['initializing', 'dead'].includes(stateObj.state)) {
|
||||
display = localize(`state.zwave.query_stage.${stateObj.state}`, 'query_stage', stateObj.attributes.query_stage);
|
||||
} else {
|
||||
display = localize(`state.zwave.default.${stateObj.state}`);
|
||||
}
|
||||
} else {
|
||||
display = localize(`state.${domain}.${stateObj.state}`);
|
||||
}
|
||||
// Fall back to default, component backend translation, or raw state if nothing else matches.
|
||||
if (!display) {
|
||||
display = localize(`state.default.${stateObj.state}`) || localize(`component.${domain}.state.${stateObj.state}`) || stateObj.state;
|
||||
}
|
||||
return display;
|
||||
};
|
||||
|
||||
let ButtonCard = class ButtonCard extends LitElement {
|
||||
static get styles() {
|
||||
return styles;
|
||||
|
@ -4049,7 +4086,11 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
return hasConfigOrEntityChanged(this, changedProps, forceUpdate);
|
||||
}
|
||||
_getMatchingConfigState(state) {
|
||||
if (!state || !this.config.state) {
|
||||
if (!this.config.state) {
|
||||
return undefined;
|
||||
}
|
||||
const hasTemplate = this.config.state.find(elt => elt.operator === 'template');
|
||||
if (!state && !hasTemplate) {
|
||||
return undefined;
|
||||
}
|
||||
let def;
|
||||
|
@ -4058,21 +4099,21 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
switch (elt.operator) {
|
||||
case '==':
|
||||
/* eslint eqeqeq: 0 */
|
||||
return state.state == elt.value;
|
||||
return state && state.state == elt.value;
|
||||
case '<=':
|
||||
return state.state <= elt.value;
|
||||
return state && state.state <= elt.value;
|
||||
case '<':
|
||||
return state.state < elt.value;
|
||||
return state && state.state < elt.value;
|
||||
case '>=':
|
||||
return state.state >= elt.value;
|
||||
return state && state.state >= elt.value;
|
||||
case '>':
|
||||
return state.state > elt.value;
|
||||
return state && state.state > elt.value;
|
||||
case '!=':
|
||||
return state.state != elt.value;
|
||||
return state && state.state != elt.value;
|
||||
case 'regex':
|
||||
{
|
||||
/* eslint no-unneeded-ternary: 0 */
|
||||
const matches = state.state.match(elt.value) ? true : false;
|
||||
const matches = state && state.state.match(elt.value) ? true : false;
|
||||
return matches;
|
||||
}
|
||||
case 'template':
|
||||
|
@ -4086,7 +4127,7 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
return elt.value == state.state;
|
||||
return state && elt.value == state.state;
|
||||
}
|
||||
});
|
||||
if (!retval && def) {
|
||||
|
@ -4200,11 +4241,12 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
_buildStateString(state) {
|
||||
let stateString;
|
||||
if (this.config.show_state && state && state.state) {
|
||||
const localizedState = computeStateDisplay(this.hass.localize, state);
|
||||
const units = this._buildUnits(state);
|
||||
if (units) {
|
||||
stateString = `${state.state} ${units}`;
|
||||
} else {
|
||||
stateString = state.state;
|
||||
stateString = localizedState;
|
||||
}
|
||||
}
|
||||
return stateString;
|
||||
|
@ -4223,7 +4265,7 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
return units;
|
||||
}
|
||||
_buildLastChanged(state, style) {
|
||||
return state ? html`<ha-relative-time .hass="${this.hass}" .datetime="${state.last_changed}" class="label" style=${styleMap(style)}></ha-relative-time>` : html``;
|
||||
return this.config.show_last_changed && state ? html`<ha-relative-time id="label" class="ellipsis" .hass="${this.hass}" .datetime="${state.last_changed}" style=${styleMap(style)}></ha-relative-time>` : undefined;
|
||||
}
|
||||
_buildLabel(state, configState) {
|
||||
if (!this.config.show_label) {
|
||||
|
@ -4316,7 +4358,7 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
<ha-card class="button-card-main ${this._isClickable(state) ? '' : 'disabled'}" style=${styleMap(cardStyle)} @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" .longpress="${longPress()}" .config="${this.config}">
|
||||
${this._getLock(lockStyle)}
|
||||
${this._buttonContent(state, configState, buttonColor)}
|
||||
${this.config.lock ? '' : html`<paper-ripple id="ripple"></paper-ripple>`}
|
||||
${this.config.lock ? '' : html`<mwc-ripple id="ripple"></mwc-ripple>`}
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
@ -4344,23 +4386,24 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
}
|
||||
_gridHtml(state, configState, containerClass, color, name, stateString) {
|
||||
const iconTemplate = this._getIconHtml(state, configState, color);
|
||||
const itemClass = ['container', containerClass];
|
||||
const itemClass = [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');
|
||||
const lastChangedTemplate = this._buildLastChanged(state, labelStyleFromConfig);
|
||||
const gridStyleFromConfig = this._buildStyleGeneric(configState, 'grid');
|
||||
if (!iconTemplate) itemClass.push('no-icon');
|
||||
if (!name) itemClass.push('no-name');
|
||||
if (!stateString) itemClass.push('no-state');
|
||||
if (!label) itemClass.push('no-label');
|
||||
if (!label && !lastChangedTemplate) itemClass.push('no-label');
|
||||
return html`
|
||||
<div class=${itemClass.join(' ')}>
|
||||
<div id="container" class=${itemClass.join(' ')} style=${styleMap(gridStyleFromConfig)}>
|
||||
${iconTemplate ? iconTemplate : ''}
|
||||
${name ? html`<div class="name" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label && !this.config.show_last_changed ? html`<div class="label" style=${styleMap(labelStyleFromConfig)}>${unsafeHTML(label)}</div>` : ''}
|
||||
${this.config.show_last_changed ? lastChangedTemplate : ''}
|
||||
${name ? html`<div id="name" class="ellipsis" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div id="state" class="ellipsis" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label && !lastChangedTemplate ? html`<div id="label" class="ellipsis" style=${styleMap(labelStyleFromConfig)}>${unsafeHTML(label)}</div>` : ''}
|
||||
${lastChangedTemplate ? lastChangedTemplate : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -4369,15 +4412,16 @@ let ButtonCard = class ButtonCard extends LitElement {
|
|||
const entityPicture = this._buildEntityPicture(state, configState);
|
||||
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 imgCellStyleFromConfig = this._buildStyleGeneric(configState, 'img_cell');
|
||||
const haIconStyle = Object.assign({ color, width: this.config.size }, haIconStyleFromConfig);
|
||||
const entityPictureStyle = Object.assign({}, haIconStyle, entityPictureStyleFromConfig);
|
||||
if (icon || entityPicture) {
|
||||
return html`
|
||||
<div class="img-cell">
|
||||
<div id="img-cell" style=${styleMap(imgCellStyleFromConfig)}>
|
||||
${icon && !entityPicture ? html`<ha-icon style=${styleMap(haIconStyle)}
|
||||
.icon="${icon}" class="icon" ?rotating=${this._rotate(configState)}></ha-icon>` : ''}
|
||||
.icon="${icon}" id="icon" ?rotating=${this._rotate(configState)}></ha-icon>` : ''}
|
||||
${entityPicture ? html`<img src="${entityPicture}" style=${styleMap(entityPictureStyle)}
|
||||
class="icon" ?rotating=${this._rotate(configState)} />` : ''}
|
||||
id="icon" ?rotating=${this._rotate(configState)} />` : ''}
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -31,6 +31,7 @@ import {
|
|||
import { handleClick } from './handle-click';
|
||||
import { longPress } from './long-press';
|
||||
import { styles } from './styles';
|
||||
import computeStateDisplay from './compute_state_display';
|
||||
|
||||
@customElement('button-card')
|
||||
class ButtonCard extends LitElement {
|
||||
|
@ -64,7 +65,13 @@ class ButtonCard extends LitElement {
|
|||
}
|
||||
|
||||
private _getMatchingConfigState(state: HassEntity | undefined): StateConfig | undefined {
|
||||
if (!state || !this.config!.state) {
|
||||
if (!this.config!.state) {
|
||||
return undefined;
|
||||
}
|
||||
const hasTemplate = this.config!.state.find(
|
||||
elt => elt.operator === 'template',
|
||||
);
|
||||
if (!state && !hasTemplate) {
|
||||
return undefined;
|
||||
}
|
||||
let def: StateConfig | undefined;
|
||||
|
@ -73,20 +80,20 @@ class ButtonCard extends LitElement {
|
|||
switch (elt.operator) {
|
||||
case '==':
|
||||
/* eslint eqeqeq: 0 */
|
||||
return (state!.state == elt.value);
|
||||
return (state && state.state == elt.value);
|
||||
case '<=':
|
||||
return (state!.state <= elt.value);
|
||||
return (state && state.state <= elt.value);
|
||||
case '<':
|
||||
return (state!.state < elt.value);
|
||||
return (state && state.state < elt.value);
|
||||
case '>=':
|
||||
return (state!.state >= elt.value);
|
||||
return (state && state.state >= elt.value);
|
||||
case '>':
|
||||
return (state.state > elt.value);
|
||||
return (state && state.state > elt.value);
|
||||
case '!=':
|
||||
return (state.state != elt.value);
|
||||
return (state && state.state != elt.value);
|
||||
case 'regex': {
|
||||
/* eslint no-unneeded-ternary: 0 */
|
||||
const matches = state.state.match(elt.value) ? true : false;
|
||||
const matches = state && state.state.match(elt.value) ? true : false;
|
||||
return matches;
|
||||
}
|
||||
case 'template': {
|
||||
|
@ -101,7 +108,7 @@ class ButtonCard extends LitElement {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
return (elt.value == state.state);
|
||||
return state && (elt.value == state.state);
|
||||
}
|
||||
});
|
||||
if (!retval && def) {
|
||||
|
@ -249,11 +256,12 @@ class ButtonCard extends LitElement {
|
|||
private _buildStateString(state: HassEntity | undefined): string | undefined {
|
||||
let stateString: string | undefined;
|
||||
if (this.config!.show_state && state && state.state) {
|
||||
const localizedState = computeStateDisplay(this.hass!.localize, state);
|
||||
const units = this._buildUnits(state);
|
||||
if (units) {
|
||||
stateString = `${state.state} ${units}`;
|
||||
} else {
|
||||
stateString = state.state;
|
||||
stateString = localizedState;
|
||||
}
|
||||
}
|
||||
return stateString;
|
||||
|
@ -276,8 +284,8 @@ class ButtonCard extends LitElement {
|
|||
private _buildLastChanged(
|
||||
state: HassEntity | undefined,
|
||||
style: StyleInfo,
|
||||
): TemplateResult {
|
||||
return state ? html`<ha-relative-time .hass="${this.hass}" .datetime="${state.last_changed}" class="label" style=${styleMap(style)}></ha-relative-time>` : html``;
|
||||
): TemplateResult | undefined {
|
||||
return this.config!.show_last_changed && state ? html`<ha-relative-time id="label" class="ellipsis" .hass="${this.hass}" .datetime="${state.last_changed}" style=${styleMap(style)}></ha-relative-time>` : undefined;
|
||||
}
|
||||
|
||||
private _buildLabel(
|
||||
|
@ -391,7 +399,7 @@ class ButtonCard extends LitElement {
|
|||
<ha-card class="button-card-main ${this._isClickable(state) ? '' : 'disabled'}" style=${styleMap(cardStyle)} @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" .longpress="${longPress()}" .config="${this.config}">
|
||||
${this._getLock(lockStyle)}
|
||||
${this._buttonContent(state, configState, buttonColor)}
|
||||
${this.config!.lock ? '' : html`<paper-ripple id="ripple"></paper-ripple>`}
|
||||
${this.config!.lock ? '' : html`<mwc-ripple id="ripple"></mwc-ripple>`}
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
@ -436,24 +444,25 @@ class ButtonCard extends LitElement {
|
|||
stateString: string | undefined,
|
||||
): TemplateResult {
|
||||
const iconTemplate = this._getIconHtml(state, configState, color);
|
||||
const itemClass: string[] = ['container', containerClass];
|
||||
const itemClass: string[] = [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');
|
||||
const lastChangedTemplate = this._buildLastChanged(state, labelStyleFromConfig);
|
||||
const gridStyleFromConfig = this._buildStyleGeneric(configState, 'grid');
|
||||
if (!iconTemplate) itemClass.push('no-icon');
|
||||
if (!name) itemClass.push('no-name');
|
||||
if (!stateString) itemClass.push('no-state');
|
||||
if (!label) itemClass.push('no-label');
|
||||
if (!label && !lastChangedTemplate) itemClass.push('no-label');
|
||||
|
||||
return html`
|
||||
<div class=${itemClass.join(' ')}>
|
||||
<div id="container" class=${itemClass.join(' ')} style=${styleMap(gridStyleFromConfig)}>
|
||||
${iconTemplate ? iconTemplate : ''}
|
||||
${name ? html`<div class="name" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div class="state" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label && !this.config!.show_last_changed ? html`<div class="label" style=${styleMap(labelStyleFromConfig)}>${unsafeHTML(label)}</div>` : ''}
|
||||
${this.config!.show_last_changed ? lastChangedTemplate : ''}
|
||||
${name ? html`<div id="name" class="ellipsis" style=${styleMap(nameStyleFromConfig)}>${name}</div>` : ''}
|
||||
${stateString ? html`<div id="state" class="ellipsis" style=${styleMap(stateStyleFromConfig)}>${stateString}</div>` : ''}
|
||||
${label && !lastChangedTemplate ? html`<div id="label" class="ellipsis" style=${styleMap(labelStyleFromConfig)}>${unsafeHTML(label)}</div>` : ''}
|
||||
${lastChangedTemplate ? lastChangedTemplate : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@ -467,11 +476,11 @@ class ButtonCard extends LitElement {
|
|||
const entityPicture = this._buildEntityPicture(state, configState);
|
||||
const entityPictureStyleFromConfig = this._buildStyleGeneric(configState, 'entity_picture');
|
||||
const haIconStyleFromConfig = this._buildStyleGeneric(configState, 'icon');
|
||||
const imgCellStyleFromConfig = this._buildStyleGeneric(configState, 'img_cell');
|
||||
|
||||
const haIconStyle = {
|
||||
color,
|
||||
width: this.config!.size,
|
||||
'min-width': this.config!.size,
|
||||
...haIconStyleFromConfig,
|
||||
};
|
||||
const entityPictureStyle = {
|
||||
|
@ -481,11 +490,11 @@ class ButtonCard extends LitElement {
|
|||
|
||||
if (icon || entityPicture) {
|
||||
return html`
|
||||
<div class="img-cell">
|
||||
<div id="img-cell" style=${styleMap(imgCellStyleFromConfig)}>
|
||||
${icon && !entityPicture ? html`<ha-icon style=${styleMap(haIconStyle)}
|
||||
.icon="${icon}" class="icon" ?rotating=${this._rotate(configState)}></ha-icon>` : ''}
|
||||
.icon="${icon}" id="icon" ?rotating=${this._rotate(configState)}></ha-icon>` : ''}
|
||||
${entityPicture ? html`<img src="${entityPicture}" style=${styleMap(entityPictureStyle)}
|
||||
class="icon" ?rotating=${this._rotate(configState)} />` : ''}
|
||||
id="icon" ?rotating=${this._rotate(configState)} />` : ''}
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { HassEntity } from 'home-assistant-js-websocket';
|
||||
import { computeDomain } from './helpers';
|
||||
import { LocalizeFunc } from './types';
|
||||
|
||||
export default (
|
||||
localize: LocalizeFunc,
|
||||
stateObj: HassEntity,
|
||||
): string => {
|
||||
let display: string | undefined;
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
|
||||
if (domain === 'binary_sensor') {
|
||||
// Try device class translation, then default binary sensor translation
|
||||
if (stateObj.attributes.device_class) {
|
||||
display = localize(
|
||||
`state.${domain}.${stateObj.attributes.device_class}.${stateObj.state}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!display) {
|
||||
display = localize(`state.${domain}.default.${stateObj.state}`);
|
||||
}
|
||||
} else if (
|
||||
stateObj.attributes.unit_of_measurement
|
||||
&& !['unknown', 'unavailable'].includes(stateObj.state)
|
||||
) {
|
||||
display = stateObj.state;
|
||||
} else if (domain === 'zwave') {
|
||||
if (['initializing', 'dead'].includes(stateObj.state)) {
|
||||
display = localize(
|
||||
`state.zwave.query_stage.${stateObj.state}`,
|
||||
'query_stage',
|
||||
stateObj.attributes.query_stage,
|
||||
);
|
||||
} else {
|
||||
display = localize(`state.zwave.default.${stateObj.state}`);
|
||||
}
|
||||
} else {
|
||||
display = localize(`state.${domain}.${stateObj.state}`);
|
||||
}
|
||||
|
||||
// Fall back to default, component backend translation, or raw state if nothing else matches.
|
||||
if (!display) {
|
||||
display = localize(`state.default.${stateObj.state}`)
|
||||
|| localize(`component.${domain}.state.${stateObj.state}`)
|
||||
|| stateObj.state;
|
||||
}
|
||||
|
||||
return display;
|
||||
};
|
114
src/styles.ts
114
src/styles.ts
|
@ -6,6 +6,9 @@ export const styles = css`
|
|||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
ha-card.disabled {
|
||||
pointer-events: none;
|
||||
|
@ -25,7 +28,7 @@ export const styles = css`
|
|||
letter-spacing: normal;
|
||||
width: 100%;
|
||||
}
|
||||
div {
|
||||
.ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
@ -99,34 +102,36 @@ export const styles = css`
|
|||
animation: rotating 2s linear infinite;
|
||||
}
|
||||
|
||||
.container {
|
||||
#container {
|
||||
display: grid;
|
||||
max-height: 100%;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
.img-cell {
|
||||
#img-cell {
|
||||
/* display: flex; */
|
||||
grid-area: i;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.icon {
|
||||
ha-icon#icon, img#icon {
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
object-fit: scale;
|
||||
object-fit: contain;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.name {
|
||||
#name {
|
||||
grid-area: n;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
/* margin: auto; */
|
||||
}
|
||||
.state {
|
||||
#state {
|
||||
grid-area: s;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
|
@ -134,205 +139,208 @@ export const styles = css`
|
|||
/* margin: auto; */
|
||||
}
|
||||
|
||||
.label {
|
||||
#label {
|
||||
grid-area: l;
|
||||
max-width: 100%;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.container.vertical {
|
||||
#container {
|
||||
width: 100%;
|
||||
}
|
||||
#container.vertical {
|
||||
grid-template-areas: "i" "n" "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content min-content min-content;
|
||||
}
|
||||
/* Vertical No Icon */
|
||||
.container.vertical.no-icon {
|
||||
#container.vertical.no-icon {
|
||||
grid-template-areas: "n" "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.vertical.no-icon .state {
|
||||
#container.vertical.no-icon #state {
|
||||
align-self: center;
|
||||
}
|
||||
.container.vertical.no-icon .name {
|
||||
#container.vertical.no-icon #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon .label {
|
||||
#container.vertical.no-icon #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Name */
|
||||
.container.vertical.no-icon.no-name {
|
||||
#container.vertical.no-icon.no-name {
|
||||
grid-template-areas: "s" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-name .state {
|
||||
#container.vertical.no-icon.no-name #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-name .label {
|
||||
#container.vertical.no-icon.no-name #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No State */
|
||||
.container.vertical.no-icon.no-state {
|
||||
#container.vertical.no-icon.no-state {
|
||||
grid-template-areas: "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-state .name {
|
||||
#container.vertical.no-icon.no-state #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-state .label {
|
||||
#container.vertical.no-icon.no-state #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Label */
|
||||
.container.vertical.no-icon.no-label {
|
||||
#container.vertical.no-icon.no-label {
|
||||
grid-template-areas: "n" "s";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label .name {
|
||||
#container.vertical.no-icon.no-label #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.vertical.no-icon.no-label .state {
|
||||
#container.vertical.no-icon.no-label #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Label No Name */
|
||||
.container.vertical.no-icon.no-label.no-name {
|
||||
#container.vertical.no-icon.no-label.no-name {
|
||||
grid-template-areas: "s";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label.no-name .state {
|
||||
#container.vertical.no-icon.no-label.no-name #state {
|
||||
align-self: center;
|
||||
}
|
||||
/* Vertical No Icon No Label No State */
|
||||
.container.vertical.no-icon.no-label.no-state {
|
||||
#container.vertical.no-icon.no-label.no-state {
|
||||
grid-template-areas: "n";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-label.no-state .name {
|
||||
#container.vertical.no-icon.no-label.no-state #name {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
/* Vertical No Icon No Name No State */
|
||||
.container.vertical.no-icon.no-name.no-state {
|
||||
#container.vertical.no-icon.no-name.no-state {
|
||||
grid-template-areas: "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.vertical.no-icon.no-name.no-state .label {
|
||||
#container.vertical.no-icon.no-name.no-state #label {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.container.icon_name_state {
|
||||
#container.icon_name_state {
|
||||
grid-template-areas: "i n" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content;
|
||||
}
|
||||
|
||||
.container.icon_name {
|
||||
#container.icon_name {
|
||||
grid-template-areas: "i n" "s s" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
|
||||
.container.icon_state {
|
||||
#container.icon_state {
|
||||
grid-template-areas: "i s" "n n" "l l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
|
||||
.container.name_state {
|
||||
#container.name_state {
|
||||
grid-template-areas: "i" "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
}
|
||||
.container.name_state.no-icon {
|
||||
#container.name_state.no-icon {
|
||||
grid-template-areas: "n" "l";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.name_state.no-icon .name {
|
||||
#container.name_state.no-icon #name {
|
||||
align-self: end
|
||||
}
|
||||
.container.name_state.no-icon .label {
|
||||
#container.name_state.no-icon #label {
|
||||
align-self: start
|
||||
}
|
||||
|
||||
.container.name_state.no-icon.no-label {
|
||||
#container.name_state.no-icon.no-label {
|
||||
grid-template-areas: "n";
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
.container.name_state.no-icon.no-label .name {
|
||||
#container.name_state.no-icon.no-label #name {
|
||||
align-self: center
|
||||
}
|
||||
|
||||
/* icon_name_state2nd default */
|
||||
.container.icon_name_state2nd {
|
||||
#container.icon_name_state2nd {
|
||||
grid-template-areas: "i n" "i s" "i l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.icon_name_state2nd .name {
|
||||
#container.icon_name_state2nd #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_name_state2nd .state {
|
||||
#container.icon_name_state2nd #state {
|
||||
align-self: center;
|
||||
}
|
||||
.container.icon_name_state2nd .label {
|
||||
#container.icon_name_state2nd #label {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_name_state2nd No Label */
|
||||
.container.icon_name_state2nd.no-label {
|
||||
#container.icon_name_state2nd.no-label {
|
||||
grid-template-areas: "i n" "i s";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.icon_name_state2nd .name {
|
||||
#container.icon_name_state2nd #name {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_name_state2nd .state {
|
||||
#container.icon_name_state2nd #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_state_name2nd Default */
|
||||
.container.icon_state_name2nd {
|
||||
#container.icon_state_name2nd {
|
||||
grid-template-areas: "i s" "i n" "i l";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content 1fr;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_state_name2nd .name {
|
||||
#container.icon_state_name2nd #name {
|
||||
align-self: center;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
/* icon_state_name2nd No Label */
|
||||
.container.icon_state_name2nd.no-label {
|
||||
#container.icon_state_name2nd.no-label {
|
||||
grid-template-areas: "i s" "i n";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
}
|
||||
.container.icon_state_name2nd .state {
|
||||
#container.icon_state_name2nd #state {
|
||||
align-self: end;
|
||||
}
|
||||
.container.icon_state_name2nd .name {
|
||||
#container.icon_state_name2nd #name {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.container.icon_label {
|
||||
#container.icon_label {
|
||||
grid-template-areas: "i l" "n n" "s s";
|
||||
grid-template-columns: 40% 1fr;
|
||||
grid-template-rows: 1fr min-content min-content;
|
||||
|
|
|
@ -73,6 +73,8 @@ export interface StylesConfig {
|
|||
name?: CssStyleConfig[];
|
||||
state?: CssStyleConfig[];
|
||||
label?: CssStyleConfig[];
|
||||
grid?: CssStyleConfig[];
|
||||
img_cell?: CssStyleConfig[];
|
||||
}
|
||||
|
||||
export interface CssStyleConfig {
|
||||
|
|
Loading…
Reference in New Issue