mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 11:16:35 +00:00
Convert state badge to TypeScript (#2712)
This commit is contained in:
parent
039bc587cc
commit
f23258eb8c
@ -1,110 +0,0 @@
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
|
|
||||||
import "../ha-icon";
|
|
||||||
import computeStateDomain from "../../common/entity/compute_state_domain";
|
|
||||||
import stateIcon from "../../common/entity/state_icon";
|
|
||||||
|
|
||||||
class StateBadge extends PolymerElement {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<style>
|
|
||||||
:host {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
width: 40px;
|
|
||||||
color: var(--paper-item-icon-color, #44739e);
|
|
||||||
border-radius: 50%;
|
|
||||||
height: 40px;
|
|
||||||
text-align: center;
|
|
||||||
background-size: cover;
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-icon {
|
|
||||||
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Color the icon if light or sun is on */
|
|
||||||
ha-icon[data-domain="light"][data-state="on"],
|
|
||||||
ha-icon[data-domain="switch"][data-state="on"],
|
|
||||||
ha-icon[data-domain="binary_sensor"][data-state="on"],
|
|
||||||
ha-icon[data-domain="fan"][data-state="on"],
|
|
||||||
ha-icon[data-domain="sun"][data-state="above_horizon"] {
|
|
||||||
color: var(--paper-item-icon-active-color, #fdd835);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Color the icon if unavailable */
|
|
||||||
ha-icon[data-state="unavailable"] {
|
|
||||||
color: var(--state-icon-unavailable-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<ha-icon
|
|
||||||
id="icon"
|
|
||||||
data-domain$="[[_computeDomain(stateObj)]]"
|
|
||||||
data-state$="[[stateObj.state]]"
|
|
||||||
icon="[[_computeIcon(stateObj, overrideIcon)]]"
|
|
||||||
></ha-icon>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
stateObj: {
|
|
||||||
type: Object,
|
|
||||||
observer: "_updateIconAppearance",
|
|
||||||
},
|
|
||||||
overrideIcon: String,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeDomain(stateObj) {
|
|
||||||
return computeStateDomain(stateObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeIcon(stateObj, overrideIcon) {
|
|
||||||
return overrideIcon || stateIcon(stateObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateIconAppearance(newVal) {
|
|
||||||
var errorMessage = null;
|
|
||||||
const iconStyle = {
|
|
||||||
color: "",
|
|
||||||
filter: "",
|
|
||||||
};
|
|
||||||
const hostStyle = {
|
|
||||||
backgroundImage: "",
|
|
||||||
};
|
|
||||||
// hide icon if we have entity picture
|
|
||||||
if (newVal.attributes.entity_picture) {
|
|
||||||
hostStyle.backgroundImage =
|
|
||||||
"url(" + newVal.attributes.entity_picture + ")";
|
|
||||||
iconStyle.display = "none";
|
|
||||||
} else {
|
|
||||||
if (newVal.attributes.hs_color) {
|
|
||||||
const hue = newVal.attributes.hs_color[0];
|
|
||||||
const sat = newVal.attributes.hs_color[1];
|
|
||||||
if (sat > 10) iconStyle.color = `hsl(${hue}, 100%, ${100 - sat / 2}%)`;
|
|
||||||
}
|
|
||||||
if (newVal.attributes.brightness) {
|
|
||||||
const brightness = newVal.attributes.brightness;
|
|
||||||
if (typeof brightness !== "number") {
|
|
||||||
errorMessage = `Type error: state-badge expected number, but type of ${
|
|
||||||
newVal.entity_id
|
|
||||||
}.attributes.brightness is ${typeof brightness} (${brightness})`;
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.warn(errorMessage);
|
|
||||||
}
|
|
||||||
// lowest brighntess will be around 50% (that's pretty dark)
|
|
||||||
iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object.assign(this.$.icon.style, iconStyle);
|
|
||||||
Object.assign(this.style, hostStyle);
|
|
||||||
if (errorMessage) {
|
|
||||||
throw new Error(`Frontend error: ${errorMessage}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define("state-badge", StateBadge);
|
|
127
src/components/entity/state-badge.ts
Normal file
127
src/components/entity/state-badge.ts
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
html,
|
||||||
|
property,
|
||||||
|
PropertyValues,
|
||||||
|
query,
|
||||||
|
} from "lit-element";
|
||||||
|
import "../ha-icon";
|
||||||
|
import computeStateDomain from "../../common/entity/compute_state_domain";
|
||||||
|
import stateIcon from "../../common/entity/state_icon";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
// Not duplicate, this is for typing.
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { HaIcon } from "../ha-icon";
|
||||||
|
|
||||||
|
class StateBadge extends LitElement {
|
||||||
|
@property() public stateObj?: HassEntity;
|
||||||
|
@property() public overrideIcon?: string;
|
||||||
|
@query("ha-icon") private _icon!: HaIcon;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
const stateObj = this.stateObj;
|
||||||
|
|
||||||
|
if (!stateObj) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-icon
|
||||||
|
id="icon"
|
||||||
|
data-domain=${computeStateDomain(stateObj)}
|
||||||
|
data-state=${stateObj.state}
|
||||||
|
.icon=${this.overrideIcon || stateIcon(stateObj)}
|
||||||
|
></ha-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues) {
|
||||||
|
if (!changedProps.has("stateObj")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const stateObj = this.stateObj;
|
||||||
|
|
||||||
|
const iconStyle: Partial<CSSStyleDeclaration> = {
|
||||||
|
color: "",
|
||||||
|
filter: "",
|
||||||
|
};
|
||||||
|
const hostStyle: Partial<CSSStyleDeclaration> = {
|
||||||
|
backgroundImage: "",
|
||||||
|
};
|
||||||
|
if (stateObj) {
|
||||||
|
// hide icon if we have entity picture
|
||||||
|
if (stateObj.attributes.entity_picture) {
|
||||||
|
hostStyle.backgroundImage =
|
||||||
|
"url(" + stateObj.attributes.entity_picture + ")";
|
||||||
|
iconStyle.display = "none";
|
||||||
|
} else {
|
||||||
|
if (stateObj.attributes.hs_color) {
|
||||||
|
const hue = stateObj.attributes.hs_color[0];
|
||||||
|
const sat = stateObj.attributes.hs_color[1];
|
||||||
|
if (sat > 10) {
|
||||||
|
iconStyle.color = `hsl(${hue}, 100%, ${100 - sat / 2}%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stateObj.attributes.brightness) {
|
||||||
|
const brightness = stateObj.attributes.brightness;
|
||||||
|
if (typeof brightness !== "number") {
|
||||||
|
const errorMessage = `Type error: state-badge expected number, but type of ${
|
||||||
|
stateObj.entity_id
|
||||||
|
}.attributes.brightness is ${typeof brightness} (${brightness})`;
|
||||||
|
// tslint:disable-next-line
|
||||||
|
console.warn(errorMessage);
|
||||||
|
}
|
||||||
|
// lowest brighntess will be around 50% (that's pretty dark)
|
||||||
|
iconStyle.filter = `brightness(${(brightness + 245) / 5}%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.assign(this._icon.style, iconStyle);
|
||||||
|
Object.assign(this.style, hostStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 40px;
|
||||||
|
color: var(--paper-item-icon-color, #44739e);
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
background-size: cover;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-icon {
|
||||||
|
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color the icon if light or sun is on */
|
||||||
|
ha-icon[data-domain="light"][data-state="on"],
|
||||||
|
ha-icon[data-domain="switch"][data-state="on"],
|
||||||
|
ha-icon[data-domain="binary_sensor"][data-state="on"],
|
||||||
|
ha-icon[data-domain="fan"][data-state="on"],
|
||||||
|
ha-icon[data-domain="sun"][data-state="above_horizon"] {
|
||||||
|
color: var(--paper-item-icon-active-color, #fdd835);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color the icon if unavailable */
|
||||||
|
ha-icon[data-state="unavailable"] {
|
||||||
|
color: var(--state-icon-unavailable-color);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"state-badge": StateBadge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("state-badge", StateBadge);
|
@ -1,18 +0,0 @@
|
|||||||
import "@polymer/iron-icon/iron-icon";
|
|
||||||
|
|
||||||
const IronIconClass = customElements.get("iron-icon");
|
|
||||||
|
|
||||||
let loaded = false;
|
|
||||||
|
|
||||||
class HaIcon extends IronIconClass {
|
|
||||||
listen(...args) {
|
|
||||||
super.listen(...args);
|
|
||||||
|
|
||||||
if (!loaded && this._iconsetName === "mdi") {
|
|
||||||
loaded = true;
|
|
||||||
import(/* webpackChunkName: "mdi-icons" */ "../resources/mdi-icons");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("ha-icon", HaIcon);
|
|
36
src/components/ha-icon.ts
Normal file
36
src/components/ha-icon.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { Constructor } from "lit-element";
|
||||||
|
import "@polymer/iron-icon/iron-icon";
|
||||||
|
// Not duplicate, this is for typing.
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { IronIconElement } from "@polymer/iron-icon/iron-icon";
|
||||||
|
|
||||||
|
const ironIconClass = customElements.get("iron-icon") as Constructor<
|
||||||
|
IronIconElement
|
||||||
|
>;
|
||||||
|
|
||||||
|
let loaded = false;
|
||||||
|
|
||||||
|
export class HaIcon extends ironIconClass {
|
||||||
|
private _iconsetName?: string;
|
||||||
|
|
||||||
|
public listen(
|
||||||
|
node: EventTarget | null,
|
||||||
|
eventName: string,
|
||||||
|
methodName: string
|
||||||
|
): void {
|
||||||
|
super.listen(node, eventName, methodName);
|
||||||
|
|
||||||
|
if (!loaded && this._iconsetName === "mdi") {
|
||||||
|
loaded = true;
|
||||||
|
import(/* webpackChunkName: "mdi-icons" */ "../resources/mdi-icons");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-icon": HaIcon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("ha-icon", HaIcon);
|
Loading…
x
Reference in New Issue
Block a user