From 466a1af902e1492cb226b1acdba174ad5c135d33 Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 11 May 2020 17:58:17 -0400 Subject: [PATCH] Weather Card/Row: Weather Icons as SVG, Themeable, user definable (#5736) * SVG * no-unneeded-ternary * declared ubnused * moving stuff around * Few updates * All svgs in | update row * No slots * Remove public/static/images/weather * style for user defined * few updates to missing fils * classes * wind color --- public/static/images/weather/cloudy.png | Bin 655 -> 0 bytes .../static/images/weather/lightning-rainy.png | Bin 888 -> 0 bytes public/static/images/weather/lightning.png | Bin 807 -> 0 bytes public/static/images/weather/night.png | Bin 639 -> 0 bytes .../static/images/weather/partly-cloudy.png | Bin 1130 -> 0 bytes public/static/images/weather/pouring.png | Bin 840 -> 0 bytes public/static/images/weather/rainy.png | Bin 798 -> 0 bytes public/static/images/weather/snowy.png | Bin 1140 -> 0 bytes public/static/images/weather/sunny.png | Bin 487 -> 0 bytes public/static/images/weather/windy.png | Bin 774 -> 0 bytes src/data/weather.ts | 240 +++++++++++- .../cards/hui-weather-forecast-card.ts | 366 +++++++++--------- .../entity-rows/hui-weather-entity-row.ts | 169 ++++++-- 13 files changed, 528 insertions(+), 247 deletions(-) delete mode 100644 public/static/images/weather/cloudy.png delete mode 100644 public/static/images/weather/lightning-rainy.png delete mode 100644 public/static/images/weather/lightning.png delete mode 100644 public/static/images/weather/night.png delete mode 100644 public/static/images/weather/partly-cloudy.png delete mode 100644 public/static/images/weather/pouring.png delete mode 100644 public/static/images/weather/rainy.png delete mode 100644 public/static/images/weather/snowy.png delete mode 100644 public/static/images/weather/sunny.png delete mode 100644 public/static/images/weather/windy.png diff --git a/public/static/images/weather/cloudy.png b/public/static/images/weather/cloudy.png deleted file mode 100644 index 1277a7ad6762ddcd4016a68f8715c4486d03ffdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 655 zcmV;A0&x9_P)dYq+ow}uL(>y4l=Y^!jl+lhT~a{!4zkA>ji@JVsFRk+dC*P10CGLy&Hqki694{@( zNi-Vig=L&!>7>4;1^e`!j4Exsg~A>?kl)Ti1_PBY&%zs8sN3nCL8*T2SXi+jc#gjd zxpDqs61P(5;xkCX`Jmr@p0F&iP%OuwuiP!fr{7Vfi5^Po-dD?j1n^`a!qTm=Q-y!U zJ7ItXU_rf*f6G6l!m{^+A`V8?gusHZ(?VFt!+@56(FlPBw*hp1f-O|xWg}J@XlMDs z%z%vqCJT=1IB&o8EN-VT>L~zU2GzX%y+PVa0Z&FNMA$J0QZ!%*17j{|X^3MI?ym2? zVVQxRf;|_!GcpMw&#k_ pF`zLDG=)J1vcV`A1*2dT007w2^2~>{w{ZXf002ovPDHLkV1i-yHQoRK diff --git a/public/static/images/weather/lightning-rainy.png b/public/static/images/weather/lightning-rainy.png deleted file mode 100644 index 07f78b6c6ff6d9f9b1f2e29cc880acba8520a3ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 888 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!<_GwMxB}^yc)_bzuYmGz-n@aU zdiU<#hYugVeEIV8=g+@?|9=1e{rB(R|Ns973IZ7rHiQ8rKmGjk?bjb5`0?Y%`}gk+ zHvcCHX>3@y4CqADk|4ie1_g(J1t0!jn2_+`fPj9(h613SV6Y!hQ$-*)f&Z#->- zv5Ci~D|YLOpSiIA$e(nj(f*6Fu*WB*#`|GmFILxYb`N?Sc=15(+5?;S{M`L9hROb4 znNx702V=R2#55-TgB?;8lE=0j5RwS~z%H>^>p_Xcb%w>qqF=4q)8oa}xIOh`W<~#= z6Rgr7wm;2%!O(Nr=DhGGmukzpDP1on`tOife^uYuXw|clx+R}7Q$#jou;gtqJaxRx z4DY$S5`Kca%T0g^-TH|Uly^WC8HsR#X92E0%gX}MmBd2 z7IHpLb#P@BQ@hf*tT1+AQ%~3d(;e?NeBBY#%Hy@2^@_r^gBvTt)=e**rg8_UB96uJ zJSXdnZoWHr-!Lc$ny?Dp?JjO?i+d6%w5)m0j_%b`s)^SU?eZBjKSkbqk#OumzW?Ox zZHIR{+&!?Y@$lE%2|o#EuA*^d^ODP$bom{j8a;=qLD<<_PdRw5^MEoZFI zJhJa3f6y8~>9hj|yV%P8bg=d#Wzp$Pz9MBsq{ diff --git a/public/static/images/weather/lightning.png b/public/static/images/weather/lightning.png deleted file mode 100644 index a6aaed9a0c68831d4352c622dd8957dad6a135a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 807 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!rUm$fxB}^yIKZ1XZ!l%vzJ2@o z^XK2cfB*ga_y7O@-@ktcs(}dp`t=Ja2$TYf1KB_l2>P%6k2&(c`W%RDu$fq-tvLNH z&}Bv?L4Lsu0tp)){68=uKz>2Pg@O+TAd~+8cli8xcl=%McX|fduO^uC-FRv_Z?|@8 zm~64fgp+rzFZwYsF!6c1IEGX(CN1D)C_VCuT$Ld@pB|E}NBD9zEi^*H+Q zAFkL|Y$Y79z4exxH|JNi?nR3=+j)Nl@Xz_ax8B{!S!i#Rv%k{eOkZZ^ zlXI@uJ2Z-NnHv6HZg5HG?mE5+wf6-?XG!O3`aF)f9JR~n@&08ob_vP8(Uy-j^*Jww zU;7f6Vjdy=S|aH}G4?kyiV zxvqb@aZpD)Myb){;3cM|R!4*%aQH;TsM|O`Ol;um;V)9(dg%N8!apvHzr@KMGj?bX zw`As+2my4ztpNlRF<+rkH;$;h$l# z!=c*9iO;f19G>;1t)8(+jgNsnQNE`ny04ittf+y-_U~*P3Hzoe48H{~{Swq$c78&6 zLoLUny@y2NE!qFrv-qC4u&U*~e4oH~MU|(mvp)R(`}Onp&s{@(-FFn1L zk=a0i*@08=~cOO3evBGBVeZA}3dH`;Hnlb1M0-2Q(8Xg*Lq$k@Lp@BTh@_y37|zd^R#{c{|w{p6j$C+_~%sqNbabdY{YkY6x^ zpuNvy9sbS#*C}1MdCO$>b<(q+Y=_S`EHo~N^G|PE9V*?wcj;v(G1t3OE0arlMYQjq zVqjn_@^oS;o^fe`^&)Mlu!6D$n!$@yB(@clF6mTP-PM$+cWTnY8wbzMl;`8})B9u6INQ)Z z*EQONXI;U=jY}*JH}2Y)vSBLgErUS5@(XJUZXCQdH}p#ihqv`vujOl0qu*%r@q)vKCidTd|nE_L&1 zFMHP~ct3q_===AFyzxlN4g0i%e7>I5y#-^>gTe~DWM4f Drk7eh diff --git a/public/static/images/weather/partly-cloudy.png b/public/static/images/weather/partly-cloudy.png deleted file mode 100644 index 6c59f6cc936b1d7b4ebb67e98e679c11e2ece5ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1130 zcmXw1X;4#F6b^*N27^F`F$FAvVX*{lKz|5?vL&)e;jvZ0s-SkPK!IVAH7rR8AW&%$ zMuP~&ZZcD9ktxe4Yq5m{Ww8(Ln4uYs$4GL z+}zyS+5#A4Pz6A#RH6bZf*@cE9zZxGYo|R9I39@56M)^7Cg7u1s{satL%CK6B%ZSW z1DU1*2)dv%Zs?>tdfuvzP_$dD8MIx7O+?hXg~|hW$@Sr zyefs?$zk5MxL>(cs-92Kh_1@u@tw8jszrusF;_Dig$RQXVIa+sv;T9U^ze`f%nQX1 zqE;z(-iwC(#m^e6vTcb3wM--!_?elU6k(*1yno$ZQ&F0KCjtugIB92n+|? z)ZHSOiFr!@X6nv3j?P#~ZA0W;{i9g~`<|bafnG)p$>cA(;^bF~L)95jbGT?Y=_amI z@NedAy0_npp%5MSRsRM$$J_^TE}OV}EzhSO{q)h84R1S_jpJ3Z^7-a7%S)jVE}eY^ zr-z}!J(gou-|`#B?@RAd`z*-k^arg<1lJ!A1(0D^ro++2>U1`F$h+@i&wOFF{zG;i zr=0IWbRPAJ?Y0`3tdF+fpW*ja1>Y*iPVQ2REGfEb*s9`hO_rQPi?L$kk96b}r|Q#oHF204UB zAAVQfbEf)c=ZUW(dq^C84Q-xuR%&7Agh{Ke=v^auMGp>Ea^K=l1(&$gy|L2mXCTCZ zbYd%ZspzwEJ_#mqV~?G?@6T<+wmz7XVD5VQ3FG?ts99E4#;FdhY?(0lQS9n$rC~aS zsx|u2X&z#v-;&4Yy*9I{3Hr5VQ4*e)MqY-TGej&xh;j-skbY~g!|VOW6kKymAU%ZE I;v38S4^xPX^8f$< diff --git a/public/static/images/weather/pouring.png b/public/static/images/weather/pouring.png deleted file mode 100644 index 487d5ac82772fa8125a2515eb853dc6d0b45ce95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!<^=eJxB}^y*udMjZ?Or3#NNGo z_xbbZFJHdAdGqG`_wRrI{{8*?_lFN3{{R2~?b|mX7by7a*Ds*ppFe+qT%aD6;-!os6FxQt39)D@Z?@?P^v1%Jy5J!vPGQZ{2L&wbfthjN?_b;msrt7ew@|2t7; zIpgG(zH{fl6&NlRmikckqL)42FORXDwQ92U6SWf;WDP8i3vHUV;$rmi$fmO^Hyq!+ zxL9OjK73@kM)3&@jrmpiPI>#XCxLot*y=Oo1 zr9?LE)(}gO{T|RDG|f`-z_Y`$F**yJjVva;F>swX`BT_~*mmb9URi$yx4h&tw$p4d zna*G)^RB?f&&K9V|Fw(y_ZodBhPxK>ZFra4E@;Ud-W68xk}rirRKZOlsJUErf~NF0 zzd3Ji^O=2IwyN-%sFUooE9&mL$Gn~P9B$!vVf5c3^;mXJb(Di-MQHsJtDYAtnGV_Q zx7!zPAHM%d|DT#USA4HZdt}&!|9^X_mG`iNfXl^9)q+1~|6Ug}T64ju^Rvrwi|-ec zxBa<(|MJhh#!fzACtJOC|6tmx=F7OrEaUZ~ua_D9Cih&u_T%0$RtfFDO~ya)(TCR^=I!jt}o4Ls#=@_OmYmKu6{1-oD!MyRD9u zWHT@@33|FXhEy<4nVLT7umX?U#@;*DrLX_?@ANY{oYmp;;OF)y-#gVJR_&VjVZqy~ zz;gyniL=B5k6dy*vZae@l~~+N?k}nZIXC|aRai}QXD)xT){S@jiKR9UKNZqF6pmJ_ zEtuk;*q{>a$TTf%PjU;-va~hqb(~q8JAJBuaV$;bkI-K@#ZO?-efj4r`FJPn)shz2 zV$@+RW@-P;R}GW36{W^d+WFJB=oa-iy1q%Os zmWi=xRJF-m?rW`Zv2&91j;Wq(_ZmfSyxd!NYYDTmLbc%1k^ zN^@HD0}n^rL=*%_-~8C;6m;H*uVU3PjT^62WUYn&bIzMk_G#H<-s*Gqy#6;Tel08i z`Z?^V@aJapO(F-q*+u4Wo*FaZk?=Xrpgo(F4thp?a!_#I#U=Nf^^`*S$@ndi3xMg0 N!PC{xWt~$(69DX%mt6n= diff --git a/public/static/images/weather/snowy.png b/public/static/images/weather/snowy.png deleted file mode 100644 index e28b6e82747cfad550104396148ae58d3816a89b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1140 zcmV-)1dIELP)YJZIjJy zWv7Xq%xhQN*z9IHQvbf`_!-Z0?clH6fS{$^XpFGFT+e@&AAK1#46R1zFF}>C4dyT{( zCVxfaH@DyZ8feefSgd3Q=H=J^bwDr3Ey3WUEdaE21J-9ieZcHfuhDfuUE>N^CaQ}M zE$imnvu?jgh3XT~j(zC`HPp*y997JLde!nNbIVNmzeB249|ux5 zbCj#|XU38V#_3~LYTUX|(mbMH&fohQBW<(De@(zRHvnau8u97@wQe z)p!2@Dl#5ed%ax5LFM@)mq2br#4d1G3?dpQ#C$2zj(*#v5E~Jx8@m7zNBMAoWk$SrA*KQx*qv? zz)Z@lj9Lj}mnV#opw8gGuO)Ppy)ai)3p^Pu#7JQEg&ScC6*Iu6;fn|>5b^^2Uy~_Z zWMos&XCVKEr2WX|5_gV-d=1(R_T;~WNWF@TNR5Ok2Mk$Xtl>%qh`%4# zytT>m$%mQLnGx0$7#5!)L0kt2kl%{e@&t-?cOT4c#r#l@(n5F?yAs-3nk{KZ$nl-tap9T*M`2i`o5M!QTsTe@Ef@yLUfJ&VI_c_;&Q_ zc+*?Y-dzUh3G2*;_xO18$Io)U`y71#MF#lc%Z#_%Z@0UjdQVGy!gRdH%m%aGG=LMB z4!=pp(}qBg0O)H3=m|_iIrR4V5n#*!380Qz)f)lE43L0`dUQ&9oZkunr+#=yA%)l9 zynZ4gfT@KVdh`5x0`)U}p5SdD0U$*IVky`3RzR>tVF6Zw5EH4^^+0`81c(TO;Opo; zh2i1xCe)4e2sr7`5c=>C7o?y0iyCb zv&AiYdLsgoV$(+El5!(s_0cHfr^1ze&4Y9f5!^Q{tq(2 z`u}a~|5q*l-msbI`@{igx?D++UoZoUQB>o+HM@kfHh=tY`}2Uf^DEERCGMh&tkMhw zC+=8%XgLD|qnxLUV@L(#+v}!HtquY#7Y?m0*#0}dSXpfPOuzr#g;5_L95>LtU1)p0 zH0QL*f)o6QI-~<7e*DlY6P~A%_vh=EDdv|X-q*DA-{H~!)YRW45Z43Ha^0#dMKdwIzw_{$EKNU+t2C=ch8UWgPK$Y6)WyNx^)cc1}E zT>Gp&MhRlsW8p_W0ga@@(!aca3%opIVKL#{_w=4;H=ThU$cbbUc@cpe$)>6Q5#&rf z!Ri6IBkugqzwah6tCuGhkp@fucK}bON{YwFzXy3CL&A$^Ag}DPv`_vcXa-6oz4G?p zD>{*EIZ-u@iNuh%MPE~6;9`PVR{hl%B&q2|65KJLo7nR59xUv%`~uX2RbF%Yv;`3j zY`uyamSTzw@^GmBz7%M}46qE4F!c|%0-t4TdG6OFTVZ|<>Ng74CLrspUn;aXZ$vky zcDNY>o4AG%)t5pYhrtZY=(VtUv1Zy+IT$daADclp0X_xBK=Dr2c5&?>l5Pf0ByI31 zbof{sI*%b!R9{9SOe;Q+!A>t?s)p+4Q!vuNC`1|{wi~b~AlXKYUd2IxlAi!>7R*Kz z1fHz(Hc;E;o%RC8km%R3lAnR`yK%IEefKMn-U4PToc4ko+kbsT3X&h7VW@cdYvb3T z*#y_UAl-gHi@TFjjVX+{G!r$ZCE^e5hFU{5YUh%ENvqt{t^7^6-KcDYKiftbv5>fC^p8p3IShZZt zES!hfh!h7LJKSR9RkW>iEpC+X6OI5ZJO7J+qgGiMr1s)Xb|K#EHfnVbGUEl|( z$W19Mu*TY3=Vu)`{+PADHRIC1MWaQ=U>@*wCL5~agZ-`$DK4?fLw~hDp}h~V!K!7` z-Vetf)L-IO++aP=JQz(;97Jl$dtYAdSgx_cBKT9!Z`AVnbXy*_t^fc407*qoM6N<$ Ef&(aQ@c;k- diff --git a/src/data/weather.ts b/src/data/weather.ts index 4fe0919191..199a5e68e9 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -1,26 +1,52 @@ -import { HomeAssistant, WeatherEntity } from "../types"; +import { SVGTemplateResult, svg, html, TemplateResult, css } from "lit-element"; +import { styleMap } from "lit-html/directives/style-map"; -export const weatherImages = { - "clear-night": "/static/images/weather/night.png", - cloudy: "/static/images/weather/cloudy.png", - fog: "/static/images/weather/cloudy.png", - lightning: "/static/images/weather/lightning.png", - "lightning-rainy": "/static/images/weather/lightning-rainy.png", - partlycloudy: "/static/images/weather/partly-cloudy.png", - pouring: "/static/images/weather/pouring.png", - rainy: "/static/images/weather/rainy.png", - hail: "/static/images/weather/rainy.png", - snowy: "/static/images/weather/snowy.png", - "snowy-rainy": "/static/images/weather/snowy.png", - sunny: "/static/images/weather/sunny.png", - windy: "/static/images/weather/windy.png", - "windy-variant": "/static/images/weather/windy.png", -}; +import type { HomeAssistant, WeatherEntity } from "../types"; + +export const weatherSVGs = new Set([ + "clear-night", + "cloudy", + "fog", + "lightning", + "lightning-rainy", + "partlycloudy", + "pouring", + "rainy", + "hail", + "snowy", + "snowy-rainy", + "sunny", + "windy", + "windy-variant", +]); export const weatherIcons = { exceptional: "hass:alert-circle-outline", }; +const cloudyStates = new Set([ + "partlycloudy", + "cloudy", + "fog", + "windy", + "windy-variant", + "hail", + "rainy", + "snowy", + "snowy-rainy", + "pouring", + "lightning", + "lightning-rainy", +]); + +const rainStates = new Set(["hail", "rainy", "pouring"]); + +const windyStates = new Set(["windy", "windy-variant"]); + +const snowyStates = new Set(["snowy", "snowy-rainy"]); + +const lightningStates = new Set(["lightning", "lightning-rainy"]); + export const cardinalDirections = [ "N", "NNE", @@ -164,3 +190,183 @@ const getWeatherExtrema = ( } `; }; + +export const weatherSVGStyles = css` + .rain { + fill: var(--weather-icon-rain-color, #30b3ff); + } + .sun { + fill: var(--weather-icon-sun-color, #fdd93c); + } + .moon { + fill: var(--weather-icon-moon-color, #fdf9cc); + } + .cloud-back { + fill: var(--weather-icon-cloud-back-color, #d4d4d4); + } + .cloud-front { + fill: var(--weather-icon-cloud-front-color, #f9f9f9); + } +`; + +export const getWeatherStateSVG = (state: string): SVGTemplateResult => { + return svg` + + ${ + state === "sunny" + ? svg` + + ` + : "" + } + ${ + state === "clear-night" + ? svg` + + ` + : "" + } + ${ + state === "partlycloudy" + ? svg` + + ` + : "" + } + ${ + cloudyStates.has(state) + ? svg` + + + ` + : "" + } + ${ + rainStates.has(state) + ? svg` + + + + + ` + : "" + } + ${ + state === "pouring" + ? svg` + + + ` + : "" + } + ${ + windyStates.has(state) + ? svg` + + + ` + : "" + } + ${ + snowyStates.has(state) + ? svg` + + + + ` + : "" + } + ${ + lightningStates.has(state) + ? svg` + + ` + : "" + } + `; +}; + +export const getWeatherStateIcon = ( + state: string, + element: HTMLElement +): TemplateResult | undefined => { + const userDefinedIcon = getComputedStyle(element).getPropertyValue( + `--weather-icon-${state}` + ); + + if (userDefinedIcon) { + return html` +
+ `; + } + + if (weatherSVGs.has(state)) { + return html`${getWeatherStateSVG(state)}`; + } + + if (state in weatherIcons) { + return html` + + `; + } + + return undefined; +}; diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 8fa9356417..3b5f7bc377 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -21,16 +21,16 @@ import { UNAVAILABLE } from "../../../data/entity"; import { getSecondaryWeatherAttribute, getWeatherUnit, - weatherIcons, - weatherImages, + getWeatherStateIcon, + weatherSVGStyles, } from "../../../data/weather"; -import { HomeAssistant, WeatherEntity } from "../../../types"; +import type { HomeAssistant, WeatherEntity } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entites"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-warning"; -import { LovelaceCard, LovelaceCardEditor } from "../types"; -import { WeatherForecastCardConfig } from "./types"; +import type { LovelaceCard, LovelaceCardEditor } from "../types"; +import type { WeatherForecastCardConfig } from "./types"; import { installResizeObserver } from "../common/install-resize-observer"; const DAY_IN_MILLISECONDS = 86400000; @@ -165,6 +165,8 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { hourly = timeDiff < DAY_IN_MILLISECONDS; } + const weatherStateIcon = getWeatherStateIcon(stateObj.state, this); + return html`
- ${stateObj.state in weatherImages - ? html` - - ` - : html` - - `} + ${weatherStateIcon || + html` + + `}
@@ -251,21 +247,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { ${item.condition !== undefined && item.condition !== null ? html`
- ${item.condition in weatherImages - ? html` - - ` - : item.condition in weatherIcons - ? html` - - ` - : ""} + ${getWeatherStateIcon(item.condition, this)}
` : ""} @@ -334,201 +316,205 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { } } - static get styles(): CSSResult { - return css` - :host { - display: block; - } + static get styles(): CSSResult[] { + return [ + weatherSVGStyles, + css` + :host { + display: block; + } - ha-card { - cursor: pointer; - padding: 16px; - } + ha-card { + cursor: pointer; + padding: 16px; + } - .content { - display: flex; - flex-wrap: nowrap; - justify-content: space-between; - align-items: center; - } + .content { + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + align-items: center; + } - .icon-image { - display: flex; - align-items: center; - min-width: 64px; - margin-right: 16px; - } + .icon-image { + display: flex; + align-items: center; + min-width: 64px; + margin-right: 16px; + } - .weather-image, - .weather-icon { - flex: 0 0 64px; - } + .icon-image > * { + flex: 0 0 64px; + height: 64px; + } - .weather-icon { - --mdc-icon-size: 64px; - } + .weather-icon { + --mdc-icon-size: 64px; + } - .info { - display: flex; - justify-content: space-between; - flex-grow: 1; - overflow: hidden; - } + .info { + display: flex; + justify-content: space-between; + flex-grow: 1; + overflow: hidden; + } - .temp-attribute { - text-align: right; - } + .temp-attribute { + text-align: right; + } - .temp-attribute .temp { - position: relative; - margin-right: 24px; - } + .temp-attribute .temp { + position: relative; + margin-right: 24px; + } - .temp-attribute .temp span { - position: absolute; - font-size: 24px; - top: 1px; - } + .temp-attribute .temp span { + position: absolute; + font-size: 24px; + top: 1px; + } - .state, - .temp-attribute .temp { - font-size: 28px; - line-height: 1.2; - } + .name, + .temp-attribute .temp { + font-size: 28px; + line-height: 1.2; + } - .name, - .attribute { - font-size: 14px; - line-height: 1; - } + .state, + .attribute { + font-size: 14px; + line-height: 1; + } - .name-state { - overflow: hidden; - padding-right: 12px; - width: 100%; - } + .name-state { + overflow: hidden; + padding-right: 12px; + width: 100%; + } - .name, - .state { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + .name, + .state { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } - .attribute { - white-space: nowrap; - } + .attribute { + white-space: nowrap; + } - .forecast { - display: flex; - justify-content: space-around; - padding-top: 16px; - } + .forecast { + display: flex; + justify-content: space-around; + padding-top: 16px; + } - .forecast > div { - text-align: center; - } + .forecast > div { + text-align: center; + } - .forecast .icon, - .forecast .temp { - margin: 4px 0; - } + .forecast .icon, + .forecast .temp { + margin: 4px 0; + } - .forecast .temp { - font-size: 16px; - } + .forecast .temp { + font-size: 16px; + } - .forecast-image-icon { - padding-top: 4px; - padding-bottom: 4px; - } + .forecast-image-icon { + padding-top: 4px; + padding-bottom: 4px; + display: flex; + } - .forecast-image { - width: 40px; - } + .forecast-image-icon > * { + width: 40px; + } - .forecast-icon { - --mdc-icon-size: 40px; - } + .forecast-icon { + --mdc-icon-size: 40px; + } - .attribute, - .templow, - .name { - color: var(--secondary-text-color); - } + .attribute, + .templow, + .state { + color: var(--secondary-text-color); + } - .unavailable { - height: 100px; - display: flex; - justify-content: center; - align-items: center; - font-size: 16px; - padding: 10px 20px; - text-align: center; - } + .unavailable { + height: 100px; + display: flex; + justify-content: center; + align-items: center; + font-size: 16px; + padding: 10px 20px; + text-align: center; + } - /* ============= NARROW ============= */ + /* ============= NARROW ============= */ - :host([narrow]) .icon-image { - min-width: 52px; - } + :host([narrow]) .icon-image { + min-width: 52px; + } - :host([narrow]) .weather-image { - flex: 0 0 52px; - width: 52px; - } + :host([narrow]) .weather-image { + flex: 0 0 52px; + width: 52px; + } - :host([narrow]) .weather-icon { - --mdc-icon-size: 52px; - } + :host([narrow]) .weather-icon { + --mdc-icon-size: 52px; + } - :host([narrow]) .state, - :host([narrow]) .temp-attribute .temp { - font-size: 22px; - } + :host([narrow]) .name, + :host([narrow]) .temp-attribute .temp { + font-size: 22px; + } - :host([narrow]) .temp-attribute .temp { - margin-right: 16px; - } + :host([narrow]) .temp-attribute .temp { + margin-right: 16px; + } - :host([narrow]) .temp span { - top: 1px; - font-size: 16px; - } + :host([narrow]) .temp span { + top: 1px; + font-size: 16px; + } - /* ============= VERY NARROW ============= */ + /* ============= VERY NARROW ============= */ - :host([veryNarrow]) .name, - :host([veryNarrow]) .attribute { - display: none; - } + :host([veryNarrow]) .state, + :host([veryNarrow]) .attribute { + display: none; + } - :host([veryNarrow]) .info { - flex-direction: column; - align-items: flex-start; - } + :host([veryNarrow]) .info { + flex-direction: column; + align-items: flex-start; + } - :host([veryNarrow]) .name-state { - padding-right: 0; - } + :host([veryNarrow]) .name-state { + padding-right: 0; + } - /* ============= VERY VERY NARROW ============= */ + /* ============= VERY VERY NARROW ============= */ - :host([veryVeryNarrow]) .info { - padding-top: 4px; - align-items: center; - } + :host([veryVeryNarrow]) .info { + padding-top: 4px; + align-items: center; + } - :host([veryVeryNarrow]) .content { - flex-wrap: wrap; - justify-content: center; - flex-direction: column; - } + :host([veryVeryNarrow]) .content { + flex-wrap: wrap; + justify-content: center; + flex-direction: column; + } - :host([veryVeryNarrow]) .icon-image { - margin-right: 0; - } - `; + :host([veryVeryNarrow]) .icon-image { + margin-right: 0; + } + `, + ]; } } diff --git a/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts b/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts index 2e04013bb1..d0ff194bc2 100644 --- a/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-weather-entity-row.ts @@ -8,21 +8,32 @@ import { PropertyValues, TemplateResult, } from "lit-element"; +import { classMap } from "lit-html/directives/class-map"; +import { ifDefined } from "lit-html/directives/if-defined"; + import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import "../../../components/entity/state-badge"; import { UNAVAILABLE_STATES } from "../../../data/entity"; import { getSecondaryWeatherAttribute, getWeatherUnit, - weatherIcons, - weatherImages, + getWeatherStateIcon, + weatherSVGStyles, } from "../../../data/weather"; -import { HomeAssistant, WeatherEntity } from "../../../types"; -import { EntitiesCardEntityConfig } from "../cards/types"; +import type { HomeAssistant, WeatherEntity } from "../../../types"; +import type { EntitiesCardEntityConfig } from "../cards/types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; import "../components/hui-warning"; -import { LovelaceRow } from "./types"; +import type { LovelaceRow } from "./types"; +import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import { actionHandler } from "../common/directives/action-handler-directive"; +import { hasAction } from "../common/has-action"; +import { computeStateName } from "../../../common/entity/compute_state_name"; +import { ActionHandlerEvent } from "../../../data/lovelace"; +import { handleAction } from "../common/handle-action"; +import { stateIcon } from "../../../common/entity/state_icon"; @customElement("hui-weather-entity-row") class HuiWeatherEntityRow extends LitElement implements LovelaceRow { @@ -61,48 +72,126 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow { `; } - const weatherRowConfig = { - ...this._config, - icon: weatherIcons[stateObj.state], - image: weatherImages[stateObj.state], - }; + const pointer = + (this._config.tap_action && this._config.tap_action.action !== "none") || + (this._config.entity && + !DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity))); + + const weatherStateIcon = getWeatherStateIcon(stateObj.state, this); return html` - -
-
- ${UNAVAILABLE_STATES.includes(stateObj.state) - ? computeStateDisplay( - this.hass.localize, - stateObj, - this.hass.language - ) - : html` - ${stateObj.attributes.temperature} - ${getWeatherUnit(this.hass, "temperature")} - `} -
-
- ${getSecondaryWeatherAttribute(this.hass!, stateObj)} -
+
+ ${weatherStateIcon || + html` + + `} +
+
+ ${this._config.name || computeStateName(stateObj)} +
+
+
+ ${UNAVAILABLE_STATES.includes(stateObj.state) + ? computeStateDisplay( + this.hass.localize, + stateObj, + this.hass.language + ) + : html` + ${stateObj.attributes.temperature} + ${getWeatherUnit(this.hass, "temperature")} + `}
- +
+ ${getSecondaryWeatherAttribute(this.hass!, stateObj)} +
+
`; } - static get styles(): CSSResult { - return css` - .attributes { - display: flex; - flex-direction: column; - justify-content: center; - text-align: right; - } + private _handleAction(ev: ActionHandlerEvent) { + handleAction(this, this.hass!, this._config!, ev.detail.action!); + } - .secondary { - color: var(--secondary-text-color); - } - `; + static get styles(): CSSResult[] { + return [ + weatherSVGStyles, + css` + :host { + display: flex; + align-items: center; + flex-direction: row; + } + + .info { + margin-left: 16px; + flex: 1 0 60px; + } + + .info, + .info > * { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .icon-image { + display: flex; + align-items: center; + min-width: 40px; + } + + .icon-image > * { + flex: 0 0 40px; + height: 40px; + } + + .weather-icon { + --iron-icon-width: 40px; + --iron-icon-height: 40px; + } + + :host([rtl]) .flex { + margin-left: 0; + margin-right: 16px; + } + + .pointer { + cursor: pointer; + } + + .attributes { + display: flex; + flex-direction: column; + justify-content: center; + text-align: right; + margin-left: 8px; + } + + .secondary { + color: var(--secondary-text-color); + } + `, + ]; } }