diff --git a/src/dialogs/more-info/controls/more-info-weather.js b/src/dialogs/more-info/controls/more-info-weather.js
deleted file mode 100644
index a9309905cd..0000000000
--- a/src/dialogs/more-info/controls/more-info-weather.js
+++ /dev/null
@@ -1,235 +0,0 @@
-import "@polymer/iron-icon/iron-icon";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-
-import LocalizeMixin from "../../../mixins/localize-mixin";
-
-/*
- * @appliesMixin LocalizeMixin
- */
-class MoreInfoWeather extends LocalizeMixin(PolymerElement) {
- static get template() {
- return html`
-
-
-
-
-
- [[localize('ui.card.weather.attributes.temperature')]]
-
-
- [[stateObj.attributes.temperature]] [[getUnit('temperature')]]
-
-
-
-
-
-
- [[localize('ui.card.weather.attributes.air_pressure')]]
-
-
- [[stateObj.attributes.pressure]] [[getUnit('air_pressure')]]
-
-
-
-
-
-
-
- [[localize('ui.card.weather.attributes.humidity')]]
-
-
[[stateObj.attributes.humidity]] %
-
-
-
-
-
-
- [[localize('ui.card.weather.attributes.wind_speed')]]
-
-
- [[getWind(stateObj.attributes.wind_speed,
- stateObj.attributes.wind_bearing, localize)]]
-
-
-
-
-
-
-
- [[localize('ui.card.weather.attributes.visibility')]]
-
-
[[stateObj.attributes.visibility]] [[getUnit('length')]]
-
-
-
-
- [[localize('ui.card.weather.forecast')]]:
-
-
-
-
-
-
- [[computeDateTime(item.datetime)]]
-
-
- [[computeDate(item.datetime)]]
-
- [[item.templow]] [[getUnit('temperature')]]
-
-
-
- [[item.temperature]] [[getUnit('temperature')]]
-
-
-
-
-
-
- [[stateObj.attributes.attribution]]
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- stateObj: Object,
- };
- }
-
- constructor() {
- super();
- this.cardinalDirections = [
- "N",
- "NNE",
- "NE",
- "ENE",
- "E",
- "ESE",
- "SE",
- "SSE",
- "S",
- "SSW",
- "SW",
- "WSW",
- "W",
- "WNW",
- "NW",
- "NNW",
- "N",
- ];
- this.weatherIcons = {
- "clear-night": "hass:weather-night",
- cloudy: "hass:weather-cloudy",
- exceptional: "hass:alert-circle-outline",
- fog: "hass:weather-fog",
- hail: "hass:weather-hail",
- lightning: "hass:weather-lightning",
- "lightning-rainy": "hass:weather-lightning-rainy",
- partlycloudy: "hass:weather-partly-cloudy",
- pouring: "hass:weather-pouring",
- rainy: "hass:weather-rainy",
- snowy: "hass:weather-snowy",
- "snowy-rainy": "hass:weather-snowy-rainy",
- sunny: "hass:weather-sunny",
- windy: "hass:weather-windy",
- "windy-variant": "hass:weather-windy-variant",
- };
- }
-
- computeDate(data) {
- const date = new Date(data);
- return date.toLocaleDateString(this.hass.language, {
- weekday: "long",
- month: "short",
- day: "numeric",
- });
- }
-
- computeDateTime(data) {
- const date = new Date(data);
- return date.toLocaleDateString(this.hass.language, {
- weekday: "long",
- hour: "numeric",
- });
- }
-
- getUnit(measure) {
- const lengthUnit = this.hass.config.unit_system.length || "";
- switch (measure) {
- case "air_pressure":
- return lengthUnit === "km" ? "hPa" : "inHg";
- case "length":
- return lengthUnit;
- case "precipitation":
- return lengthUnit === "km" ? "mm" : "in";
- default:
- return this.hass.config.unit_system[measure] || "";
- }
- }
-
- windBearingToText(degree) {
- const degreenum = parseInt(degree);
- if (isFinite(degreenum)) {
- return this.cardinalDirections[(((degreenum + 11.25) / 22.5) | 0) % 16];
- }
- return degree;
- }
-
- getWind(speed, bearing, localize) {
- if (bearing != null) {
- const cardinalDirection = this.windBearingToText(bearing);
- return `${speed} ${this.getUnit("length")}/h (${localize(
- `ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
- ) || cardinalDirection})`;
- }
- return `${speed} ${this.getUnit("length")}/h`;
- }
-
- getWeatherIcon(condition) {
- return this.weatherIcons[condition];
- }
-
- _showValue(item) {
- return typeof item !== "undefined" && item !== null;
- }
-}
-
-customElements.define("more-info-weather", MoreInfoWeather);
diff --git a/src/dialogs/more-info/controls/more-info-weather.ts b/src/dialogs/more-info/controls/more-info-weather.ts
new file mode 100644
index 0000000000..8d14f80cac
--- /dev/null
+++ b/src/dialogs/more-info/controls/more-info-weather.ts
@@ -0,0 +1,288 @@
+import "@polymer/iron-icon/iron-icon";
+import {
+ LitElement,
+ property,
+ CSSResult,
+ css,
+ customElement,
+ PropertyValues,
+} from "lit-element";
+import { HassEntity } from "home-assistant-js-websocket";
+import { TemplateResult, html } from "lit-html";
+
+import { HomeAssistant } from "../../../types";
+
+const cardinalDirections = [
+ "N",
+ "NNE",
+ "NE",
+ "ENE",
+ "E",
+ "ESE",
+ "SE",
+ "SSE",
+ "S",
+ "SSW",
+ "SW",
+ "WSW",
+ "W",
+ "WNW",
+ "NW",
+ "NNW",
+ "N",
+];
+
+const weatherIcons = {
+ "clear-night": "hass:weather-night",
+ cloudy: "hass:weather-cloudy",
+ exceptional: "hass:alert-circle-outline",
+ fog: "hass:weather-fog",
+ hail: "hass:weather-hail",
+ lightning: "hass:weather-lightning",
+ "lightning-rainy": "hass:weather-lightning-rainy",
+ partlycloudy: "hass:weather-partly-cloudy",
+ pouring: "hass:weather-pouring",
+ rainy: "hass:weather-rainy",
+ snowy: "hass:weather-snowy",
+ "snowy-rainy": "hass:weather-snowy-rainy",
+ sunny: "hass:weather-sunny",
+ windy: "hass:weather-windy",
+ "windy-variant": "hass:weather-windy-variant",
+};
+
+@customElement("more-info-weather")
+class MoreInfoWeather extends LitElement {
+ @property() public hass!: HomeAssistant;
+ @property() public stateObj?: HassEntity;
+
+ protected shouldUpdate(changedProps: PropertyValues): boolean {
+ if (changedProps.has("stateObj")) {
+ return true;
+ }
+
+ const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
+ if (
+ !oldHass ||
+ oldHass.language !== this.hass.language ||
+ oldHass.config.unit_system !== this.hass.config.unit_system
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected render(): TemplateResult | void {
+ if (!this.hass || !this.stateObj) {
+ return html``;
+ }
+
+ return html`
+
+
+
+ ${this.hass.localize("ui.card.weather.attributes.temperature")}
+
+
+ ${this.stateObj.attributes.temperature} ${this.getUnit("temperature")}
+
+
+ ${this.stateObj.attributes.pressure
+ ? html`
+
+
+
+ ${this.hass.localize("ui.card.weather.attributes.air_pressure")}
+
+
+ ${this.stateObj.attributes.pressure}
+ ${this.getUnit("air_pressure")}
+
+
+ `
+ : ""}
+ ${this.stateObj.attributes.humidity
+ ? html`
+
+
+
+ ${this.hass.localize("ui.card.weather.attributes.humidity")}
+
+
${this.stateObj.attributes.humidity} %
+
+ `
+ : ""}
+ ${this.stateObj.attributes.wind_speed
+ ? html`
+
+
+
+ ${this.hass.localize("ui.card.weather.attributes.wind_speed")}
+
+
+ ${this.getWind(
+ this.stateObj.attributes.wind_speed,
+ this.stateObj.attributes.wind_bearing
+ )}
+
+
+ `
+ : ""}
+ ${this.stateObj.attributes.visibility
+ ? html`
+
+
+
+ ${this.hass.localize("ui.card.weather.attributes.visibility")}
+
+
+ ${this.stateObj.attributes.visibility} ${this.getUnit("length")}
+
+
+ `
+ : ""}
+ ${this.stateObj.attributes.forecast
+ ? html`
+
+ ${this.hass.localize("ui.card.weather.forecast")}:
+
+ ${this.stateObj.attributes.forecast.map((item) => {
+ return html`
+
+ ${item.condition
+ ? html`
+
+ `
+ : ""}
+ ${!item.templow
+ ? html`
+
+ ${this.computeDateTime(item.datetime)}
+
+ `
+ : ""}
+ ${item.templow
+ ? html`
+
+ ${this.computeDate(item.datetime)}
+
+
+ ${item.templow} ${this.getUnit("temperature")}
+
+ `
+ : ""};
+
+ ${item.temperature} ${this.getUnit("temperature")}
+
+
+ `;
+ })}
+ `
+ : ""}
+ ${this.stateObj.attributes.attribution
+ ? html`
+
+ ${this.stateObj.attributes.attribution}
+
+ `
+ : ""}
+ `;
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ iron-icon {
+ color: var(--paper-item-icon-color);
+ }
+ .section {
+ margin: 16px 0 8px 0;
+ font-size: 1.2em;
+ }
+
+ .flex {
+ display: flex;
+ height: 32px;
+ align-items: center;
+ }
+
+ .main {
+ flex: 1;
+ margin-left: 24px;
+ }
+
+ .temp,
+ .templow {
+ min-width: 48px;
+ text-align: right;
+ }
+
+ .templow {
+ margin: 0 16px;
+ color: var(--secondary-text-color);
+ }
+
+ .attribution {
+ color: var(--secondary-text-color);
+ text-align: center;
+ }
+ `;
+ }
+
+ private computeDate(data) {
+ const date = new Date(data);
+ return date.toLocaleDateString(this.hass.language, {
+ weekday: "long",
+ month: "short",
+ day: "numeric",
+ });
+ }
+
+ private computeDateTime(data) {
+ const date = new Date(data);
+ return date.toLocaleDateString(this.hass.language, {
+ weekday: "long",
+ hour: "numeric",
+ });
+ }
+
+ private getUnit(measure: string): string {
+ const lengthUnit = this.hass.config.unit_system.length || "";
+ switch (measure) {
+ case "air_pressure":
+ return lengthUnit === "km" ? "hPa" : "inHg";
+ case "length":
+ return lengthUnit;
+ case "precipitation":
+ return lengthUnit === "km" ? "mm" : "in";
+ default:
+ return this.hass.config.unit_system[measure] || "";
+ }
+ }
+
+ private windBearingToText(degree: string): string {
+ const degreenum = parseInt(degree, 10);
+ if (isFinite(degreenum)) {
+ // tslint:disable-next-line: no-bitwise
+ return cardinalDirections[(((degreenum + 11.25) / 22.5) | 0) % 16];
+ }
+ return degree;
+ }
+
+ private getWind(speed: string, bearing: string) {
+ if (bearing != null) {
+ const cardinalDirection = this.windBearingToText(bearing);
+ return `${speed} ${this.getUnit("length")}/h (${this.hass.localize(
+ `ui.card.weather.cardinal_direction.${cardinalDirection.toLowerCase()}`
+ ) || cardinalDirection})`;
+ }
+ return `${speed} ${this.getUnit("length")}/h`;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "more-info-weather": MoreInfoWeather;
+ }
+}