mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
v1.51.2: the v1.51.1 review (HP-1511-01, HP-1511-02)
- HP-1511-01: defaultPositions ran over different rosters — the full card reserves grid cells for hidden devices, the static card compacted them away, so an undragged marker sat in different spots on the two cards. The static card feeds spaceDevs (hidden included) to the shared grid and renders devs (visible) — exactly the split HP-1510-01 introduced for LQI. - HP-1511-02: a hidden ripple-display marker rendered as an icon-less inactive pulse. A ghost drops the display dressing entirely: ripple presentation off, noicon off, base icon on, whatever marker.display says. smoke_hidden_flag: the weak 'has icon OR noicon' assertion is gone — every ghost must carry a base icon; new autoGridParity vector (vb-coordinate comparison, the cards render in different view systems) and a ripple-ghost vector. The demo stub got a connection.subscribeEvents so the static card's module-level config cache can be invalidated between in-test cards.
This commit is contained in:
@@ -93,11 +93,97 @@ Object.assign(out, await page.evaluate(async () => {
|
||||
o.ghostHidesValue = pm === null; // «42 kW» не отрисован
|
||||
o.ghostNoLiveBadges = ghosts.every((g) =>
|
||||
!g.querySelector('.valtext') && !g.querySelector('.tval') && !g.querySelector('.hval') && !g.querySelector('.lqi'));
|
||||
o.ghostKeepsIcon = ghosts.every((g) => !!g.querySelector('ha-icon') || g.classList.contains('noicon'));
|
||||
// у КАЖДОГО призрака есть базовая иконка — «noicon» не оправдание
|
||||
// (HP-1511-02: ripple-призрак был безликим пульсом)
|
||||
o.ghostKeepsIcon = ghosts.every((g) => !!g.querySelector('ha-icon') && !g.classList.contains('noicon'));
|
||||
c._setMode('view'); c._showHidden = false;
|
||||
return o;
|
||||
}));
|
||||
|
||||
// --- HP-1511-02: ripple-призрак с базовой иконкой, без пульса -------------
|
||||
Object.assign(out, await page.evaluate(async () => {
|
||||
const o = {};
|
||||
const c = window.__card;
|
||||
const sr = () => c.shadowRoot || c.renderRoot;
|
||||
const lamp = c._devices.find((x) => x.space === 'f1' && x.bindingKind === 'device' && !x.hidden);
|
||||
c._serverCfg.markers = c._serverCfg.markers || [];
|
||||
c._serverCfg.markers = c._serverCfg.markers.filter((m) => m.id !== lamp.id);
|
||||
c._serverCfg.markers.push({ id: lamp.id, binding: 'device:' + lamp.bindingRef,
|
||||
display: 'ripple', hidden: true });
|
||||
c._cfgEpoch++; c._regSignature = '';
|
||||
c._maybeRebuildDevices();
|
||||
c._setMode('devices'); c._showHidden = true;
|
||||
c.requestUpdate(); await c.updateComplete;
|
||||
const g = [...sr().querySelectorAll('.dev.ghost')].find((x) => x.querySelector('.ripple') || !x.classList.contains('noicon'));
|
||||
const ghosts = [...sr().querySelectorAll('.dev.ghost')];
|
||||
o.rippleGhostHasIcon = ghosts.length > 0 && ghosts.every((x) => !!x.querySelector('ha-icon'));
|
||||
o.rippleGhostNoNoicon = ghosts.every((x) => !x.classList.contains('noicon'));
|
||||
o.rippleGhostNoRipple = ghosts.every((x) => !x.querySelector('.ripple'));
|
||||
c._serverCfg.markers = c._serverCfg.markers.filter((m) => m.id !== lamp.id);
|
||||
c._cfgEpoch++; c._regSignature = ''; c._maybeRebuildDevices();
|
||||
c._setMode('view'); c._showHidden = false;
|
||||
return o;
|
||||
}));
|
||||
|
||||
// --- HP-1511-01: авто-сетка одинакова на обеих карточках ------------------
|
||||
Object.assign(out, await page.evaluate(async () => {
|
||||
const o = {};
|
||||
const c = window.__card;
|
||||
await customElements.whenDefined('houseplan-space-card');
|
||||
const cfg = JSON.parse(JSON.stringify(c._serverCfg));
|
||||
const f1 = cfg.spaces.find((s) => s.id === 'f1');
|
||||
// один видимый, остальные зоны living_room скрыты; layout пуст
|
||||
const vis = c._devices.filter((x) => x.area === 'living_room' && !x.virtual);
|
||||
const keep = vis[0];
|
||||
for (const d of vis.slice(1)) {
|
||||
cfg.markers = (cfg.markers || []).filter((m) => m.id !== d.id);
|
||||
cfg.markers.push({ id: d.id, binding: d.bindingKind + ':' + d.bindingRef, hidden: true });
|
||||
}
|
||||
cfg.markers = cfg.markers.filter((m) => m.id !== keep.id || !m.hidden);
|
||||
c._serverCfg = cfg; c._cfgEpoch++; c._regSignature = '';
|
||||
c._layout = {}; // пустой layout: работают только авто-позиции
|
||||
c._maybeRebuildDevices(); c.requestUpdate(); await c.updateComplete;
|
||||
const full = [...(c.shadowRoot || c.renderRoot).querySelectorAll('.dev')]
|
||||
.find((el) => el.style.left && !el.classList.contains('ghost'));
|
||||
// проценты полной карточки считаются от content-fit view — переводим в vb
|
||||
const v = c._viewOr(c._baseVb());
|
||||
const fullVb = full && [
|
||||
v.x + (parseFloat(full.style.left) / 100) * v.w,
|
||||
v.y + (parseFloat(full.style.top) / 100) * v.h,
|
||||
];
|
||||
|
||||
const hass = { ...c.hass, callWS: async (m) => {
|
||||
// rev уникален: у статичной карточки модульный кэш конфига по rev,
|
||||
// и одинаковый rev в соседних тестах подсовывает чужой конфиг
|
||||
if (m.type === 'houseplan/config/get') return { config: cfg, rev: 31 };
|
||||
if (m.type === 'houseplan/layout/get') return { layout: {}, rev: 31 };
|
||||
return { ok: true };
|
||||
},
|
||||
// модульный кэш конфига инвалидируется только через это событие — стаб
|
||||
// сохраняет колбэк, чтобы следующий тест мог сбросить кэш
|
||||
connection: { subscribeEvents: async (cb) => { window.__hpInvalidate = cb; return () => {}; } } };
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const card = document.createElement('houseplan-space-card');
|
||||
card.setConfig({ type: 'custom:houseplan-space-card', space: 'f1' });
|
||||
card.hass = hass;
|
||||
host.appendChild(card);
|
||||
const t0 = Date.now();
|
||||
while (!card.renderRoot?.querySelector('[style*="left"]') && Date.now() - t0 < 6000) {
|
||||
await new Promise((r) => setTimeout(r, 60));
|
||||
}
|
||||
await card.updateComplete;
|
||||
const st = [...card.renderRoot.querySelectorAll('[style*="left"]')]
|
||||
.find((el) => /%$/.test(el.style.left || '') && el.style.top);
|
||||
// статичная карточка рендерит от полного квадрата 0..1000
|
||||
const stVb = st && [parseFloat(st.style.left) * 10, parseFloat(st.style.top) * 10];
|
||||
o.autoGridParity = !!fullVb && !!stVb
|
||||
&& Math.abs(fullVb[0] - stVb[0]) < 6 && Math.abs(fullVb[1] - stVb[1]) < 6;
|
||||
if (!o.autoGridParity) console.log('full', fullVb, 'static', stVb);
|
||||
host.remove();
|
||||
return o;
|
||||
}));
|
||||
|
||||
// --- HP-1510-01: LQI комнаты одинаков на полной и статичной карточке ------
|
||||
Object.assign(out, await page.evaluate(async () => {
|
||||
const o = {};
|
||||
@@ -120,11 +206,13 @@ Object.assign(out, await page.evaluate(async () => {
|
||||
.find((r) => (r.getAttribute('style') || '').includes('--room-fill'));
|
||||
const fullFill = fullRoom ? (fullRoom.getAttribute('style').match(/--room-fill:([^;]+)/) || [])[1] : null;
|
||||
|
||||
window.__hpInvalidate?.(); // сбросить модульный кэш от предыдущей карточки
|
||||
const hass = { ...c.hass, callWS: async (m) => {
|
||||
if (m.type === 'houseplan/config/get') return { config: cfg, rev: 1 };
|
||||
if (m.type === 'houseplan/layout/get') return { layout: {}, rev: 1 };
|
||||
if (m.type === 'houseplan/config/get') return { config: cfg, rev: 57 };
|
||||
if (m.type === 'houseplan/layout/get') return { layout: {}, rev: 57 };
|
||||
return { ok: true };
|
||||
} };
|
||||
},
|
||||
connection: { subscribeEvents: async () => () => {} } };
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const card = document.createElement('houseplan-space-card');
|
||||
|
||||
@@ -1583,7 +1583,7 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
||||
z-index: 120;
|
||||
max-width: 90vw;
|
||||
}
|
||||
`,Gi=1e3;function Vi(t,e){const i=Number(t),s=Number.isFinite(i)&&i>0?i:1,o=s>=1?e:e*s,n=s>=1?e/s:e;return{x:(e-o)/2,y:(e-n)/2,w:o,h:n}}function Ki(t){if(null==t.x||null==t.y)return{x:t.x,y:t.y,w:t.w,h:t.h};const e=Number(t.w)||0,i=Number(t.h)||0;return{x:e<0?t.x+e:t.x,y:i<0?t.y+i:t.y,w:Math.abs(e),h:Math.abs(i)}}function Zi(t){return t&&Array.isArray(t.spaces)?t.spaces.map(t=>{const e=Gi,i=function(t){return Array.isArray(t)&&4===t.length&&t.every(t=>Number.isFinite(t))&&t[2]>1e-6&&t[3]>1e-6?t:[0,0,1,1]}(t.view_box);return{id:t.id,title:t.title,vb:[i[0]*Gi,i[1]*e,i[2]*Gi,i[3]*e],bg:t.plan_url?{href:bi(t.plan_url),...Vi(t.plan_aspect,Gi)}:null,rooms:(t.rooms||[]).map(t=>{const i={...t,...Ki(t)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*Gi:void 0,y:null!=i.y?i.y*e:void 0,w:null!=i.w?i.w*Gi:void 0,h:null!=i.h?i.h*e:void 0,poly:i.poly?i.poly.map(t=>[t[0]*Gi,t[1]*e]):void 0}})}}):[]}function Ji(t){if(t.poly&&t.poly.length){const e=t.poly.map(t=>t[0]),i=t.poly.map(t=>t[1]),s=Math.min(...e),o=Math.min(...i);return{x:s,y:o,w:Math.max(...e)-s,h:Math.max(...i)-o}}return{x:t.x??0,y:t.y??0,w:t.w??0,h:t.h??0}}function Xi(t){if(t.poly){const e=t.poly.length;return[t.poly.reduce((t,e)=>t+e[0],0)/e,t.poly.reduce((t,e)=>t+e[1],0)/e]}return[t.x+t.w/2,t.y+.1*Math.min(t.w,t.h)]}function Yi(t){const e=Zi(t.cfg),i=e.find(e=>e.id===t.spaceId);if(!i)return null;const s=i.vb,o=ti(t.cfg.spaces.find(e=>e.id===t.spaceId)),n=t.iconSize??2.5,r=n>8?2.5:n,a={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(a[t.area]=e.id);const l=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):ht,c=pt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:dt),h=Oi({hass:t.hass,areaToSpace:a,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:l,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>Bi(t.lang,e),iconRules:c}),d=h.filter(e=>e.space===t.spaceId),p=d.filter(t=>!t.hidden),u=function(t,e,i){const s={},o=i/100*Gi*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const n=Ji(i),r=.1*Math.min(n.w,n.h),a=n.w-2*r,l=n.h-2*r,c=Math.max(1,Math.round(Math.sqrt(e.length*a/Math.max(l,1)))),h=a/c,d=l/Math.max(Math.ceil(e.length/c),1),p=e.map((t,e)=>({x:n.x+r+h*(e%c+.5),y:n.y+r+d*(Math.floor(e/c)+.5)}));je(p,n,o,.5*r),e.forEach((t,e)=>s[t.id]=p[e])}return s}(p,i,r),_=i.rooms.filter(t=>t.area||o.showBorders).map(e=>{let s="room "+(i.bg?"overlay":"yard"),n="";const r=vi(o.fill,e);if(o.showBorders||"none"!==r){s+=" styled";const i=[`--room-stroke:${o.color}`,`--room-stroke-op:${o.showBorders?o.opacity:0}`],a=e.area?ni(r,"lqi"===r?function(t,e,i){const s=[];for(const o of e){if(o.area!==i||o.virtual)continue;const e=Ti(t,o.entities);null!=e&&s.push(e)}return He(s)}(t.hass,d,e.area):null,"light"===r?Ii(t.hass,d,e.area):"none","temp"===r?function(t,e,i){const s=[];for(const o of e){if(o.area!==i)continue;if("mdi:thermometer"!==o.icon&&"mdi:air-filter"!==o.icon)continue;const e=zi(t,o.entities);null!=e&&s.push(e)}return s.length?Math.round(s.reduce((t,e)=>t+e,0)/s.length*10)/10:null}(t.hass,d,e.area):null,o.tempMin,o.tempMax,si(t.cfg?.settings)):null;a?(s+=" filled",i.push(`--room-fill:${a.c}`,`--room-fill-op:${a.a.toFixed(3)}`)):i.push("--room-fill:transparent","--room-fill-op:0"),n=i.join(";")}const a=!i.bg&&!o.showNames,l=Xi(e),c=e.poly?j`<polygon class="${s}" style="${n}" points="${e.poly.map(t=>t.join(",")).join(" ")}"></polygon>`:j`<rect class="${s}" style="${n}" x="${e.x}" y="${e.y}" width="${e.w}" height="${e.h}" rx="${.03*Math.min(e.w,e.h)}"></rect>`;return j`${c}${a?j`<text class="rlabel" x="${l[0]}" y="${l[1]}">${e.name}</text>`:G}`}),m=p.map(e=>{const o=function(t,e,i,s,o){const n=e[t.id];if(n&&n.s===t.space)return{x:n.x*Gi,y:n.y*Gi};if(s[t.id])return s[t.id];const r=o.vb;return{x:r[0]+r[2]/2,y:r[1]+r[3]/2}}(e,t.layout,t.cfg,u,i),n=(o.x-s[0])/s[2]*100,r=(o.y-s[1])/s[3]*100;return B`<div class="dev ${e.virtual?"virtual":""}" style="left:${n}%;top:${r}%">
|
||||
`,Gi=1e3;function Vi(t,e){const i=Number(t),s=Number.isFinite(i)&&i>0?i:1,o=s>=1?e:e*s,n=s>=1?e/s:e;return{x:(e-o)/2,y:(e-n)/2,w:o,h:n}}function Ki(t){if(null==t.x||null==t.y)return{x:t.x,y:t.y,w:t.w,h:t.h};const e=Number(t.w)||0,i=Number(t.h)||0;return{x:e<0?t.x+e:t.x,y:i<0?t.y+i:t.y,w:Math.abs(e),h:Math.abs(i)}}function Zi(t){return t&&Array.isArray(t.spaces)?t.spaces.map(t=>{const e=Gi,i=function(t){return Array.isArray(t)&&4===t.length&&t.every(t=>Number.isFinite(t))&&t[2]>1e-6&&t[3]>1e-6?t:[0,0,1,1]}(t.view_box);return{id:t.id,title:t.title,vb:[i[0]*Gi,i[1]*e,i[2]*Gi,i[3]*e],bg:t.plan_url?{href:bi(t.plan_url),...Vi(t.plan_aspect,Gi)}:null,rooms:(t.rooms||[]).map(t=>{const i={...t,...Ki(t)};return{id:i.id,name:i.name,area:i.area??null,open_to:i.open_to||void 0,settings:i.settings||void 0,x:null!=i.x?i.x*Gi:void 0,y:null!=i.y?i.y*e:void 0,w:null!=i.w?i.w*Gi:void 0,h:null!=i.h?i.h*e:void 0,poly:i.poly?i.poly.map(t=>[t[0]*Gi,t[1]*e]):void 0}})}}):[]}function Ji(t){if(t.poly&&t.poly.length){const e=t.poly.map(t=>t[0]),i=t.poly.map(t=>t[1]),s=Math.min(...e),o=Math.min(...i);return{x:s,y:o,w:Math.max(...e)-s,h:Math.max(...i)-o}}return{x:t.x??0,y:t.y??0,w:t.w??0,h:t.h??0}}function Xi(t){if(t.poly){const e=t.poly.length;return[t.poly.reduce((t,e)=>t+e[0],0)/e,t.poly.reduce((t,e)=>t+e[1],0)/e]}return[t.x+t.w/2,t.y+.1*Math.min(t.w,t.h)]}function Yi(t){const e=Zi(t.cfg),i=e.find(e=>e.id===t.spaceId);if(!i)return null;const s=i.vb,o=ti(t.cfg.spaces.find(e=>e.id===t.spaceId)),n=t.iconSize??2.5,r=n>8?2.5:n,a={};for(const e of t.cfg.spaces||[])for(const t of e.rooms||[])t.area&&(a[t.area]=e.id);const l=t.cfg.settings?.exclude_integrations?new Set(t.cfg.settings.exclude_integrations):ht,c=pt(t.cfg.settings?.icon_rules?.length?t.cfg.settings.icon_rules:dt),h=Oi({hass:t.hass,areaToSpace:a,markers:t.cfg.markers||[],settings:t.cfg.settings||{},excluded:l,showAll:!!t.cfg.settings?.show_all,firstSpaceId:e[0]?.id||"",loc:e=>Bi(t.lang,e),iconRules:c}),d=h.filter(e=>e.space===t.spaceId),p=d.filter(t=>!t.hidden),u=function(t,e,i){const s={},o=i/100*Gi*1.3;for(const i of e.rooms){if(!i.area)continue;const e=t.filter(t=>t.area===i.area);if(!e.length)continue;const n=Ji(i),r=.1*Math.min(n.w,n.h),a=n.w-2*r,l=n.h-2*r,c=Math.max(1,Math.round(Math.sqrt(e.length*a/Math.max(l,1)))),h=a/c,d=l/Math.max(Math.ceil(e.length/c),1),p=e.map((t,e)=>({x:n.x+r+h*(e%c+.5),y:n.y+r+d*(Math.floor(e/c)+.5)}));je(p,n,o,.5*r),e.forEach((t,e)=>s[t.id]=p[e])}return s}(d,i,r),_=i.rooms.filter(t=>t.area||o.showBorders).map(e=>{let s="room "+(i.bg?"overlay":"yard"),n="";const r=vi(o.fill,e);if(o.showBorders||"none"!==r){s+=" styled";const i=[`--room-stroke:${o.color}`,`--room-stroke-op:${o.showBorders?o.opacity:0}`],a=e.area?ni(r,"lqi"===r?function(t,e,i){const s=[];for(const o of e){if(o.area!==i||o.virtual)continue;const e=Ti(t,o.entities);null!=e&&s.push(e)}return He(s)}(t.hass,d,e.area):null,"light"===r?Ii(t.hass,d,e.area):"none","temp"===r?function(t,e,i){const s=[];for(const o of e){if(o.area!==i)continue;if("mdi:thermometer"!==o.icon&&"mdi:air-filter"!==o.icon)continue;const e=zi(t,o.entities);null!=e&&s.push(e)}return s.length?Math.round(s.reduce((t,e)=>t+e,0)/s.length*10)/10:null}(t.hass,d,e.area):null,o.tempMin,o.tempMax,si(t.cfg?.settings)):null;a?(s+=" filled",i.push(`--room-fill:${a.c}`,`--room-fill-op:${a.a.toFixed(3)}`)):i.push("--room-fill:transparent","--room-fill-op:0"),n=i.join(";")}const a=!i.bg&&!o.showNames,l=Xi(e),c=e.poly?j`<polygon class="${s}" style="${n}" points="${e.poly.map(t=>t.join(",")).join(" ")}"></polygon>`:j`<rect class="${s}" style="${n}" x="${e.x}" y="${e.y}" width="${e.w}" height="${e.h}" rx="${.03*Math.min(e.w,e.h)}"></rect>`;return j`${c}${a?j`<text class="rlabel" x="${l[0]}" y="${l[1]}">${e.name}</text>`:G}`}),m=p.map(e=>{const o=function(t,e,i,s,o){const n=e[t.id];if(n&&n.s===t.space)return{x:n.x*Gi,y:n.y*Gi};if(s[t.id])return s[t.id];const r=o.vb;return{x:r[0]+r[2]/2,y:r[1]+r[3]/2}}(e,t.layout,t.cfg,u,i),n=(o.x-s[0])/s[2]*100,r=(o.y-s[1])/s[3]*100;return B`<div class="dev ${e.virtual?"virtual":""}" style="left:${n}%;top:${r}%">
|
||||
<ha-icon icon="${e.icon}"></ha-icon>
|
||||
</div>`}),g=o.showNames?i.rooms.filter(t=>t.name).map(e=>{const n=function(t,e,i){const s=i["rl_"+(t.id||"")];if(s&&s.s===e)return{x:s.x*Gi,y:s.y*Gi};const o=Xi(t);return{x:o[0],y:o[1]}}(e,i.id,t.layout,t.cfg),r=(n.x-s[0])/s[2]*100,a=(n.y-s[1])/s[3]*100,l=Math.min(1,o.opacity+.25);return B`<div class="roomlabel" style="left:${r}%;top:${a}%;color:${o.color};opacity:${l}">${e.name}</div>`}):[],f=i.bg?t.displayUrl?t.displayUrl(i.bg.href):i.bg.href:"";return B`
|
||||
<div class="hp-static-stage" style="aspect-ratio:${s[2]}/${s[3]}">
|
||||
@@ -2003,8 +2003,8 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
||||
${this._kioskDialog?this._renderKioskDialog():G}
|
||||
${this._toast?B`<div class="toast">${this._toast}</div>`:G}
|
||||
</ha-card>
|
||||
`}_renderDevice(t,e,i=!0){const s=this._pos(t),o=(s.x-e.x)/e.w*100,n=(s.y-e.y)/e.h*100,r=t.hidden?"":this._stateClass(t),a=t.hidden?null:this._liveTemp(t),l=t.hidden?null:this._liveHum(t),c=!i||t.virtual||t.hidden?null:Ti(this.hass,t.entities),h=t.marker,d=h?.display||"badge",p="ripple"===d||"icon_ripple"===d,u=t.primary?this.hass.states[t.primary]:void 0,_="value"!==d||t.hidden?null:null!=a?a+"°":null!=l?l+"%":u&&!isNaN(parseFloat(u.state))?parseFloat(u.state)+(u.attributes?.unit_of_measurement?" "+u.attributes.unit_of_measurement:""):null,m=t.primary?t.primary.split(".")[0]:null,g=this._config?.live_states&&!t.hidden?ri(t.icon,m,u?.attributes?.device_class,u?.state,!!h?.icon):t.icon,f=(h?.controls||[]).filter(di),b=this._config?.live_states&&!t.hidden?f.length?f.map(t=>ai(this.hass.states[t])).find(t=>t)||null:"light"===m?ai(u):null:null,v=this._config?.live_states&&!t.hidden&&function(t,e,i){return"on"===i&&("siren"===t||"binary_sensor"===t&&!!e&&xi.has(e))}(m,u?.attributes?.device_class,u?.state),y=p&&!t.hidden&&!!t.primary&&$e(this.hass.states[t.primary]?.state),w=Number(h?.size)>0?Number(h.size):1,x=Number(h?.angle)||0,k=Number(h?.ripple_size)>0?Number(h.ripple_size):3,$=[`left:${o}%`,`top:${n}%`];return 1!==w&&$.push(`--dev-scale:${w}`),p&&($.push(`--ripple-scale:${k}`),h?.ripple_color?$.push(`--ripple-color:${h.ripple_color}`):b&&$.push(`--ripple-color:${b}`)),b&&$.push(`--light-color:${b}`),B`<div
|
||||
class="dev ${r} ${this._selId===t.id?"sel":""} ${t.virtual?"virtual":""} ${t.hidden?"ghost":""} ${"ripple"===d?"noicon":""} ${null!=_?"valonly":""} ${b?"rgb":""} ${v?"alarm":""}"
|
||||
`}_renderDevice(t,e,i=!0){const s=this._pos(t),o=(s.x-e.x)/e.w*100,n=(s.y-e.y)/e.h*100,r=t.hidden?"":this._stateClass(t),a=t.hidden?null:this._liveTemp(t),l=t.hidden?null:this._liveHum(t),c=!i||t.virtual||t.hidden?null:Ti(this.hass,t.entities),h=t.marker,d=h?.display||"badge",p=("ripple"===d||"icon_ripple"===d)&&!t.hidden,u=t.primary?this.hass.states[t.primary]:void 0,_="value"!==d||t.hidden?null:null!=a?a+"°":null!=l?l+"%":u&&!isNaN(parseFloat(u.state))?parseFloat(u.state)+(u.attributes?.unit_of_measurement?" "+u.attributes.unit_of_measurement:""):null,m=t.primary?t.primary.split(".")[0]:null,g=this._config?.live_states&&!t.hidden?ri(t.icon,m,u?.attributes?.device_class,u?.state,!!h?.icon):t.icon,f=(h?.controls||[]).filter(di),b=this._config?.live_states&&!t.hidden?f.length?f.map(t=>ai(this.hass.states[t])).find(t=>t)||null:"light"===m?ai(u):null:null,v=this._config?.live_states&&!t.hidden&&function(t,e,i){return"on"===i&&("siren"===t||"binary_sensor"===t&&!!e&&xi.has(e))}(m,u?.attributes?.device_class,u?.state),y=p&&!t.hidden&&!!t.primary&&$e(this.hass.states[t.primary]?.state),w=Number(h?.size)>0?Number(h.size):1,x=Number(h?.angle)||0,k=Number(h?.ripple_size)>0?Number(h.ripple_size):3,$=[`left:${o}%`,`top:${n}%`];return 1!==w&&$.push(`--dev-scale:${w}`),p&&($.push(`--ripple-scale:${k}`),h?.ripple_color?$.push(`--ripple-color:${h.ripple_color}`):b&&$.push(`--ripple-color:${b}`)),b&&$.push(`--light-color:${b}`),B`<div
|
||||
class="dev ${r} ${this._selId===t.id?"sel":""} ${t.virtual?"virtual":""} ${t.hidden?"ghost":""} ${"ripple"!==d||t.hidden?"":"noicon"} ${null!=_?"valonly":""} ${b?"rgb":""} ${v?"alarm":""}"
|
||||
style="${$.join(";")}"
|
||||
@click=${e=>this._clickDevice(e,t)}
|
||||
@contextmenu=${e=>this._ctxDevice(e,t)}
|
||||
@@ -2017,7 +2017,7 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
||||
>
|
||||
${p?B`<span class="ripple ${y?"active":""}"><i></i><i></i><i></i></span>`:G}
|
||||
${this._newIds.has(t.id)?B`<span class="newdot" title=${this._t("device.new")}></span>`:G}
|
||||
${null!=_?B`<span class="valtext">${_}</span>`:"ripple"!==d?B`<ha-icon icon="${g}" style=${x?`transform:rotate(${x}deg)`:G}></ha-icon>`:G}
|
||||
${null!=_?B`<span class="valtext">${_}</span>`:"ripple"!==d||t.hidden?B`<ha-icon icon="${g}" style=${x?`transform:rotate(${x}deg)`:G}></ha-icon>`:G}
|
||||
${null!=a&&null==_?B`<span class="tval">${a}°</span>`:G}
|
||||
${null!=l&&null==_?B`<span class="hval">${l}%</span>`:G}
|
||||
${null!=c?B`<span class="lqi" style="color:${be(c)}">${c}</span>`:G}
|
||||
@@ -2668,4 +2668,4 @@ const t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow
|
||||
</button>`}
|
||||
</div>
|
||||
</div>
|
||||
</div>`}}fs.properties={_hdrH:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},fs.ZOOM_MAX=8,fs.ZOOM_MIN=.4,fs._touchSeen=!1,fs._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,fs.styles=Wi,customElements.get("houseplan-card")||customElements.define("houseplan-card",fs),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.51.1 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
||||
</div>`}}fs.properties={_hdrH:{state:!0},hass:{attribute:!1},_config:{state:!0},_space:{state:!0},_layout:{state:!0},_devices:{state:!0},_tip:{state:!0},_selId:{state:!0},_toast:{state:!0},_serverCfg:{state:!0},_mode:{state:!0},_tool:{state:!0},_path:{state:!0},_cursorPt:{state:!0},_mergeSel:{state:!0},_openingDialog:{state:!0},_openingInfo:{state:!0},_mergeDialog:{state:!0},_splitSel:{state:!0},_decorTool:{state:!0},_decorStyle:{state:!0},_decorDraft:{state:!0},_decorSel:{state:!0},_decorTextDialog:{state:!0},_kioskDialog:{state:!0},_kioskDots:{state:!0},_areaSel:{state:!0},_nameSel:{state:!0},_roomDialog:{state:!0},_roomEditId:{state:!0},_roomFill:{state:!0},_roomTempSrc:{state:!0},_roomHumSrc:{state:!0},_roomSrcOpen:{state:!0},_roomSrcFilter:{state:!0},_roomNameScale:{state:!0},_roomLabelScale:{state:!0},_spaceDialog:{state:!0},_infoCard:{state:!0},_rulesDialog:{state:!0},_settingsDialog:{state:!0},_importDialog:{state:!0},_markerDialog:{state:!0},_zoom:{state:!0},_view:{state:!0}},fs.ZOOM_MAX=8,fs.ZOOM_MIN=.4,fs._touchSeen=!1,fs._noHoverMq="undefined"!=typeof window&&"function"==typeof window.matchMedia&&window.matchMedia("(hover: none)").matches,fs.styles=Wi,customElements.get("houseplan-card")||customElements.define("houseplan-card",fs),window.customCards=window.customCards||[],window.customCards.find(t=>"houseplan-card"===t.type)||window.customCards.push({type:"houseplan-card",name:"House Plan Card",description:"Interactive house plan: spaces, rooms and devices with live states and drag layout."}),console.info("%c HOUSEPLAN-CARD %c v1.51.2 ","background:#3ea6ff;color:#04121f;font-weight:700","");
|
||||
|
||||
Reference in New Issue
Block a user