From 8e4fce24405c241dacd0f7cb04bac298fbe649a8 Mon Sep 17 00:00:00 2001 From: Cloos <36499953+Clooos@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:44:56 +0100 Subject: [PATCH] v1.6.0-beta.3 --- dist/bubble-card.js | 147 ++++++++++--------- dist/bubble-pop-up.js | 92 +----------- src/bubble-card.ts | 6 +- src/bubble-pop-up.ts | 6 +- src/cards/button.ts | 9 +- src/cards/horizontal-buttons-stack.ts | 92 ++++++------ src/cards/pop-up-old.ts | 14 ++ src/cards/pop-up.ts | 202 ++++++++++++++------------ src/editor/bubble-card-editor.ts | 103 ++++++------- src/editor/bubble-pop-up-editor.ts | 180 ----------------------- src/tools/init.ts | 61 ++++---- src/tools/style.ts | 5 +- src/tools/tap-actions.ts | 78 +++------- src/tools/url-listener.ts | 2 +- src/var/cards.ts | 4 +- src/var/version.ts | 2 +- webpack.config.js | 3 +- 17 files changed, 371 insertions(+), 635 deletions(-) diff --git a/dist/bubble-card.js b/dist/bubble-card.js index e92f0b2d..022d5f97 100644 --- a/dist/bubble-card.js +++ b/dist/bubble-card.js @@ -1,6 +1,6 @@ -(()=>{"use strict";var __webpack_modules__={946:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{G:()=>getIconStyles,IU:()=>createIcon,L2:()=>addStyles,_k:()=>convertToRGBA,mk:()=>getIconColor,wW:()=>isColorCloseToWhite});const addStyles=function(hass,context,styles,customStyles,state,entityId,stateChanged,path="",element=context.content){const customStylesEval=customStyles?eval("`"+customStyles+"`"):"";let styleAddedKey=styles+"Added";if(!context[styleAddedKey]||context.previousStyle!==customStylesEval||stateChanged||context.previousConfig!==context.config){if(!context[styleAddedKey]){if(context.styleElement=element.querySelector("style"),!context.styleElement){context.styleElement=document.createElement("style");const t=path?element.querySelector(path):element;t?.appendChild(context.styleElement)}context[styleAddedKey]=!0}context.styleElement.innerHTML!==customStylesEval+styles&&(context.styleElement.innerHTML=customStylesEval+styles),context.previousStyle=customStylesEval,context.previousConfig=context.config}};function createIcon(t,e,n,o,i){let a=t._hass,r=!(!e||!a.states[e].attributes)&&a.states[e].attributes;t.imageUrl=!!r.entity_picture&&r.entity_picture,updateIcon(t,a,e,n,o),i||setInterval((()=>{a=t._hass,e&&a.states[e]&&(t.currentEntityPicture=a.states[e].attributes.entity_picture,t.currentEntityPicture!==t.previousEntityPicture&&(t.imageUrl=t.currentEntityPicture,updateIcon(t,a,e,n,o),t.previousEntityPicture=t.currentEntityPicture))}),1e3)}function updateIcon(t,e,n,o,i){for(;i.firstChild;)i.removeChild(i.firstChild);let a=t.config.icon&&t.config.icon.includes("/")?t.config.icon:t.imageUrl?t.imageUrl:"";if(a&&(r=e.states[n].state,n.startsWith("media_player.")&&!["off","unknown","idle",void 0].includes(r)||!n.startsWith("media_player."))){const t=document.createElement("div");t.setAttribute("class","entity-picture"),t.setAttribute("alt","Icon"),i&&(i.appendChild(t),i.style.background="center / cover no-repeat url("+a+"), var(--card-background-color,var(--ha-card-background))")}else{const t=document.createElement("ha-icon");t.setAttribute("icon",o),t.setAttribute("class","icon"),i&&i.appendChild(t)}var r}function isColorCloseToWhite(t){let e=[220,220,190];for(let n=0;n<3;n++)if(t[n]{for(var n in e)__webpack_require__.o(e,n)&&!__webpack_require__.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},__webpack_require__.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var __webpack_exports__={};(()=>{var t="v1.6.0-beta.2",e=__webpack_require__(946);const n=(t,e,n,o)=>{o=o||{},n=null==n?{}:n;const i=new Event(e,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return i.detail=n,t.dispatchEvent(i),i},o=t=>{n(window,"haptic",t)},i=(t,e,o=!1)=>{o?history.replaceState(null,"",e):history.pushState(null,"",e),n(window,"location-changed",{replace:o})};function a(t,e){t.callService("homeassistant","toggle",{entity_id:e})}function r(t,e,n){const o={entity:e.entity,tap_action:{action:"more-info"},double_tap_action:{action:"toggle"},hold_action:{action:"toggle"}},i=new Event("hass-action",{bubbles:!0,composed:!0});i.detail={config:o,action:n},t.dispatchEvent(i)}function s(t,e,n,o){e.tap_action,e.double_tap_action,e.hold_action;let i,a=0,s=0,l=0;t.addEventListener("mousedown",(()=>{s=Date.now(),i=setTimeout((()=>{r(t,e,"hold")}),300)}),{passive:!0}),t.addEventListener("mouseup",(()=>{clearTimeout(i),l=Date.now(),l-s<300&&(a++,1===a&&setTimeout((()=>{1===a?r(t,e,"tap"):(r(t,e,"double_tap"),o("success")),a=0}),300)),s=0,l=0}),{passive:!0}),t.addEventListener("touchstart",(n=>{o("light"),s=Date.now(),i=setTimeout((()=>{r(t,e,"hold")}),300),n.preventDefault()}),{passive:!0}),t.addEventListener("touchend",(n=>{clearTimeout(i),l=Date.now(),l-s<300&&(a++,1===a&&setTimeout((()=>{r(t,e,1===a?"tap":"double_tap"),a=0}),300)),s=0,l=0,n.preventDefault()}),{passive:!0}),t.addEventListener("mouseout",(()=>{clearTimeout(i)}),{passive:!0}),t.addEventListener("touchcancel",(()=>{clearTimeout(i)}),{passive:!0})}let l,c,d,p;function h(t,n,o,i){let a=n.styles?n.styles:"",r=n.entity&&o.states[n.entity]?n.entity:"",s=!n.icon&&n.entity?o.states[r].attributes.icon||o.states[r].attributes.entity_picture||"":n.icon||"",h=n.name?n.name:n.entity?o.states[r].attributes.friendly_name:"",u=n.width_desktop||"540px",g=u?u.match(/(\d+)(\D+)/):"",b=n.is_sidebar_hidden||!1,m=r?o.states[r].state:"";!function(t,e,n){t.hasState=e.states[n],t.hasState&&(t.newState=[t.hasState.state,t.hasState.attributes.rgb_color],t.oldState&&t.newState[0]===t.oldState[0]&&t.newState[1]===t.oldState[1]?t.stateChanged=!1:(t.oldState=t.newState,t.stateChanged=!0),t.stateChanged)}(t,o,r);let f=t.stateChanged,_=["on","open","cleaning","true","home","playing"].includes(m)||0!==Number(m)&&!isNaN(Number(m)),v=void 0===n.rise_animation||n.rise_animation,y=n.margin?"0"!==n.margin?n.margin:"0px":"7px",w=void 0!==n.bg_opacity?n.bg_opacity:"88",x=void 0!==n.shadow_opacity?n.shadow_opacity:"0",k=void 0!==n.bg_blur?n.bg_blur:"10",{iconColorOpacity:C,iconColor:$,iconFilter:S}=(0,e.mk)(o,r,_,e.wW),E=(0,e.G)(r,_,$,S),O=getComputedStyle(document.body),L=O.getPropertyValue("--ha-card-background")||O.getPropertyValue("--card-background-color"),A=n.bg_color?n.bg_color:L;if(A&&(!t.color||A!==t.color)){const n=1.02;c=(0,e._k)(A,w/100,n),document.body.style.setProperty("--bubble-pop-up-background",c),t.color=A,window.color=A}return{customStyles:a,entityId:r,icon:s,name:h,widthDesktop:u,widthDesktopDivided:g,isSidebarHidden:b,state:m,stateChanged:f,stateOn:_,formatedState:p,riseAnimation:v,marginCenter:y,popUpOpen:l,rgbaColor:c,rgbColor:d,bgOpacity:w,shadowOpacity:x,bgBlur:k,iconColorOpacity:C,iconColor:$,iconFilter:S,iconStyles:E,haStyle:O,themeBgColor:L,color:A}}function u(t){const n=t._hass,r=t.editor,l=t.config;if(!n)return;let c,d,{customStyles:p,entityId:u,icon:g,name:b,widthDesktop:m,widthDesktopDivided:f,isSidebarHidden:_,state:v,stateChanged:y,stateOn:w,formatedState:x,riseAnimation:k,marginCenter:C,popUpOpen:$,rgbaColor:S,rgbColor:E,bgOpacity:O,shadowOpacity:L,bgBlur:A,iconColorOpacity:I,iconColor:T,iconFilter:V,iconStyles:D,haStyle:z,themeBgColor:M,color:B}=h(t,l,n),q=l.auto_close||!1,H=l.hash,U=l.trigger_entity?l.trigger_entity:"",Y=l.trigger_state?l.trigger_state:"",F=!!l.trigger_close&&l.trigger_close;if(t.errorTriggered)return;t.initStyleAdded||t.popUp||r||(t.card.style.marginTop="4000px",t.initStyleAdded=!0);if(setTimeout((()=>{let i=t.getRootNode().querySelector("#root");if(i&&(!t.popUp||y||r&&!t.editorModeAdded)){t.popUp=i,(()=>{let i,h,k=t.popUp,E=l.text||"",O=l.state,I=l.margin_top_mobile&&"0"!==l.margin_top_mobile?l.margin_top_mobile:"0px",T=l.margin_top_desktop&&"0"!==l.margin_top_desktop?l.margin_top_desktop:"0px",V=l.entity?"flex":"none";if(v=O?n.states[O].state:"",x=O?n.formatEntityState(n.states[O]):"",t.headerAdded){if(u){const n=t.content.querySelector("#header-container .icon-container"),o=t.content.querySelector("#header-container h2"),i=t.content.querySelector("#header-container p"),a=t.content.querySelector("#header-container .power-button");n.innerHTML="",(0,e.IU)(t,u,g,n,r),o.textContent=b,i.textContent=x,a.setAttribute("style",`display: ${V};`)}}else{const n=document.createElement("div");n.setAttribute("id","header-container");const i=document.createElement("div");n.appendChild(i);const a=document.createElement("div");a.setAttribute("class","icon-container"),i.appendChild(a),(0,e.IU)(t,u,g,a,r),s(a,l,0,o);const c=document.createElement("h2");c.textContent=b,i.appendChild(c);const d=document.createElement("p");d.textContent=x,i.appendChild(d);const p=document.createElement("ha-icon");p.setAttribute("class","power-button"),p.setAttribute("icon","mdi:power"),p.setAttribute("style",`display: ${V};`),i.appendChild(p);const h=document.createElement("button");h.setAttribute("class","close-pop-up"),h.onclick=function(){history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+H,!0)},n.appendChild(h);const m=document.createElement("ha-icon");m.setAttribute("icon","mdi:close"),h.appendChild(m),t.content.appendChild(n),t.header=i,t.headerAdded=!0}function z(){a(n,u)}function M(t){"Escape"===t.key&&($=H+!1,history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+H,!0))}function U(t){window.hash===H&&P(),c=t.touches[0].clientY,d=c}function Y(t){t.touches[0].clientY-c>300&&t.touches[0].clientY>d&&($=H+!1,history.replaceState(null,null,location.href.split("#")[0]),$=H+!1,localStorage.setItem("isManuallyClosed_"+H,!0)),d=t.touches[0].clientY}if(t.eventAdded||r||(window["checkHashRef_"+H]=function(){r||(window.hash=location.hash.split("?")[0],window.hash===H?setTimeout((function(){k.classList.remove("close-pop-up"),k.classList.add("open-pop-up"),F.querySelector(".power-button").addEventListener("click",z,{passive:!0}),window.addEventListener("keydown",M,{passive:!0}),k.addEventListener("touchstart",U,{passive:!0}),k.addEventListener("touchmove",Y,{passive:!0}),$=H+!0,document.body.style.overflow="hidden",setTimeout((()=>{window.justOpened=!0}),10),W(k,!1),P()}),0):k.classList.contains("open-pop-up")&&(setTimeout((function(){k.classList.remove("open-pop-up"),k.classList.add("close-pop-up"),F.querySelector(".power-button").removeEventListener("click",z),window.removeEventListener("keydown",M),k.removeEventListener("touchstart",U),k.removeEventListener("touchmove",Y),$=H+!1,document.body.style.overflow="",window.justOpened=!1,clearTimeout(i)}),0),setTimeout((function(){W(k,!0)}),320)))},window.addEventListener("urlChanged",window["checkHashRef_"+H],{passive:!0}),window.addEventListener("click",(function(t){if(location.hash===H&&P(),!window.justOpened)return;const e=t.composedPath();!e||e.some((t=>"HA-MORE-INFO-DIALOG"===t.nodeName))||e.some((t=>"root"===t.id&&!t.classList.contains("close-pop-up")))||$!==H+!0||setTimeout((function(){location.hash===H&&($=H+!1,history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+H,!0))}),0)}),{passive:!0}),t.eventAdded=!0),u){const o=n.states[u].attributes.rgb_color;t.rgbColor=o?(0,e.wW)(o)?"rgb(255,220,200)":`rgb(${o})`:w?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"rgba(255, 255, 255, 1",t.rgbColorOpacity=o?(0,e.wW)(o)?"rgba(255,220,200, 0.5)":`rgba(${o}, 0.5)`:u&&w?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"var(--background-color,var(--secondary-background-color))",h=(0,e._k)(B,0),t.iconFilter=o?(0,e.wW)(o)?"none":"brightness(1.1)":"none"}else h=(0,e._k)(B,0);let F=t.content;function W(t,e){for(var n=t.querySelectorAll("video"),o=0;o0&&!n[o].paused&&!n[o].ended&&n[o].readyState>n[o].HAVE_CURRENT_DATA;e&&i?n[o].pause():e||i||(n[o].play(),n[o].currentTime>0&&(n[o].currentTime=1e4))}var a=t.querySelectorAll("*");for(o=0;o0&&(i=setTimeout(R,q))}function R(){history.replaceState(null,null,location.href.split("#")[0])}const j=` \n ha-card {\n margin-top: 0 !important;\n background: none !important;\n border: none !important;\n }\n .card-content {\n width: 100% !important;\n padding: 0 !important;\n }\n #root {\n transition: all 1s !important;\n position: fixed !important;\n margin: 0 -${C}; /* 7px */\n width: 100%;\n ${l.bg_color||l.bg_opacity?"--bubble-pop-up-background-custom: "+S:""};\n background-color: var(--bubble-pop-up-background-custom, var(--bubble-pop-up-background));\n box-shadow: 0px 0px 50px rgba(0,0,0,${L/100});\n backdrop-filter: blur(${A}px);\n -webkit-backdrop-filter: blur(${A}px);\n border-radius: 42px;\n box-sizing: border-box;\n top: calc(120% + ${I} + var(--header-height));\n grid-gap: 12px !important;\n gap: 12px !important;\n grid-auto-rows: min-content;\n padding: 18px 18px 220px 18px !important;\n height: 100% !important;\n -ms-overflow-style: none; /* for Internet Explorer, Edge */\n scrollbar-width: none; /* for Firefox */\n overflow-y: auto; \n overflow-x: hidden; \n z-index: 1 !important; /* Higher value hide the more-info panel */\n /* For older Safari but not working with Firefox */\n /* display: grid !important; */ \n }\n #root.hidden {\n \tdisplay: none !important;\n }\n #root > :first-child::after {\n content: '';\n display: block;\n position: sticky;\n top: 0;\n left: -50px;\n margin: -70px 0 -36px -36px;\n overflow: visible;\n width: 200%;\n height: 100px;\n background: linear-gradient(0deg, ${h} 0%, ${S} 80%);\n z-index: 0;\n } \n #root::-webkit-scrollbar {\n display: none; /* for Chrome, Safari, and Opera */\n }\n #root > :first-child {\n position: sticky;\n top: 0;\n z-index: 1;\n background: none !important;\n overflow: visible;\n }\n #root.open-pop-up {\n /*will-change: transform;*/\n transform: translateY(-120%);\n transition: transform .36s !important;\n }\n #root.open-pop-up > * {\n /* Block child items to overflow and if they do clip them */\n /*max-width: calc(100vw - 38px);*/\n max-width: 100% !important;\n /*overflow-x: clip;*/\n }\n #root.close-pop-up { \n transform: translateY(-20%);\n transition: transform .4s !important;\n box-shadow: none;\n }\n @media only screen and (min-width: 600px) {\n #root {\n top: calc(120% + ${T} + var(--header-height));\n width: calc(${m}${"%"!==f[2]||_?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${f[1]/2}${f[2]});\n margin: 0 !important;\n }\n } \n @media only screen and (min-width: 870px) {\n #root {\n left: calc(50% - ${f[1]/2}${f[2]} + ${_?"0px":"var(--mdc-drawer-width) "+("%"===f[2]?"":"/ 2")});\n }\n } \n #root.editor {\n position: inherit !important;\n width: 100% !important;\n padding: 18px !important;\n }\n `,X=`\n ${D}\n\n ha-card {\n margin-top: 0 !important;\n }\n #header-container {\n display: inline-flex;\n ${g||b||u||v||E?"":"flex-direction: row-reverse;"}\n height: 50px;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n #header-container > div {\n display: ${g||b||u||v||E?"inline-flex":"none"};\n align-items: center;\n position: relative;\n padding-right: 6px;\n z-index: 1;\n flex-grow: 1;\n background-color: ${u?t.rgbColorOpacity:"var(--background-color,var(--secondary-background-color))"};\n transition: background 1s;\n border-radius: 25px;\n margin-right: 14px;\n backdrop-filter: blur(14px);\n -webkit-backdrop-filter: blur(14px);\n }\n #header-container h2 {\n display: inline-flex;\n margin: 0 18px 0 0;\n padding: 4px;\n z-index: 1;\n font-size: 18px;\n }\n #header-container p {\n display: inline-flex;\n font-size: 16px;\n min-width: fit-content ;\n }\n .power-button {\n cursor: pointer; \n flex-grow: inherit; \n width: 24px;\n height: 24px;\n border-radius: 12px;\n margin: 0 10px;\n background: none !important;\n justify-content: flex-end;\n background-color: var(--background-color,var(--secondary-background-color));\n }\n .close-pop-up {\n height: 50px;\n width: 50px;\n border: none;\n border-radius: 50%;\n z-index: 1;\n background: var(--background-color,var(--secondary-background-color));\n color: var(--primary-text-color);\n flex-shrink: 0;\n cursor: pointer;\n }\n `;t.popUpStyleAdded||((0,e.L2)(n,t,j,p,v,u,"","",k),t.popUpStyleAdded=!0),(0,e.L2)(n,t,X,p,v,u,y)})();const h=new Event("popUpInitialized");window.dispatchEvent(h),r&&(t.popUp.classList.add("editor"),t.editorModeAdded=!0)}else!r&&t.popUp&&(t.popUp.classList.remove("editor"),t.editorModeAdded=!1)}),0),t.popUp&&U&&y){null===localStorage.getItem("previousTriggerState_"+H)&&localStorage.setItem("previousTriggerState_"+H,""),null===localStorage.getItem("isManuallyClosed_"+H)&&localStorage.setItem("isManuallyClosed_"+H,"false"),null===localStorage.getItem("isTriggered_"+H)&&localStorage.setItem("isTriggered_"+H,"false");let e=localStorage.getItem("previousTriggerState_"+H),o="true"===localStorage.getItem("isManuallyClosed_"+H),a="true"===localStorage.getItem("isTriggered_"+H);n.states[U].state!==Y||null!==e||a||(i(0,H),a=!0,localStorage.setItem("isTriggered_"+H,a)),n.states[U].state!==e&&(o=!1,localStorage.setItem("previousTriggerState_"+H,n.states[U].state),localStorage.setItem("isManuallyClosed_"+H,o)),n.states[U].state!==Y||o?n.states[U].state!==Y&&F&&t.popUp.classList.contains("open-pop-up")&&a&&!o&&(history.replaceState(null,null,location.href.split("#")[0]),$=H+!1,a=!1,o=!0,localStorage.setItem("isManuallyClosed_"+H,o),localStorage.setItem("isTriggered_"+H,a)):(i(0,H),a=!0,localStorage.setItem("isTriggered_"+H,a))}}const g=Object.getPrototypeOf(customElements.get("ha-panel-lovelace")),b=g.prototype.html,m=g.prototype.css;let f;!function(){if(!window.eventAdded){const t=new Event("urlChanged");function e(){let e=0;window.dispatchEvent(t);const n=setInterval((()=>{e<10?(window.dispatchEvent(t),e++):clearInterval(n)}),1e3)}window.popUpInitialized=!1,["click","mousedown","touchstart","focus","location-changed","connection-status"].forEach((t=>{window.addEventListener(t,e)}),{passive:!0});const n=()=>{window.dispatchEvent(t),window.addEventListener("popstate",e,{passive:!0})};window.addEventListener("popUpInitialized",n,{passive:!0}),window.eventAdded=!0}}();class _ extends HTMLElement{set hass(t){var n;switch(this._hass=t,f=document.querySelector("body > home-assistant").shadowRoot.querySelector("home-assistant-main").shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace").shadowRoot.querySelector("hui-root").shadowRoot.querySelector("div").classList.contains("edit-mode"),this.editor=f,(n=this).content||(n.attachShadow({mode:"open"}),n.shadowRoot.innerHTML='\n \n
\n
\n
\n ',n.card=n.shadowRoot.querySelector("ha-card"),n.content=n.shadowRoot.querySelector("div")),this.config.card_type){case"pop-up":u(this);break;case"horizontal-buttons-stack":!function(t){const n=t._hass,a=t.editor;let{customStyles:r,entityId:s,icon:l,name:c,widthDesktop:d,widthDesktopDivided:p,isSidebarHidden:u,state:g,stateChanged:b,stateOn:m,riseAnimation:f,marginCenter:_,popUpOpen:v,rgbaColor:y,rgbColor:w,bgOpacity:x,shadowOpacity:k,bgBlur:C,iconColorOpacity:$,iconColor:S,iconFilter:E,iconStyles:O,haStyle:L,themeBgColor:A,color:I}=h(t,t.config,n);if(!t.buttonsAdded){const e=document.createElement("div");e.classList.add("horizontal-buttons-stack-container"),t.content.appendChild(e),t.buttonsContainer=e}const T=(t,o,i)=>{if(n.states[o].attributes.rgb_color){const i=n.states[o].attributes.rgb_color,a=(0,e.wW)(i)?"rgba(255,220,200, 0.5)":`rgba(${i}, 0.5)`;t.style.backgroundColor=a,t.style.border="1px solid rgba(0,0,0,0)"}else n.states[o].attributes.rgb_color||"on"!=n.states[o].state?(t.style.backgroundColor="rgba(0,0,0,0)",t.style.border="1px solid var(--primary-text-color)"):(t.style.backgroundColor="rgba(255,255,255,0.5)",t.style.border="1px solid rgba(0,0,0,0)")};let V=[],D=1;for(;t.config[D+"_link"];){const e=D+"_",n=t.config[e+"name"]||"",o=t.config[e+"pir_sensor"];l=t.config[e+"icon"]||"";const i=t.config[e+"link"],a=t.config[e+"entity"];V.push({button:n,pirSensor:o,icon:l,link:i,lightEntity:a}),D++}if(t.config.auto_order&&V.sort(((t,e)=>t.pirSensor&&e.pirSensor?"on"===n.states[t.pirSensor].state&&"on"===n.states[e.pirSensor].state?n.states[t.pirSensor].last_updated{const a=((e,n,a)=>{const r=document.createElement("button");return r.setAttribute("class",`button ${n.substring(1)}`),r.innerHTML=`\n ${""!==a?``:""}\n ${""!==e?`

${e}

`:""}\n `,r.hasListener||(r.addEventListener("click",(t=>{t.stopPropagation(),o("light"),v=location.hash+!0,localStorage.getItem("isManuallyClosed_"+n),v!==n+!0?(i(0,n),v=n+!0):(history.replaceState(null,null,location.href.split("#")[0]),v=n+!1)}),{passive:!0}),window.addEventListener("urlChanged",(function(){t.config.highlightCurrentview&&(location.pathname===n||location.hash===n?r.classList.add("highlight"):r.classList.remove("highlight"))}),{passive:!0}),r.hasListener=!0),r})(n.button,n.link,n.icon);e[n.link]=a,t.buttonsContainer.appendChild(a)})),t.buttonsAdded=!0,t.buttons=e}let z=0;!async function(t){if(t.buttonsUpdated)return;let e=[];for(let n of V)t.buttons[n.link]&&(e.push(localStorage.getItem(`buttonWidth-${n.link}`)),e.push(localStorage.getItem(`buttonContent-${n.link}`)));let n=await Promise.all(e),o=0;for(let e of V){let i=t.buttons[e.link];if(i){let r=n[o],s=n[o+1];o+=2,r&&"0"!==r&&s===i.innerHTML&&!a||(r=i.offsetWidth,await localStorage.setItem(`buttonWidth-${e.link}`,r),await localStorage.setItem(`buttonContent-${e.link}`,i.innerHTML),t.previousConfig=t.config),i.style.transform=`translateX(${z}px)`,z+=parseInt(r)+12}e.lightEntity&&T(i,e.lightEntity,e.link)}t.buttonsAdded=!0}(t);const M=`\n ha-card {\n border-radius: 0;\n }\n .horizontal-buttons-stack {\n width: 100%;\n margin-top: 0 !important;\n background: none !important;\n position: fixed;\n height: 51px;\n bottom: 16px;\n left: ${_};\n z-index: 1 !important; /* Higher value hide the more-info panel */\n }\n @keyframes from-bottom {\n 0% {transform: translateY(200px);}\n 20% {transform: translateY(200px);}\n 46% {transform: translateY(-8px);}\n 56% {transform: translateY(1px);}\n 62% {transform: translateY(-2px);}\n 70% {transform: translateY(0);}\n 100% {transform: translateY(0);}\n }\n .horizontal-buttons-stack-container {\n width: max-content;\n position: relative;\n height: 51px;\n }\n .button {\n display: inline-flex;\n position: absolute;\n box-sizing: border-box !important;\n border: 1px solid var(--primary-text-color);\n align-items: center;\n height: 50px;\n line-height: 16px;\n white-space: nowrap;\n width: auto;\n border-radius: 25px;\n z-index: 1;\n padding: 0 16px;\n background: none;\n transition: background-color 1s, border 1s, transform 1s;\n color: var(--primary-text-color);\n }\n .highlight {\n animation: pulse 1.4s infinite alternate;\n }\n @keyframes pulse {\n 0% {\n filter: brightness(0.7);\n }\n 100% {\n filter: brightness(1.3);\n }\n }\n .icon {\n height: 24px;\n }\n .card-content {\n width: calc(100% + 18px);\n box-sizing: border-box !important;\n margin: 0 -36px !important;\n padding: 0 36px !important;\n overflow: scroll !important;\n -ms-overflow-style: none;\n scrollbar-width: none;\n -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 1) calc(0% + 28px), rgba(0, 0, 0, 1) calc(100% - 28px), transparent 100%);\n /* mask-image: linear-gradient(90deg, transparent 2%, rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 1) 96%, transparent 100%); */\n /* -webkit-mask-image: linear-gradient(90deg, transparent 2%, rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 1) 96%, transparent 100%); */\n }\n .horizontal-buttons-stack::before {\n content: '';\n position: absolute;\n top: -32px;\n left: -100%;\n display: block;\n background: linear-gradient(0deg, var(--background-color, var(--primary-background-color)) 50%, rgba(79, 69, 87, 0));\n width: 200%;\n height: 100px;\n }\n .card-content::-webkit-scrollbar {\n display: none;\n }\n @media only screen and (min-width: 600px) {\n .card-content {\n position: fixed;\n width: ${d} !important;\n left: calc(50% - ${p[1]/2}${p[2]});\n margin-left: -13px !important;\n padding: 0 26px !important;\n }\n }\n @media only screen and (min-width: 870px) {\n .card-content {\n position: fixed;\n width: calc(${d}${"%"!==p[2]||u?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${p[1]/2}${p[2]} + ${!0===u?"0px":"var(--mdc-drawer-width) "+("%"===p[2]?"":"/ 2")});\n margin-left: -13px !important;\n padding: 0 26px !important;\n }\n }\n .horizontal-buttons-stack.editor {\n position: relative;\n bottom: 0;\n left: 0;\n overflow: hidden;\n }\n .horizontal-buttons-stack.editor::before {\n top: -32px;\n left: -100%;\n background: none;\n width: 100%;\n height: 0;\n }\n .horizontal-buttons-stack-container.editor > .button {\n transition: background-color 0s, border 0s, transform 0s;\n }\n .horizontal-buttons-stack-container.editor {\n margin-left: 1px;\n }\n .horizontal-buttons-stack.editor > .card-content {\n position: relative;\n width: calc(100% + 26px) !important;\n left: -26px;\n margin: 0 !important;\n padding: 0;\n }\n `;!window.hasAnimated&&f&&(t.content.style.animation="from-bottom 1.3s forwards",window.hasAnimated=!0,setTimeout((()=>{t.content.style.animation="none"}),1500)),(0,e.L2)(n,t,M,r),a?(t.buttonsContainer.classList.add("editor"),t.card.classList.add("editor")):(t.buttonsContainer.classList.remove("editor"),t.card.classList.remove("editor"))}(this);break;case"button":!function(t){const n=t._hass,i=t.editor;let{customStyles:r,entityId:l,icon:c,name:d,widthDesktop:p,widthDesktopDivided:u,isSidebarHidden:g,state:b,stateChanged:m,stateOn:f,formatedState:_,riseAnimation:v,marginCenter:y,popUpOpen:w,rgbaColor:x,rgbColor:k,bgOpacity:C,shadowOpacity:$,bgBlur:S,iconColorOpacity:E,iconColor:O,iconFilter:L,iconStyles:A,haStyle:I,themeBgColor:T,color:V}=h(t,t.config,n);_=m||i?n.formatEntityState(n.states[l]):_||"";const D=t.config.button_type||"switch",z=!!t.config.show_state&&t.config.show_state;let M=l?n.states[l].attributes.brightness||0:"",B=l?n.states[l].attributes.volume_level||0:"",q=!1,H=M,U=B,Y=0,F=0,W=0,P=!1,R=null;if(!t.buttonAdded){const e=document.createElement("div");e.setAttribute("class","button-container"),t.content.appendChild(e)}const j=document.createElement("div");j.setAttribute("class","icon-container"),t.iconContainer=j;const X=document.createElement("div");X.setAttribute("class","name-container");const N=document.createElement("div");N.setAttribute("class","switch-button");const G=document.createElement("div");G.setAttribute("class","range-slider");const K=document.createElement("div");if(K.setAttribute("class","range-fill"),!t.buttonContainer||i){if(i&&t.buttonContainer){for(;t.buttonContainer.firstChild;)t.buttonContainer.removeChild(t.buttonContainer.firstChild);t.eventAdded=!1,t.wasEditing=!0}t.buttonContainer=t.content.querySelector(".button-container"),"slider"!==D||t.buttonAdded&&!i?("switch"===D||"custom"===D||i)&&(t.buttonContainer.appendChild(N),N.appendChild(j),N.appendChild(X),t.switchButton=t.content.querySelector(".switch-button")):(t.buttonContainer.appendChild(G),G.appendChild(j),G.appendChild(X),G.appendChild(K),t.rangeFill=t.content.querySelector(".range-fill")),(0,e.IU)(t,l,c,j,i),X.innerHTML=`\n

${d}

\n ${z?`

${_}

`:""}\n `,t.buttonAdded=!0}function Z(t){o("success");let e=t.querySelector(".feedback-element");e||(e=document.createElement("div"),e.setAttribute("class","feedback-element"),t.appendChild(e)),e.style.animation="tap-feedback .5s",setTimeout((()=>{e.style.animation="none",t.removeChild(e)}),500)}function J(t){Y=t.pageX||(t.touches?t.touches[0].pageX:0),F=t.pageY||(t.touches?t.touches[0].pageY:0),W=G.value,t.target!==j&&t.target!==j.querySelector("ha-icon")&&(q=!0,document.addEventListener("mouseup",tt,{passive:!0}),document.addEventListener("touchend",tt,{passive:!0}),document.addEventListener("mousemove",Q,{passive:!0}),document.addEventListener("touchmove",Q,{passive:!0}),R=setTimeout((()=>{ot(t.pageX||t.touches[0].pageX),et(),R=null}),200))}function Q(t){const e=t.pageX||(t.touches?t.touches[0].pageX:0),n=t.pageY||(t.touches?t.touches[0].pageY:0);Math.abs(n-F)>Math.abs(e-Y)?(clearTimeout(R),tt()):(document.removeEventListener("mousemove",Q),document.removeEventListener("touchmove",Q),document.addEventListener("mousemove",nt,{passive:!0}),document.addEventListener("touchmove",nt,{passive:!0}))}function tt(){q=!1,P=!1,et(),document.removeEventListener("mouseup",tt),document.removeEventListener("touchend",tt),document.removeEventListener("mousemove",nt),document.removeEventListener("touchmove",nt)}function et(){l.startsWith("light.")?(M=H,n.callService("light","turn_on",{entity_id:l,brightness:M})):l.startsWith("media_player.")&&(B=U,n.callService("media_player","volume_set",{entity_id:l,volume_level:B}))}function nt(t){const e=t.pageX||(t.touches?t.touches[0].pageX:0),n=t.pageY||(t.touches?t.touches[0].pageY:0);q&&Math.abs(e-Y)>10?(o("light"),ot(e)):q&&Math.abs(n-F)>10&&(q=!1,G.value=W)}function ot(t){const e=G.getBoundingClientRect(),n=Math.min(Math.max(t-e.left,0),e.width)/e.width;l.startsWith("light.")?H=Math.round(255*n):l.startsWith("media_player.")&&(U=n),K.style.transition="none",K.style.transform=`translateX(${100*n}%)`}z&&_&&(t.content.querySelector(".state").textContent=_),t.eventAdded||"switch"!==D?t.eventAdded||"slider"!==D?t.eventAdded||"custom"!==D||(N.addEventListener("click",(()=>Z(t.switchButton)),{passive:!0}),s(j,t.config,0,o),t.eventAdded=!0):(G.addEventListener("mousedown",J,{passive:!0}),G.addEventListener("touchstart",J,{passive:!0}),s(j,t.config,0,o),t.eventAdded=!0):(N.addEventListener("click",(()=>Z(t.switchButton)),{passive:!0}),N.addEventListener("click",(function(t){t.target!==j&&t.target!==j.querySelector("ha-icon")&&a(n,l)}),{passive:!0}),s(j,t.config,0,o),t.eventAdded=!0),t.isDragging||"slider"!==D||(t.rangeFill.style.transition="all .3s",l.startsWith("light.")?t.rangeFill.style.transform=`translateX(${M/255*100}%)`:l.startsWith("media_player.")&&(t.rangeFill.style.transform=`translateX(${100*B}%)`));const it=`\n ha-card {\n margin-top: 0 !important;\n background: none !important;\n opacity: ${"unavailable"!==b?"1":"0.5"};\n }\n \n .button-container {\n position: relative;\n width: 100%;\n height: 50px;\n z-index: 0;\n background-color: var(--background-color-2,var(--secondary-background-color));\n border-radius: 25px;\n mask-image: radial-gradient(white, black);\n -webkit-mask-image: radial-gradient(white, black);\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n -webkit-transform: translateZ(0);\n overflow: hidden;\n }\n \n .switch-button,\n .range-slider {\n display: inline-flex;\n position: absolute;\n height: 100%;\n width: 100%;\n transition: background-color 1.5s;\n background-color: ${f&&["switch","custom"].includes(D)?"var(--accent-color)":"rgba(0,0,0,0)"};\n }\n\n .range-fill {\n z-index: -1;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n background-color: ${E};\n width: 100%;\n left: -100%;\n }\n \n .switch-button {\n cursor: pointer !important;\n }\n \n .range-slider {\n cursor: ew-resize;\n }\n \n .name-container {\n position: relative;\n display: ${z?"block":"inline-flex"};\n margin-left: 4px;\n z-index: 1;\n font-weight: 600;\n align-items: center;\n line-height: ${z?"4px":"16px"};\n padding-right: 16px;\n }\n \n .state {\n font-size: 12px;\n opacity: 0.7;\n }\n \n .feedback-element {\n position: absolute;\n top: 0;\n left: 0;\n opacity: 0;\n width: 100%;\n height: 100%;\n background-color: rgb(0,0,0);\n }\n \n @keyframes tap-feedback {\n 0% {transform: translateX(-100%); opacity: 0;}\n 64% {transform: translateX(0); opacity: 0.1;}\n 100% {transform: translateX(100%); opacity: 0;}\n }\n\n ${A}\n `;(0,e.L2)(n,t,it,r,b,l,m)}(this);break;case"separator":!function(t){const n=t._hass,o=t.editor,i=t.config;let{customStyles:a,entityId:r,icon:s,name:l,widthDesktop:c,widthDesktopDivided:d,isSidebarHidden:p,state:u,stateChanged:g,stateOn:b,formatedState:m,riseAnimation:f,marginCenter:_,popUpOpen:v,rgbaColor:y,rgbColor:w,bgOpacity:x,shadowOpacity:k,bgBlur:C,iconColorOpacity:$,iconColor:S,iconFilter:E,iconStyles:O,haStyle:L,themeBgColor:A,color:I}=h(t,i,n);if(!t.separatorAdded||o){if(o&&t.separatorContainer)for(;t.separatorContainer.firstChild;)t.separatorContainer.removeChild(t.separatorContainer.firstChild);t.separatorAdded||(t.separatorContainer=document.createElement("div"),t.separatorContainer.setAttribute("class","separator-container")),t.separatorContainer.innerHTML=`\n
\n \n

${l}

\n
\n
\n `,t.content.appendChild(t.separatorContainer),t.separatorAdded=!0}(0,e.L2)(n,t,"\n .separator-container {\n display: inline-flex;\n width: 100%;\n margin-top: 12px;\n }\n .separator-container div:first-child {\n display: inline-flex;\n max-width: calc(100% - 38px);\n }\n .separator-container div ha-icon {\n display: inline-flex;\n height: 24px;\n width: 24px;\n margin: 0 22px 0 8px;\n transform: translateY(-2px);\n }\n .separator-container div h4 {\n display: inline-flex;\n margin: 0 20px 0 0;\n font-size: 16px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .separator-container div:last-child {\n display: inline-flex; \n border-radius: 6px; \n opacity: 0.5; \n margin-left: 10px; \n flex-grow: 1; \n height: 6px; \n align-self: center; \n background-color: var(--background-color,var(--secondary-background-color));\n }\n ",a)}(this);break;case"cover":!function(t){const n=t._hass,i=t.editor,a=t.config;let{customStyles:r,entityId:l,icon:c,name:d,widthDesktop:p,widthDesktopDivided:u,isSidebarHidden:g,state:b,stateChanged:m,stateOn:f,formatedState:_,riseAnimation:v,marginCenter:y,popUpOpen:w,rgbaColor:x,rgbColor:k,bgOpacity:C,shadowOpacity:$,bgBlur:S,iconColorOpacity:E,iconColor:O,iconFilter:L,iconStyles:A,haStyle:I,themeBgColor:T,color:V}=h(t,a,n);const D=a.icon_open?a.icon_open:"mdi:window-shutter-open",z=a.icon_close?a.icon_close:"mdi:window-shutter",M=a.open_service?a.open_service:"cover.open_cover",B=a.close_service?a.close_service:"cover.close_cover",q=a.stop_service?a.stop_service:"cover.stop_cover",H=a.icon_up?a.icon_up:"mdi:arrow-up",U=a.icon_down?a.icon_down:"mdi:arrow-down",Y=!!t.config.show_state&&t.config.show_state;if(c="open"===n.states[a.entity].state?D:z,_=m?n.formatEntityState(n.states[l]):_||"",!t.coverAdded||i){if(i&&t.coverContainer)for(;t.coverContainer.firstChild;)t.coverContainer.removeChild(t.coverContainer.firstChild);t.coverContainer=document.createElement("div"),t.coverContainer.setAttribute("class","cover-container"),t.coverContainer.innerHTML=`\n
\n
\n
\n
\n

${d}

\n

\n
\n
\n
\n \n \n \n
\n `,t.content.appendChild(t.coverContainer);const e=t.coverContainer.querySelector(".open"),r=t.coverContainer.querySelector(".stop"),c=t.coverContainer.querySelector(".close");e.addEventListener("click",(()=>{n.callService(M.split(".")[0],M.split(".")[1],{entity_id:l})}),{passive:!0}),r.addEventListener("click",(()=>{n.callService(q.split(".")[0],q.split(".")[1],{entity_id:l})}),{passive:!0}),c.addEventListener("click",(()=>{n.callService(B.split(".")[0],B.split(".")[1],{entity_id:l})}),{passive:!0}),t.iconContainer=t.content.querySelector(".icon-container"),s(t.iconContainer,a,0,o),t.coverAdded=!0}t.iconContainer&&(m||i)&&(t.iconContainer.innerHTML=``,t.content.querySelector(".state").textContent=Y?_:""),(0,e.L2)(n,t,"\n ha-card {\n margin-top: 0 !important;\n background: none !important;\n }\n \n .header-container {\n display: flex;\n align-items: center;\n margin-bottom: 10px;\n }\n \n .cover-container {\n display: grid;\n }\n \n .icon-container {\n display: flex;\n margin: 0 !important;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n /*z-index: 1;*/\n width: 48px;\n height: 48px;\n margin: 6px;\n border-radius: 50%;\n background-color: var(--card-background-color,var(--ha-card-background));\n border: 6px solid var(--background-color-2,var(--secondary-background-color));\n box-sizing: border-box;\n }\n \n .name-container {\n font-weight: 600;\n margin-left: 10px;\n line-height: 4px;\n }\n \n .buttons-container {\n display: grid;\n align-self: center;\n grid-auto-flow: column;\n grid-gap: 18px; \n }\n \n .state {\n font-size: 12px;\n opacity: 0.7;\n }\n \n ha-icon {\n display: flex; \n height: 24px; \n width: 24px; \n color: var(--primary-text-color);\n }\n \n .button {\n display: flex;\n background: var(--background-color-2,var(--secondary-background-color));\n height: 42px;\n border-radius: 32px;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n }\n ",r,b,l)}(this);break;case"empty-column":!function(t){if(!t.emptyCollumnAdded){const e=document.createElement("div");e.setAttribute("class","empty-column"),e.innerHTML='\n
\n ',t.content.appendChild(e),t.emptyColumnAdded=!0}}(this)}}setConfig(t){if("pop-up"===t.card_type){if(!t.hash)throw new Error("You need to define an hash. Please note that this card must be placed inside a vertical_stack to work as a pop-up.")}else if("horizontal-buttons-stack"===t.card_type){var e={};for(var n in t)if(n.match(/^\d+_icon$/)){var o=n.replace("_icon","_link");if(void 0===t[o])throw new Error("You need to define "+o);if(e[t[o]])throw new Error("You can't use "+t[o]+" twice");e[t[o]]=!0}}else if(("button"===t.card_type||"cover"===t.card_type)&&!t.entity)throw new Error("You need to define an entity");if(window.entityError)throw new Error("You need to define a valid entity");this.config=t}getCardSize(){return-1e4}static getConfigElement(){return document.createElement("bubble-card-editor")}}customElements.define("bubble-card",_),customElements.define("bubble-card-editor",class extends g{setConfig(t){this._config={...t}}static get properties(){return{hass:{},_config:{}}}get _card_type(){return this._config.card_type||""}get _button_type(){return this._config.button_type||"switch"}get _entity(){return this._config.entity||""}get _name(){return this._config.name||""}get _icon(){return this._config.icon||""}get _state(){return this._config.state||""}get _text(){return this._config.text||""}get _hash(){return this._config.hash||"#pop-up-name"}get _trigger_entity(){return this._config.trigger_entity||""}get _trigger_state(){return this._config.trigger_state||""}get _trigger_close(){return this._config.trigger_close||!1}get _margin(){return this._config.margin||"7px"}get _margin_top_mobile(){return this._config.margin_top_mobile||"0px"}get _margin_top_desktop(){return this._config.margin_top_desktop||"0px"}get _width_desktop(){return this._config.width_desktop||"540px"}get _bg_color(){return this._config.bg_color||window.color}get _bg_opacity(){return void 0!==this._config.bg_opacity?this._config.bg_opacity:"88"}get _bg_blur(){return void 0!==this._config.bg_blur?this._config.bg_blur:"14"}get _shadow_opacity(){return void 0!==this._config.shadow_opacity?this._config.shadow_opacity:"0"}get _is_sidebar_hidden(){return this._config.is_sidebar_hidden||!1}get _rise_animation(){return void 0===this._config.rise_animation||this._config.rise_animation}get _auto_close(){return this._config.auto_close||""}get _back_open(){return this._config.back_open||!1}get _icon_open(){return this._config.icon_open||""}get _icon_close(){return this._config.icon_close||""}get _open_service(){return this._config.open_service||"cover.open_cover"}get _close_service(){return this._config.open_service||"cover.close_cover"}get _stop_service(){return this._config.open_service||"cover.stop_cover"}get _auto_order(){return this._config.auto_order||!1}get _highlightCurrentview(){return this._config.highlightCurrentview||!1}get _show_state(){return this._config.show_state||!1}render(){if(!this.hass)return b``;if(!this.listsUpdated){const t=t=>({label:t,value:t});this.allEntitiesList=Object.keys(this.hass.states).map(t),this.lightList=Object.keys(this.hass.states).filter((t=>"light"===t.substr(0,t.indexOf(".")))).map(t),this.sensorList=Object.keys(this.hass.states).filter((t=>"sensor"===t.substr(0,t.indexOf(".")))).map(t),this.binarySensorList=Object.keys(this.hass.states).filter((t=>"binary_sensor"===t.substr(0,t.indexOf(".")))).map(t),this.coverList=Object.keys(this.hass.states).filter((t=>"cover"===t.substr(0,t.indexOf(".")))).map(t),this.cardTypeList=[{label:"Button",value:"button"},{label:"Cover",value:"cover"},{label:"Empty column",value:"empty-column"},{label:"Horizontal buttons stack",value:"horizontal-buttons-stack"},{label:"Pop-up",value:"pop-up"},{label:"Separator",value:"separator"}],this.buttonTypeList=[{label:"Switch",value:"switch"},{label:"Slider",value:"slider"}],this.listsUpdated=!0}const t=this.allEntitiesList,e=(this.lightList,this.sensorList,this.coverList),n=this.cardTypeList,o=this.buttonTypeList;if("pop-up"===this._config.card_type)return b` +(()=>{"use strict";var __webpack_modules__={946:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{G:()=>getIconStyles,IU:()=>createIcon,L2:()=>addStyles,_k:()=>convertToRGBA,mk:()=>getIconColor,wW:()=>isColorCloseToWhite});const addStyles=function(hass,context,styles,customStyles,state,entityId,stateChanged,path="",element=context.content){const customStylesEval=customStyles?eval("`"+customStyles+"`"):"";let styleAddedKey=styles+"Added";if(!context[styleAddedKey]||context.previousStyle!==customStylesEval||stateChanged||context.previousConfig!==context.config){if(!context[styleAddedKey]){if(context.styleElement=element.querySelector("style"),!context.styleElement){context.styleElement=document.createElement("style");const t=path?element.querySelector(path):element;t?.appendChild(context.styleElement)}context[styleAddedKey]=!0}context.styleElement.innerHTML!==customStylesEval+styles&&(context.styleElement.innerHTML=customStylesEval+styles),context.previousStyle=customStylesEval,context.previousConfig=context.config}};function createIcon(t,e,n,o,i){let a=t._hass,r=!(!e||!a.states[e].attributes)&&a.states[e].attributes;t.imageUrl=!!r.entity_picture&&r.entity_picture,updateIcon(t,a,e,n,o),i||setInterval((()=>{a=t._hass,e&&a.states[e]&&(t.currentEntityPicture=a.states[e].attributes.entity_picture,t.currentEntityPicture!==t.previousEntityPicture&&(t.imageUrl=t.currentEntityPicture,updateIcon(t,a,e,n,o),t.previousEntityPicture=t.currentEntityPicture))}),1e3)}function updateIcon(t,e,n,o,i){for(;i.firstChild;)i.removeChild(i.firstChild);let a=t.config.icon&&t.config.icon.includes("/")?t.config.icon:t.imageUrl?t.imageUrl:"";if(a&&(r=e.states[n].state,n.startsWith("media_player.")&&!["off","unknown","idle",void 0].includes(r)||!n.startsWith("media_player."))){const t=document.createElement("div");t.setAttribute("class","entity-picture"),t.setAttribute("alt","Icon"),i&&(i.appendChild(t),i.style.background="center / cover no-repeat url("+a+"), var(--card-background-color,var(--ha-card-background))")}else{const t=document.createElement("ha-icon");t.setAttribute("icon",o),t.setAttribute("class","icon"),i&&i.appendChild(t)}var r}function isColorCloseToWhite(t){let e=[220,220,190];for(let n=0;n<3;n++)if(t[n]{for(var n in e)__webpack_require__.o(e,n)&&!__webpack_require__.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},__webpack_require__.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var __webpack_exports__={};(()=>{var t="v1.6.0-beta.3";const e=function(){try{return document.querySelector("body > home-assistant").shadowRoot.querySelector("home-assistant-main").shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace").shadowRoot.querySelector("hui-root").shadowRoot.querySelector("div")}catch(t){return}}();function n(){if(e)return e.classList.contains("edit-mode")}var o=__webpack_require__(946);const i=(t,e,n,o)=>{o=o||{},n=null==n?{}:n;const i=new Event(e,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return i.detail=n,t.dispatchEvent(i),i},a=t=>{i(window,"haptic",t)},r=(t,e,n=!1)=>{n?history.replaceState(null,"",e):history.pushState(null,"",e),i(window,"location-changed",{replace:n})};function s(t,e){t.callService("homeassistant","toggle",{entity_id:e})}function l(t,e,n){const o={entity:e.entity,tap_action:{action:"more-info"},double_tap_action:{action:"toggle"},hold_action:{action:"toggle"}},i=new Event("hass-action",{bubbles:!0,composed:!0});i.detail={config:o,action:n},t.dispatchEvent(i)}function c(t,e,n,o){e.tap_action,e.double_tap_action,e.hold_action;let i,a,r=!1,s=0,c=0,d=0,p=0;t.addEventListener("mousedown",(()=>{d=Date.now(),a=setTimeout((()=>{l(t,e,"hold")}),300)}),{passive:!0}),t.addEventListener("mouseup",(()=>{clearTimeout(a),p=Date.now(),p-d<300&&(c++,1===c&&setTimeout((()=>{1===c?l(t,e,"tap"):(l(t,e,"double_tap"),o("success")),c=0}),300)),d=0,p=0}),{passive:!0}),t.addEventListener("touchstart",(n=>{r=!0,r&&o("light"),d=Date.now(),a=setTimeout((()=>{l(t,e,"hold")}),300),"touchstart"!==n.type&&n.preventDefault()}),{passive:!0}),t.addEventListener("touchend",(function(n){let o=(new Date).getTime(),r=o-s;clearTimeout(a),r<500&&r>0?(clearTimeout(i),l(t,e,"double_tap")):i=setTimeout((function(){l(t,e,"tap")}),300),s=o}),{passive:!0}),t.addEventListener("mouseout",(()=>{clearTimeout(a)}),{passive:!0}),t.addEventListener("touchcancel",(()=>{clearTimeout(a)}),{passive:!0})}let d,p,h,u;function g(t,e,n,i){let a=e.styles?e.styles:"",r=e.entity&&n.states[e.entity]?e.entity:"",s=!e.icon&&r?n.states[r].attributes.icon||n.states[r].attributes.entity_picture||"":e.icon||"",l=e.name?e.name:r?n.states[r].attributes.friendly_name:"",c=e.width_desktop||"540px",g=c?c.match(/(\d+)(\D+)/):"",m=e.is_sidebar_hidden||!1,b=r?n.states[r].state:"";!function(t,e,n){t.hasState=e.states[n],t.hasState&&(t.newState=[t.hasState.state,t.hasState.attributes.rgb_color],t.oldState&&t.newState[0]===t.oldState[0]&&t.newState[1]===t.oldState[1]?t.stateChanged=!1:(t.oldState=t.newState,t.stateChanged=!0),t.stateChanged)}(t,n,r);let f=t.stateChanged,_=["on","open","cleaning","true","home","playing"].includes(b)||0!==Number(b)&&!isNaN(Number(b)),v=void 0===e.rise_animation||e.rise_animation,y=e.margin?"0"!==e.margin?e.margin:"0px":"7px",w=void 0!==e.bg_opacity?e.bg_opacity:"88",x=void 0!==e.shadow_opacity?e.shadow_opacity:"0",k=void 0!==e.bg_blur?e.bg_blur:"10",{iconColorOpacity:C,iconColor:$,iconFilter:S}=(0,o.mk)(n,r,_,o.wW),E=(0,o.G)(r,_,$,S),O=getComputedStyle(document.body),L=O.getPropertyValue("--ha-card-background")||O.getPropertyValue("--card-background-color"),A=e.bg_color?e.bg_color:L;if(A&&(!t.color||A!==t.color)){const e=1.02;p=(0,o._k)(A,w/100,e),document.body.style.setProperty("--bubble-pop-up-background",p),t.color=A,window.color=A}return{customStyles:a,entityId:r,icon:s,name:l,widthDesktop:c,widthDesktopDivided:g,isSidebarHidden:m,state:b,stateChanged:f,stateOn:_,formatedState:u,riseAnimation:v,marginCenter:y,popUpOpen:d,rgbaColor:p,rgbColor:h,bgOpacity:w,shadowOpacity:x,bgBlur:k,iconColorOpacity:C,iconColor:$,iconFilter:S,iconStyles:E,haStyle:O,themeBgColor:L,color:A}}function m(t){const e=t._hass,n=t.editor,l=t.config;if(!e)return;let d,p,{customStyles:h,entityId:u,icon:m,name:b,widthDesktop:f,widthDesktopDivided:_,isSidebarHidden:v,state:y,stateChanged:w,stateOn:x,formatedState:k,riseAnimation:C,marginCenter:$,popUpOpen:S,rgbaColor:E,rgbColor:O,bgOpacity:L,shadowOpacity:A,bgBlur:I,iconColorOpacity:T,iconColor:V,iconFilter:D,iconStyles:M,haStyle:z,themeBgColor:B,color:q}=g(t,l,e),H=l.auto_close||!1,U=l.hash,Y=l.trigger_entity?l.trigger_entity:"",W=l.trigger_state?l.trigger_state:"",F=!!l.trigger_close&&l.trigger_close;if(t.errorTriggered)return;t.initStyleAdded||t.popUp||n||(t.card.style.marginTop="4000px",t.initStyleAdded=!0);setTimeout((()=>{let r=t.getRootNode().querySelector("#root");if(r&&(!t.popUp||w||n&&!t.editorModeAdded)){t.popUp=r,(()=>{let r,g,C=t.popUp,O=l.text||"",L=l.state,T=l.margin_top_mobile&&"0"!==l.margin_top_mobile?l.margin_top_mobile:"0px",V=l.margin_top_desktop&&"0"!==l.margin_top_desktop?l.margin_top_desktop:"0px",D=l.entity?"flex":"none";if(y=L&&e.states[L]?e.states[L].state:"",k=L?e.formatEntityState(e.states[L]):"",t.headerAdded){if(u){const e=t.content.querySelector("#header-container .icon-container"),i=t.content.querySelector("#header-container h2"),a=t.content.querySelector("#header-container p"),r=t.content.querySelector("#header-container .power-button");e.innerHTML="",(0,o.IU)(t,u,m,e,n),i.textContent=b,a.textContent=k,r.setAttribute("style",`display: ${D};`)}}else{const e=document.createElement("div");e.setAttribute("id","header-container");const r=document.createElement("div");e.appendChild(r);const s=document.createElement("div");s.setAttribute("class","icon-container"),r.appendChild(s),(0,o.IU)(t,u,m,s,n),c(s,l,0,a);const d=document.createElement("h2");d.textContent=b,r.appendChild(d);const p=document.createElement("p");p.textContent=k,r.appendChild(p);const h=document.createElement("ha-icon");h.setAttribute("class","power-button"),h.setAttribute("icon","mdi:power"),h.setAttribute("style",`display: ${D};`),r.appendChild(h);const g=document.createElement("button");g.setAttribute("class","close-pop-up"),g.onclick=function(){history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+U,!0)},e.appendChild(g);const f=document.createElement("ha-icon");f.setAttribute("icon","mdi:close"),g.appendChild(f),t.content.appendChild(e),t.header=r,t.headerAdded=!0}function z(){s(e,u)}function B(t){"Escape"===t.key&&(S=U+!1,history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+U,!0))}function Y(t){window.hash===U&&R(),d=t.touches[0].clientY,p=d}function W(t){t.touches[0].clientY-d>300&&t.touches[0].clientY>p&&(S=U+!1,history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+U,!0)),p=t.touches[0].clientY}if(t.eventAdded||n||(window["checkHashRef_"+U]=function(){n||(window.hash=location.hash.split("?")[0],window.hash===U?(C.classList.remove("close-pop-up"),C.classList.add("open-pop-up"),setTimeout((function(){F.querySelector(".power-button").addEventListener("click",z,{passive:!0}),window.addEventListener("keydown",B,{passive:!0}),C.addEventListener("touchstart",Y,{passive:!0}),C.addEventListener("touchmove",W,{passive:!0}),S=U+!0,document.body.style.overflow="hidden",setTimeout((()=>{window.justOpened=!0}),10),P(C,!1),R()}),0)):C.classList.contains("open-pop-up")&&(C.classList.remove("open-pop-up"),C.classList.add("close-pop-up"),setTimeout((function(){F.querySelector(".power-button").removeEventListener("click",z),window.removeEventListener("keydown",B),C.removeEventListener("touchstart",Y),C.removeEventListener("touchmove",W),S=U+!1,document.body.style.overflow="",window.justOpened=!1,clearTimeout(r)}),0),setTimeout((function(){P(C,!0)}),320)))},window.addEventListener("urlChanged",window["checkHashRef_"+U],{passive:!0}),window.addEventListener("click",(function(t){if(window.hash===U&&R(),!window.justOpened)return;const e=t.composedPath();!e||e.some((t=>"HA-MORE-INFO-DIALOG"===t.nodeName))||e.some((t=>"root"===t.id&&!t.classList.contains("close-pop-up")))||S!==U+!0||setTimeout((function(){window.hash===U&&(S=U+!1,history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+U,!0))}),10)}),{passive:!0}),t.eventAdded=!0),u){const n=e.states[u].attributes.rgb_color;t.rgbColor=n?(0,o.wW)(n)?"rgb(255,220,200)":`rgb(${n})`:x?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"rgba(255, 255, 255, 1",t.rgbColorOpacity=n?(0,o.wW)(n)?"rgba(255,220,200, 0.5)":`rgba(${n}, 0.5)`:u&&x?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"var(--background-color,var(--secondary-background-color))",g=(0,o._k)(q,0),t.iconFilter=n?(0,o.wW)(n)?"none":"brightness(1.1)":"none"}else g=(0,o._k)(q,0);let F=t.content;function P(t,e){for(var n=t.querySelectorAll("video"),o=0;o0&&!n[o].paused&&!n[o].ended&&n[o].readyState>n[o].HAVE_CURRENT_DATA;e&&i?n[o].pause():e||i||(n[o].play(),n[o].currentTime>0&&(n[o].currentTime=1e4))}var a=t.querySelectorAll("*");for(o=0;o0&&(r=setTimeout(j,H))}function j(){history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0)}const X=` \n ha-card {\n margin-top: 0 !important;\n background: none !important;\n border: none !important;\n }\n .card-content {\n width: 100% !important;\n padding: 0 !important;\n }\n #root {\n \ttransition: transform .36s !important;\n position: fixed !important;\n margin: 0 -${$}; /* 7px */\n width: 100%;\n ${l.bg_color||l.bg_opacity?"--bubble-pop-up-background-custom: "+E:""};\n background-color: var(--bubble-pop-up-background-custom, var(--bubble-pop-up-background));\n box-shadow: 0px 0px 50px rgba(0,0,0,${A/100});\n backdrop-filter: blur(${I}px);\n -webkit-backdrop-filter: blur(${I}px);\n border-radius: 42px;\n box-sizing: border-box;\n top: calc(120% + ${T} + var(--header-height));\n grid-gap: 12px !important;\n gap: 12px !important;\n grid-auto-rows: min-content;\n padding: 18px 18px 220px 18px !important;\n height: 100% !important;\n -ms-overflow-style: none; /* for Internet Explorer, Edge */\n scrollbar-width: none; /* for Firefox */\n overflow-y: auto; \n overflow-x: hidden; \n z-index: 1 !important; /* Higher value hide the more-info panel */\n /* For older Safari but not working with Firefox */\n /* display: grid !important; */ \n }\n #root.hidden {\n \tdisplay: none !important;\n }\n #root > :first-child::after {\n content: '';\n display: block;\n position: sticky;\n top: 0;\n left: -50px;\n margin: -70px 0 -36px -36px;\n overflow: visible;\n width: 200%;\n height: 100px;\n background: linear-gradient(0deg, ${g} 0%, ${E} 80%);\n z-index: 0;\n } \n #root::-webkit-scrollbar {\n display: none; /* for Chrome, Safari, and Opera */\n }\n #root > :first-child {\n position: sticky;\n top: 0;\n z-index: 1;\n background: none !important;\n overflow: visible;\n }\n #root.open-pop-up {\n will-change: transform, backdrop-filter;\n transform: translateY(-120%);\n }\n #root.open-pop-up > * {\n /* Block child items to overflow and if they do clip them */\n /*max-width: calc(100vw - 38px);*/\n max-width: 100% !important;\n /*overflow-x: clip;*/\n }\n #root.close-pop-up { \n transform: translateY(-20%);\n box-shadow: none;\n backdrop-filter: none !important;\n }\n @media only screen and (min-width: 600px) {\n #root {\n top: calc(120% + ${V} + var(--header-height));\n width: calc(${f}${"%"!==_[2]||v?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${_[1]/2}${_[2]});\n margin: 0 !important;\n }\n } \n @media only screen and (min-width: 870px) {\n #root {\n left: calc(50% - ${_[1]/2}${_[2]} + ${v?"0px":"var(--mdc-drawer-width) "+("%"===_[2]?"":"/ 2")});\n }\n } \n #root.editor {\n position: inherit !important;\n width: 100% !important;\n padding: 18px !important;\n backdrop-filter: none !important;\n }\n `,N=`\n ${M}\n\n ha-card {\n margin-top: 0 !important;\n }\n #header-container {\n display: inline-flex;\n ${m||b||u||y||O?"":"flex-direction: row-reverse;"}\n height: 50px;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n #header-container > div {\n display: ${m||b||u||y||O?"inline-flex":"none"};\n align-items: center;\n position: relative;\n padding-right: 6px;\n z-index: 1;\n flex-grow: 1;\n background-color: ${u?t.rgbColorOpacity:"var(--background-color,var(--secondary-background-color))"};\n transition: background 1s;\n border-radius: 25px;\n margin-right: 14px;\n backdrop-filter: blur(14px);\n -webkit-backdrop-filter: blur(14px);\n }\n #header-container h2 {\n display: inline-flex;\n margin: 0 18px 0 0;\n padding: 4px;\n z-index: 1;\n font-size: 18px;\n }\n #header-container p {\n display: inline-flex;\n font-size: 16px;\n min-width: fit-content ;\n }\n .power-button {\n cursor: pointer; \n flex-grow: inherit; \n width: 24px;\n height: 24px;\n border-radius: 12px;\n margin: 0 10px;\n background: none !important;\n justify-content: flex-end;\n background-color: var(--background-color,var(--secondary-background-color));\n }\n .close-pop-up {\n height: 50px;\n width: 50px;\n border: none;\n border-radius: 50%;\n z-index: 1;\n background: var(--background-color,var(--secondary-background-color));\n color: var(--primary-text-color);\n flex-shrink: 0;\n cursor: pointer;\n }\n `;t.popUpStyleAdded||((0,o.L2)(e,t,X,h,y,u,"","",C),t.popUpStyleAdded=!0),(0,o.L2)(e,t,N,h,y,u,w)})();const g=new Event("popUpInitialized");window.dispatchEvent(g),n&&t.popUp&&!t.editorModeAdded&&(t.popUp.classList.add("editor"),t.popUp.classList.remove("close-pop-up","open-pop-up"),t.editorModeAdded=!0)}else!n&&t.popUp&&t.editorModeAdded&&(t.popUp.classList.remove("editor"),t.editorModeAdded=!1)}),0),setTimeout((()=>{if(t.popUp&&Y&&w){null===localStorage.getItem("previousTriggerState_"+U)&&localStorage.setItem("previousTriggerState_"+U,""),null===localStorage.getItem("isManuallyClosed_"+U)&&localStorage.setItem("isManuallyClosed_"+U,"false"),null===localStorage.getItem("isTriggered_"+U)&&localStorage.setItem("isTriggered_"+U,"false");let n=localStorage.getItem("previousTriggerState_"+U),o="true"===localStorage.getItem("isManuallyClosed_"+U),a="true"===localStorage.getItem("isTriggered_"+U);e.states[Y].state!==W||null!==n||a||(r(0,U),a=!0,localStorage.setItem("isTriggered_"+U,a)),e.states[Y].state!==n&&(o=!1,localStorage.setItem("previousTriggerState_"+U,e.states[Y].state),localStorage.setItem("isManuallyClosed_"+U,o)),e.states[Y].state!==W||o?e.states[Y].state!==W&&F&&t.popUp.classList.contains("open-pop-up")&&a&&!o&&(history.replaceState(null,null,location.href.split("#")[0]),i(window,"location-changed",!0),S=U+!1,a=!1,o=!0,localStorage.setItem("isManuallyClosed_"+U,o),localStorage.setItem("isTriggered_"+U,a)):(r(0,U),a=!0,localStorage.setItem("isTriggered_"+U,a))}}),0)}const b=Object.getPrototypeOf(customElements.get("ha-panel-lovelace")),f=b.prototype.html,_=b.prototype.css;let v;!function(){if(!window.eventAdded){const t=new Event("urlChanged");function e(){let e=0;window.dispatchEvent(t);const n=setInterval((()=>{e<10?(window.dispatchEvent(t),e++):clearInterval(n)}),1e3)}window.popUpInitialized=!1,["location-changed","connection-status"].forEach((t=>{window.addEventListener(t,e)}),{passive:!0});const n=()=>{window.dispatchEvent(t),window.addEventListener("popstate",e,{passive:!0})};window.addEventListener("popUpInitialized",n,{passive:!0}),window.eventAdded=!0}}();class y extends HTMLElement{set hass(e){var i;switch(this._hass=e,v=n(),this.editor=v,async function(e){if(!window.resourcesChecked){window.resourcesChecked=!0;let n=t;const o=localStorage.getItem("version");customElements.get("bubble-pop-up"),o!==n&&(localStorage.setItem("version",n),location.reload());let i=(await e.callWS({type:"lovelace/resources"})).find((t=>t.url.includes("bubble-pop-up.js")));i&&await e.callWS({type:"lovelace/resources/delete",resource_id:i.id})}}(e),(i=this).content||(i.attachShadow({mode:"open"}),i.shadowRoot.innerHTML='\n \n
\n
\n
\n ',i.card=i.shadowRoot.querySelector("ha-card"),i.content=i.shadowRoot.querySelector("div")),this.config.card_type){case"pop-up":m(this);break;case"horizontal-buttons-stack":!function(t){const e=t._hass;let i,{customStyles:s,entityId:l,icon:c,name:d,widthDesktop:p,widthDesktopDivided:h,isSidebarHidden:u,state:m,stateChanged:b,stateOn:f,riseAnimation:_,marginCenter:v,popUpOpen:y,rgbaColor:w,rgbColor:x,bgOpacity:k,shadowOpacity:C,bgBlur:$,iconColorOpacity:S,iconColor:E,iconFilter:O,iconStyles:L,haStyle:A,themeBgColor:I,color:T}=g(t,t.config,e);if(setInterval((()=>{i=n(),i&&!t.editorModeAdded?(t.buttonsContainer.classList.add("editor"),t.card.classList.add("editor"),t.editorModeAdded=!0):!i&&t.editorModeAdded&&(t.buttonsContainer.classList.remove("editor"),t.card.classList.remove("editor"),t.editorModeAdded=!1)}),100),!t.buttonsAdded){const e=document.createElement("div");e.classList.add("horizontal-buttons-stack-container"),t.content.appendChild(e),t.buttonsContainer=e}const V=(t,n,i)=>{if(e.states[n].attributes.rgb_color){const i=e.states[n].attributes.rgb_color,a=(0,o.wW)(i)?"rgba(255,220,200, 0.5)":`rgba(${i}, 0.5)`;t.style.backgroundColor=a,t.style.border="1px solid rgba(0,0,0,0)"}else e.states[n].attributes.rgb_color||"on"!=e.states[n].state?(t.style.backgroundColor="rgba(0,0,0,0)",t.style.border="1px solid var(--primary-text-color)"):(t.style.backgroundColor="rgba(255,255,255,0.5)",t.style.border="1px solid rgba(0,0,0,0)")};let D=[],M=1;for(;t.config[M+"_link"];){const e=M+"_",n=t.config[e+"name"]||"",o=t.config[e+"pir_sensor"];c=t.config[e+"icon"]||"";const i=t.config[e+"link"],a=t.config[e+"entity"];D.push({button:n,pirSensor:o,icon:c,link:i,lightEntity:a}),M++}if(t.config.auto_order&&D.sort(((t,n)=>t.pirSensor&&n.pirSensor?"on"===e.states[t.pirSensor].state&&"on"===e.states[n.pirSensor].state?e.states[t.pirSensor].last_updated{const o=((e,n,o)=>{const i=document.createElement("button");return i.setAttribute("class",`button ${n.substring(1)}`),i.innerHTML=`\n ${""!==o?``:""}\n ${""!==e?`

${e}

`:""}\n `,i.hasListener||(i.addEventListener("click",(t=>{y=location.hash+!0,localStorage.getItem("isManuallyClosed_"+n),y!==n+!0?(r(0,n),y=n+!0):(history.replaceState(null,null,location.href.split("#")[0]),y=n+!1),t.stopPropagation(),a("light")}),{passive:!0}),window.addEventListener("urlChanged",(function(){t.config.highlightCurrentview&&(location.pathname===n||location.hash===n?i.classList.add("highlight"):i.classList.remove("highlight"))}),{passive:!0}),i.hasListener=!0),i})(n.button,n.link,n.icon);e[n.link]=o,t.buttonsContainer.appendChild(o)})),t.buttonsAdded=!0,t.buttons=e}let z=0;!function(t){if(t.buttonsUpdated)return;let e=[];for(let n of D)t.buttons[n.link]&&(e.push(localStorage.getItem(`buttonWidth-${n.link}`)),e.push(localStorage.getItem(`buttonContent-${n.link}`)));Promise.all(e).then((e=>{let n=0;for(let o of D){let a=t.buttons[o.link];if(a){let r=e[n],s=e[n+1];n+=2,r&&"0"!==r&&s===a.innerHTML&&!i||(r=a.offsetWidth,localStorage.setItem(`buttonWidth-${o.link}`,r),localStorage.setItem(`buttonContent-${o.link}`,a.innerHTML),t.previousConfig=t.config),a.style.transform=`translateX(${z}px)`,z+=parseInt(r)+12}o.lightEntity&&V(a,o.lightEntity,o.link)}t.buttonsAdded=!0}))}(t);const B=`\n ha-card {\n border-radius: 0;\n }\n .horizontal-buttons-stack {\n width: 100%;\n margin-top: 0 !important;\n background: none !important;\n position: fixed;\n height: 51px;\n bottom: 16px;\n left: ${v};\n z-index: 1 !important; /* Higher value hide the more-info panel */\n }\n @keyframes from-bottom {\n 0% {transform: translateY(200px);}\n 20% {transform: translateY(200px);}\n 46% {transform: translateY(-8px);}\n 56% {transform: translateY(1px);}\n 62% {transform: translateY(-2px);}\n 70% {transform: translateY(0);}\n 100% {transform: translateY(0);}\n }\n .horizontal-buttons-stack-container {\n width: max-content;\n position: relative;\n height: 51px;\n }\n .button {\n display: inline-flex;\n position: absolute;\n box-sizing: border-box !important;\n border: 1px solid var(--primary-text-color);\n align-items: center;\n height: 50px;\n line-height: 16px;\n white-space: nowrap;\n width: auto;\n border-radius: 25px;\n z-index: 1;\n padding: 0 16px;\n background: none;\n transition: background-color 1s, border 1s, transform 1s;\n color: var(--primary-text-color);\n }\n .highlight {\n animation: pulse 1.4s infinite alternate;\n }\n @keyframes pulse {\n 0% {\n filter: brightness(0.7);\n }\n 100% {\n filter: brightness(1.3);\n }\n }\n .icon {\n height: 24px;\n }\n .card-content {\n width: calc(100% + 18px);\n box-sizing: border-box !important;\n margin: 0 -36px !important;\n padding: 0 36px !important;\n overflow: scroll !important;\n -ms-overflow-style: none;\n scrollbar-width: none;\n -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 1) calc(0% + 28px), rgba(0, 0, 0, 1) calc(100% - 28px), transparent 100%);\n /* mask-image: linear-gradient(90deg, transparent 2%, rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 1) 96%, transparent 100%); */\n /* -webkit-mask-image: linear-gradient(90deg, transparent 2%, rgba(0, 0, 0, 1) 6%, rgba(0, 0, 0, 1) 96%, transparent 100%); */\n }\n .horizontal-buttons-stack::before {\n content: '';\n position: absolute;\n top: -32px;\n left: -100%;\n display: block;\n background: linear-gradient(0deg, var(--background-color, var(--primary-background-color)) 50%, rgba(79, 69, 87, 0));\n width: 200%;\n height: 100px;\n }\n .card-content::-webkit-scrollbar {\n display: none;\n }\n @media only screen and (min-width: 600px) {\n .card-content {\n position: fixed;\n width: ${p} !important;\n left: calc(50% - ${h[1]/2}${h[2]});\n margin-left: -13px !important;\n padding: 0 26px !important;\n }\n }\n @media only screen and (min-width: 870px) {\n .card-content {\n position: fixed;\n width: calc(${p}${"%"!==h[2]||u?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${h[1]/2}${h[2]} + ${!0===u?"0px":"var(--mdc-drawer-width) "+("%"===h[2]?"":"/ 2")});\n margin-left: -13px !important;\n padding: 0 26px !important;\n }\n }\n .horizontal-buttons-stack.editor {\n position: relative;\n bottom: 0;\n left: 0;\n overflow: hidden;\n }\n .horizontal-buttons-stack.editor::before {\n top: -32px;\n left: -100%;\n background: none;\n width: 100%;\n height: 0;\n }\n .horizontal-buttons-stack-container.editor > .button {\n transition: background-color 0s, border 0s, transform 0s;\n }\n .horizontal-buttons-stack-container.editor {\n margin-left: 1px;\n }\n .horizontal-buttons-stack.editor > .card-content {\n position: relative;\n width: calc(100% + 26px) !important;\n left: -26px;\n margin: 0 !important;\n padding: 0;\n }\n `;!window.hasAnimated&&_&&(t.content.style.animation="from-bottom 1.3s forwards",window.hasAnimated=!0,setTimeout((()=>{t.content.style.animation="none"}),1500)),(0,o.L2)(e,t,B,s)}(this);break;case"button":!function(t){const e=t._hass,n=t.editor;let{customStyles:i,entityId:r,icon:l,name:d,widthDesktop:p,widthDesktopDivided:h,isSidebarHidden:u,state:m,stateChanged:b,stateOn:f,formatedState:_,riseAnimation:v,marginCenter:y,popUpOpen:w,rgbaColor:x,rgbColor:k,bgOpacity:C,shadowOpacity:$,bgBlur:S,iconColorOpacity:E,iconColor:O,iconFilter:L,iconStyles:A,haStyle:I,themeBgColor:T,color:V}=g(t,t.config,e);_=r&&(b||n)?e.formatEntityState(e.states[r]):"";const D=t.config.button_type||"switch",M=!!t.config.show_state&&t.config.show_state;let z=r?e.states[r].attributes.brightness||0:"",B=r?e.states[r].attributes.volume_level||0:"",q=!1,H=z,U=B,Y=0,W=0,F=0,P=!1,R=null;if(!t.buttonAdded){const e=document.createElement("div");e.setAttribute("class","button-container"),t.content.appendChild(e)}const j=document.createElement("div");j.setAttribute("class","icon-container"),t.iconContainer=j;const X=document.createElement("div");X.setAttribute("class","name-container");const N=document.createElement("div");N.setAttribute("class","switch-button");const G=document.createElement("div");G.setAttribute("class","range-slider");const K=document.createElement("div");if(K.setAttribute("class","range-fill"),!t.buttonContainer||n){if(n&&t.buttonContainer){for(;t.buttonContainer.firstChild;)t.buttonContainer.removeChild(t.buttonContainer.firstChild);t.eventAdded=!1,t.wasEditing=!0}t.buttonContainer=t.content.querySelector(".button-container"),"slider"!==D||t.buttonAdded&&!n?("switch"===D||"custom"===D||n)&&(t.buttonContainer.appendChild(N),N.appendChild(j),N.appendChild(X),t.switchButton=t.content.querySelector(".switch-button")):(t.buttonContainer.appendChild(G),G.appendChild(j),G.appendChild(X),G.appendChild(K),t.rangeFill=t.content.querySelector(".range-fill")),(0,o.IU)(t,r,l,j,n),X.innerHTML=`\n

${d}

\n ${M?`

${_}

`:""}\n `,t.buttonAdded=!0}function Z(t){a("success");let e=t.querySelector(".feedback-element");e||(e=document.createElement("div"),e.setAttribute("class","feedback-element"),t.appendChild(e)),e.style.animation="tap-feedback .5s",setTimeout((()=>{e.style.animation="none",t.removeChild(e)}),500)}function J(t){Y=t.pageX||(t.touches?t.touches[0].pageX:0),W=t.pageY||(t.touches?t.touches[0].pageY:0),F=G.value,t.target!==j&&t.target!==j.querySelector("ha-icon")&&(q=!0,document.addEventListener("mouseup",tt,{passive:!0}),document.addEventListener("touchend",tt,{passive:!0}),document.addEventListener("mousemove",Q,{passive:!0}),document.addEventListener("touchmove",Q,{passive:!0}),R=setTimeout((()=>{ot(t.pageX||t.touches[0].pageX),et(),R=null}),200))}function Q(t){const e=t.pageX||(t.touches?t.touches[0].pageX:0),n=t.pageY||(t.touches?t.touches[0].pageY:0);Math.abs(n-W)>Math.abs(e-Y)?(clearTimeout(R),tt()):(document.removeEventListener("mousemove",Q),document.removeEventListener("touchmove",Q),document.addEventListener("mousemove",nt,{passive:!0}),document.addEventListener("touchmove",nt,{passive:!0}))}function tt(){q=!1,P=!1,et(),document.removeEventListener("mouseup",tt),document.removeEventListener("touchend",tt),document.removeEventListener("mousemove",nt),document.removeEventListener("touchmove",nt)}function et(){r.startsWith("light.")?(z=H,e.callService("light","turn_on",{entity_id:r,brightness:z})):r.startsWith("media_player.")&&(B=U,e.callService("media_player","volume_set",{entity_id:r,volume_level:B}))}function nt(t){const e=t.pageX||(t.touches?t.touches[0].pageX:0),n=t.pageY||(t.touches?t.touches[0].pageY:0);q&&Math.abs(e-Y)>10?(a("light"),ot(e)):q&&Math.abs(n-W)>10&&(q=!1,G.value=F)}function ot(t){const e=G.getBoundingClientRect(),n=Math.min(Math.max(t-e.left,0),e.width)/e.width;r.startsWith("light.")?H=Math.round(255*n):r.startsWith("media_player.")&&(U=n),K.style.transition="none",K.style.transform=`translateX(${100*n}%)`}M&&_&&(t.content.querySelector(".state").textContent=_),t.eventAdded||"switch"!==D?t.eventAdded||"slider"!==D?t.eventAdded||"custom"!==D||(N.addEventListener("click",(()=>Z(t.switchButton)),{passive:!0}),c(j,t.config,0,a),t.eventAdded=!0):(G.addEventListener("mousedown",J,{passive:!0}),G.addEventListener("touchstart",J,{passive:!0}),c(j,t.config,0,a),t.eventAdded=!0):(N.addEventListener("click",(()=>Z(t.switchButton)),{passive:!0}),N.addEventListener("click",(function(t){t.target!==j&&t.target!==j.querySelector("ha-icon")&&s(e,r)}),{passive:!0}),c(j,t.config,0,a),t.eventAdded=!0),t.isDragging||"slider"!==D||(t.rangeFill.style.transition="all .3s",r.startsWith("light.")?t.rangeFill.style.transform=`translateX(${z/255*100}%)`:r.startsWith("media_player.")&&(t.rangeFill.style.transform=`translateX(${100*B}%)`));const it=`\n ha-card {\n margin-top: 0 !important;\n background: none !important;\n opacity: ${"unavailable"!==m?"1":"0.5"};\n }\n \n .button-container {\n position: relative;\n width: 100%;\n height: 50px;\n z-index: 0;\n background-color: var(--background-color-2,var(--secondary-background-color));\n border-radius: 25px;\n mask-image: radial-gradient(white, black);\n -webkit-mask-image: radial-gradient(white, black);\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n -webkit-transform: translateZ(0);\n overflow: hidden;\n }\n \n .switch-button,\n .range-slider {\n display: inline-flex;\n position: absolute;\n height: 100%;\n width: 100%;\n transition: background-color 1.5s;\n background-color: ${f&&["switch","custom"].includes(D)?"var(--accent-color)":"rgba(0,0,0,0)"};\n }\n\n .range-fill {\n z-index: -1;\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n background-color: ${E};\n width: 100%;\n left: -100%;\n }\n \n .switch-button {\n cursor: pointer !important;\n }\n \n .range-slider {\n cursor: ew-resize;\n }\n \n .name-container {\n position: relative;\n display: ${M?"block":"inline-flex"};\n margin-left: 4px;\n z-index: 1;\n font-weight: 600;\n align-items: center;\n line-height: ${M?"4px":"16px"};\n padding-right: 16px;\n }\n \n .state {\n font-size: 12px;\n opacity: 0.7;\n }\n \n .feedback-element {\n position: absolute;\n top: 0;\n left: 0;\n opacity: 0;\n width: 100%;\n height: 100%;\n background-color: rgb(0,0,0);\n }\n \n @keyframes tap-feedback {\n 0% {transform: translateX(-100%); opacity: 0;}\n 64% {transform: translateX(0); opacity: 0.1;}\n 100% {transform: translateX(100%); opacity: 0;}\n }\n\n ${A}\n `;(0,o.L2)(e,t,it,i,m,r,b)}(this);break;case"separator":!function(t){const e=t._hass,n=t.editor,i=t.config;let{customStyles:a,entityId:r,icon:s,name:l,widthDesktop:c,widthDesktopDivided:d,isSidebarHidden:p,state:h,stateChanged:u,stateOn:m,formatedState:b,riseAnimation:f,marginCenter:_,popUpOpen:v,rgbaColor:y,rgbColor:w,bgOpacity:x,shadowOpacity:k,bgBlur:C,iconColorOpacity:$,iconColor:S,iconFilter:E,iconStyles:O,haStyle:L,themeBgColor:A,color:I}=g(t,i,e);if(!t.separatorAdded||n){if(n&&t.separatorContainer)for(;t.separatorContainer.firstChild;)t.separatorContainer.removeChild(t.separatorContainer.firstChild);t.separatorAdded||(t.separatorContainer=document.createElement("div"),t.separatorContainer.setAttribute("class","separator-container")),t.separatorContainer.innerHTML=`\n
\n \n

${l}

\n
\n
\n `,t.content.appendChild(t.separatorContainer),t.separatorAdded=!0}(0,o.L2)(e,t,"\n .separator-container {\n display: inline-flex;\n width: 100%;\n margin-top: 12px;\n }\n .separator-container div:first-child {\n display: inline-flex;\n max-width: calc(100% - 38px);\n }\n .separator-container div ha-icon {\n display: inline-flex;\n height: 24px;\n width: 24px;\n margin: 0 22px 0 8px;\n transform: translateY(-2px);\n }\n .separator-container div h4 {\n display: inline-flex;\n margin: 0 20px 0 0;\n font-size: 16px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .separator-container div:last-child {\n display: inline-flex; \n border-radius: 6px; \n opacity: 0.5; \n margin-left: 10px; \n flex-grow: 1; \n height: 6px; \n align-self: center; \n background-color: var(--background-color,var(--secondary-background-color));\n }\n ",a)}(this);break;case"cover":!function(t){const e=t._hass,n=t.editor,i=t.config;let{customStyles:r,entityId:s,icon:l,name:d,widthDesktop:p,widthDesktopDivided:h,isSidebarHidden:u,state:m,stateChanged:b,stateOn:f,formatedState:_,riseAnimation:v,marginCenter:y,popUpOpen:w,rgbaColor:x,rgbColor:k,bgOpacity:C,shadowOpacity:$,bgBlur:S,iconColorOpacity:E,iconColor:O,iconFilter:L,iconStyles:A,haStyle:I,themeBgColor:T,color:V}=g(t,i,e);const D=i.icon_open?i.icon_open:"mdi:window-shutter-open",M=i.icon_close?i.icon_close:"mdi:window-shutter",z=i.open_service?i.open_service:"cover.open_cover",B=i.close_service?i.close_service:"cover.close_cover",q=i.stop_service?i.stop_service:"cover.stop_cover",H=i.icon_up?i.icon_up:"mdi:arrow-up",U=i.icon_down?i.icon_down:"mdi:arrow-down",Y=!!t.config.show_state&&t.config.show_state;if(l="open"===e.states[i.entity].state?D:M,_=b?e.formatEntityState(e.states[s]):_||"",!t.coverAdded||n){if(n&&t.coverContainer)for(;t.coverContainer.firstChild;)t.coverContainer.removeChild(t.coverContainer.firstChild);t.coverContainer=document.createElement("div"),t.coverContainer.setAttribute("class","cover-container"),t.coverContainer.innerHTML=`\n
\n
\n
\n
\n

${d}

\n

\n
\n
\n
\n \n \n \n
\n `,t.content.appendChild(t.coverContainer);const o=t.coverContainer.querySelector(".open"),r=t.coverContainer.querySelector(".stop"),l=t.coverContainer.querySelector(".close");o.addEventListener("click",(()=>{e.callService(z.split(".")[0],z.split(".")[1],{entity_id:s})}),{passive:!0}),r.addEventListener("click",(()=>{e.callService(q.split(".")[0],q.split(".")[1],{entity_id:s})}),{passive:!0}),l.addEventListener("click",(()=>{e.callService(B.split(".")[0],B.split(".")[1],{entity_id:s})}),{passive:!0}),t.iconContainer=t.content.querySelector(".icon-container"),c(t.iconContainer,i,0,a),t.coverAdded=!0}t.iconContainer&&(b||n)&&(t.iconContainer.innerHTML=``,t.content.querySelector(".state").textContent=Y?_:""),(0,o.L2)(e,t,"\n ha-card {\n margin-top: 0 !important;\n background: none !important;\n }\n \n .header-container {\n display: flex;\n align-items: center;\n margin-bottom: 10px;\n }\n \n .cover-container {\n display: grid;\n }\n \n .icon-container {\n display: flex;\n margin: 0 !important;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n /*z-index: 1;*/\n width: 48px;\n height: 48px;\n margin: 6px;\n border-radius: 50%;\n background-color: var(--card-background-color,var(--ha-card-background));\n border: 6px solid var(--background-color-2,var(--secondary-background-color));\n box-sizing: border-box;\n }\n \n .name-container {\n font-weight: 600;\n margin-left: 10px;\n line-height: 4px;\n }\n \n .buttons-container {\n display: grid;\n align-self: center;\n grid-auto-flow: column;\n grid-gap: 18px; \n }\n \n .state {\n font-size: 12px;\n opacity: 0.7;\n }\n \n ha-icon {\n display: flex; \n height: 24px; \n width: 24px; \n color: var(--primary-text-color);\n }\n \n .button {\n display: flex;\n background: var(--background-color-2,var(--secondary-background-color));\n height: 42px;\n border-radius: 32px;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n }\n ",r,m,s)}(this);break;case"empty-column":!function(t){if(!t.emptyCollumnAdded){const e=document.createElement("div");e.setAttribute("class","empty-column"),e.innerHTML='\n
\n ',t.content.appendChild(e),t.emptyColumnAdded=!0}}(this)}}setConfig(t){if("pop-up"===t.card_type){if(!t.hash)throw new Error("You need to define an hash. Please note that this card must be placed inside a vertical_stack to work as a pop-up.")}else if("horizontal-buttons-stack"===t.card_type){var e={};for(var n in t)if(n.match(/^\d+_icon$/)){var o=n.replace("_icon","_link");if(void 0===t[o])throw new Error("You need to define "+o);if(e[t[o]])throw new Error("You can't use "+t[o]+" twice");e[t[o]]=!0}}else if(("button"===t.card_type||"cover"===t.card_type)&&!t.entity)throw new Error("You need to define an entity");if(window.entityError)throw new Error("You need to define a valid entity");this.config=t}getCardSize(){return-1e4}static getConfigElement(){return document.createElement("bubble-card-editor")}}customElements.define("bubble-card",y),customElements.define("bubble-card-editor",class extends b{setConfig(t){this._config={...t}}static get properties(){return{hass:{},_config:{}}}get _card_type(){return this._config.card_type||""}get _button_type(){return this._config.button_type||"switch"}get _entity(){return this._config.entity||""}get _name(){return this._config.name||""}get _icon(){return this._config.icon||""}get _state(){return this._config.state||""}get _text(){return this._config.text||""}get _hash(){return this._config.hash||"#pop-up-name"}get _trigger_entity(){return this._config.trigger_entity||""}get _trigger_state(){return this._config.trigger_state||""}get _trigger_close(){return this._config.trigger_close||!1}get _margin(){return this._config.margin||"7px"}get _margin_top_mobile(){return this._config.margin_top_mobile||"0px"}get _margin_top_desktop(){return this._config.margin_top_desktop||"0px"}get _width_desktop(){return this._config.width_desktop||"540px"}get _bg_color(){return this._config.bg_color||window.color}get _bg_opacity(){return void 0!==this._config.bg_opacity?this._config.bg_opacity:"88"}get _bg_blur(){return void 0!==this._config.bg_blur?this._config.bg_blur:"14"}get _shadow_opacity(){return void 0!==this._config.shadow_opacity?this._config.shadow_opacity:"0"}get _is_sidebar_hidden(){return this._config.is_sidebar_hidden||!1}get _rise_animation(){return void 0===this._config.rise_animation||this._config.rise_animation}get _auto_close(){return this._config.auto_close||""}get _back_open(){return this._config.back_open||!1}get _icon_open(){return this._config.icon_open||""}get _icon_close(){return this._config.icon_close||""}get _open_service(){return this._config.open_service||"cover.open_cover"}get _close_service(){return this._config.open_service||"cover.close_cover"}get _stop_service(){return this._config.open_service||"cover.stop_cover"}get _auto_order(){return this._config.auto_order||!1}get _highlightCurrentview(){return this._config.highlightCurrentview||!1}get _show_state(){return this._config.show_state||!1}render(){if(!this.hass)return f``;if(!this.listsUpdated){const t=t=>({label:t,value:t});this.allEntitiesList=Object.keys(this.hass.states).map(t),this.lightList=Object.keys(this.hass.states).filter((t=>"light"===t.substr(0,t.indexOf(".")))).map(t),this.sensorList=Object.keys(this.hass.states).filter((t=>"sensor"===t.substr(0,t.indexOf(".")))).map(t),this.binarySensorList=Object.keys(this.hass.states).filter((t=>"binary_sensor"===t.substr(0,t.indexOf(".")))).map(t),this.coverList=Object.keys(this.hass.states).filter((t=>"cover"===t.substr(0,t.indexOf(".")))).map(t),this.cardTypeList=[{label:"Button",value:"button"},{label:"Cover",value:"cover"},{label:"Empty column",value:"empty-column"},{label:"Horizontal buttons stack",value:"horizontal-buttons-stack"},{label:"Pop-up",value:"pop-up"},{label:"Separator",value:"separator"}],this.buttonTypeList=[{label:"Switch",value:"switch"},{label:"Slider",value:"slider"}],this.listsUpdated=!0}const e=this.allEntitiesList,n=(this.lightList,this.sensorList,this.coverList),o=this.cardTypeList,i=this.buttonTypeList;if("pop-up"===this._config.card_type)return f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Pop-up This card allows you to convert any vertical stack into a pop-up. Each pop-up can be opened by targeting its link (e.g. '#pop-up-name'), with navigation_path or with the horizontal buttons stack that is included.
It must be placed within a vertical-stack card at the top most position to function properly. The pop-up will be hidden by default until you open it.

How to get the optimized mode? + This card allows you to convert any vertical stack into a pop-up. Each pop-up can be opened by targeting its link (e.g. '#pop-up-name'), with navigation_path or with the horizontal buttons stack that is included.
It must be placed within a vertical-stack card at the top most position to function properly. The pop-up will be hidden by default until you open it.

How to get the optimized mode?
${this.makeDropdown("Optional - Icon","icon")} - ${this.makeDropdown("Optional - Entity to toggle (e.g. room light group)","entity",t)} - ${this.makeDropdown("Optional - Entity state to display (e.g. room temperature)","state",t)} + ${this.makeDropdown("Optional - Entity to toggle (e.g. room light group)","entity",e)} + ${this.makeDropdown("Optional - Entity state to display (e.g. room temperature)","state",e)}

Pop-up trigger

This allows you to open this pop-up based on the state of any entity, for example you can open a "Security" pop-up with a camera when a person is in front of your house. You can also create a toggle helper (input_boolean) and trigger its opening/closing in an automation. - ${this.makeDropdown("Optional - Entity to open the pop-up based on its state","trigger_entity",t)} + ${this.makeDropdown("Optional - Entity to open the pop-up based on its state","trigger_entity",e)}

+ Set ‘Background blur’ to 0 if your pop-up animations are rendering at low FPS. You can't set a value to 0 with the sliders for now, just change it to 0 in the text field if you need to. -

Advanced settings

- - -
- -
-
- Back button/event support : This allow you to navigate through your pop-ups history when you press the back button of your browser. This setting can be applied only once, you don't need to change it in all pop-ups. If it's not working just turn it on for each pop-ups. ${this.makeVersion()} - `;if("button"===this._config.card_type)return b` + `;if("button"===this._config.card_type)return f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Button

This card can be a slider or a button, allowing you to toggle your entities, control the brightness of your lights and the volume of your media players. To access color / control of an entity, simply tap on the icon. - ${this.makeDropdown("slider"!==this._button_type?"Entity (toggle)":"Entity (light or media_player)","entity",t)} + ${this.makeDropdown("slider"!==this._button_type?"Entity (toggle)":"Entity (light or media_player)","entity",e)} Optional - Show entity state
- ${this.makeDropdown("Button type","button_type",o)} + ${this.makeDropdown("Button type","button_type",i)} - `;if("separator"===this._config.card_type)return b` + `;if("separator"===this._config.card_type)return f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Separator

This card is a simple separator for dividing your pop-up into categories / sections. e.g. Lights, Devices, Covers, Settings, Automations... - `;if("horizontal-buttons-stack"===this._config.card_type){if(!this.buttonAdded&&this.shadowRoot.querySelector("#add-button")){const t=this.shadowRoot.querySelector("#add-button");for(this.buttonIndex=0;this._config[this.buttonIndex+1+"_link"];)this.buttonIndex++;t.addEventListener("click",(()=>{this.buttonIndex++;const e=t.style.opacity,n=t.innerText;t.style.opacity="0.6",t.style.transition="opacity 1s",t.innerText="Loading...",setTimeout((()=>{t.style.opacity=e,t.innerText=n}),5e3)}),{passive:!0}),this.buttonAdded=!0}return b` + `;if("horizontal-buttons-stack"===this._config.card_type){if(!this.buttonAdded&&this.shadowRoot.querySelector("#add-button")){this.buttonAdded=!0;const t=this.shadowRoot.querySelector("#add-button");for(this.buttonIndex=0;this._config[this.buttonIndex+1+"_link"];)this.buttonIndex++;t.addEventListener("click",(()=>{this.buttonIndex++;const e=t.style.opacity,n=t.innerText;t.style.opacity="0.6",t.style.transition="opacity 1s",t.innerText="Loading...",setTimeout((()=>{t.style.opacity=e,t.innerText=n}),5e3)}),{passive:!0})}return f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Horizontal buttons stack

This card is the companion to the pop-up card, allowing you to open the corresponding pop-ups. It also allows you to open any page of your dashboard. In addition, you can add your motion sensors so that the order of the buttons adapts according to the room you just entered. This card is scrollable, remains visible and acts as a footer.

Please note that this card may take some time to load in edit mode.
@@ -292,12 +280,12 @@ ${this.makeVersion()}
- `}return"cover"===this._config.card_type?b` + `}return"cover"===this._config.card_type?f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Cover

This card allows you to control your covers. - ${this.makeDropdown("Entity","entity",e)} + ${this.makeDropdown("Entity","entity",n)} - `:"empty-column"===this._config.card_type?b` + `:"empty-column"===this._config.card_type?f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)}

Empty column

Just an empty card to fill any empty column. ${this.makeVersion()}
- `:this._config.card_type?void 0:b` + `:this._config.card_type?void 0:f`
- ${this.makeDropdown("Card type","card_type",n)} + ${this.makeDropdown("Card type","card_type",o)} You need to add a card type first. +

The Bubble Card ${t} changelog is available here. +


Almost everything is available in the GUI editor, but in the YAML editor you can add your own custom styles, create custom buttons or modify the tap actions of all cards. You can find more details on my GitHub page.

+

And if you like my project and want to support me, please consider making a donation. Any amount is welcome and very much appreciated! 🍻

@@ -365,7 +356,7 @@
${this.makeVersion()}
- `}makeDropdown(t,e,n){return this.hass,t.includes("icon")||t.includes("Icon")?b` + `}makeDropdown(t,e,n){return this.hass,t.includes("icon")||t.includes("Icon")?f`
- `:b` + `:f`
- `}makeButton(){let t=[];for(let e=1;e<=this.buttonIndex;e++)t.push(b` + `}makeButton(){let t=[];for(let e=1;e<=this.buttonIndex;e++)t.push(f`
this.removeButton(e)}> @@ -430,7 +421,7 @@ @value-changed="${this._valueChanged}" >
- `);return t}makeVersion(){return b` + `);return t}makeVersion(){return f`

{"use strict";var __webpack_modules__={946:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{G:()=>getIconStyles,IU:()=>createIcon,L2:()=>addStyles,_k:()=>convertToRGBA,mk:()=>getIconColor,wW:()=>isColorCloseToWhite});const addStyles=function(hass,context,styles,customStyles,state,entityId,stateChanged,path="",element=context.content){const customStylesEval=customStyles?eval("`"+customStyles+"`"):"";let styleAddedKey=styles+"Added";if(!context[styleAddedKey]||context.previousStyle!==customStylesEval||stateChanged||context.previousConfig!==context.config){if(!context[styleAddedKey]){if(context.styleElement=element.querySelector("style"),!context.styleElement){context.styleElement=document.createElement("style");const e=path?element.querySelector(path):element;e?.appendChild(context.styleElement)}context[styleAddedKey]=!0}context.styleElement.innerHTML!==customStylesEval+styles&&(context.styleElement.innerHTML=customStylesEval+styles),context.previousStyle=customStylesEval,context.previousConfig=context.config}};function createIcon(e,t,n,o,i){let a=e._hass,r=!(!t||!a.states[t].attributes)&&a.states[t].attributes;e.imageUrl=!!r.entity_picture&&r.entity_picture,updateIcon(e,a,t,n,o),i||setInterval((()=>{a=e._hass,t&&a.states[t]&&(e.currentEntityPicture=a.states[t].attributes.entity_picture,e.currentEntityPicture!==e.previousEntityPicture&&(e.imageUrl=e.currentEntityPicture,updateIcon(e,a,t,n,o),e.previousEntityPicture=e.currentEntityPicture))}),1e3)}function updateIcon(e,t,n,o,i){for(;i.firstChild;)i.removeChild(i.firstChild);let a=e.config.icon&&e.config.icon.includes("/")?e.config.icon:e.imageUrl?e.imageUrl:"";if(a&&(r=t.states[n].state,n.startsWith("media_player.")&&!["off","unknown","idle",void 0].includes(r)||!n.startsWith("media_player."))){const e=document.createElement("div");e.setAttribute("class","entity-picture"),e.setAttribute("alt","Icon"),i&&(i.appendChild(e),i.style.background="center / cover no-repeat url("+a+"), var(--card-background-color,var(--ha-card-background))")}else{const e=document.createElement("ha-icon");e.setAttribute("icon",o),e.setAttribute("class","icon"),i&&i.appendChild(e)}var r}function isColorCloseToWhite(e){let t=[220,220,190];for(let n=0;n<3;n++)if(e[n]{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{var e="v1.6.0-beta.2",t=__webpack_require__(946);const n=(e,t,n,o)=>{o=o||{},n=null==n?{}:n;const i=new Event(t,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return i.detail=n,e.dispatchEvent(i),i},o=e=>{n(window,"haptic",e)},i=(e,t,o=!1)=>{o?history.replaceState(null,"",t):history.pushState(null,"",t),n(window,"location-changed",{replace:o})};function a(e,t,n){const o={entity:t.entity,tap_action:{action:"more-info"},double_tap_action:{action:"toggle"},hold_action:{action:"toggle"}},i=new Event("hass-action",{bubbles:!0,composed:!0});i.detail={config:o,action:n},e.dispatchEvent(i)}let r,s,l,c,d;function p(e,n,o,i){let a=n.styles?n.styles:"",d=n.entity&&o.states[n.entity]?n.entity:"",p=!n.icon&&n.entity?o.states[d].attributes.icon||o.states[d].attributes.entity_picture||"":n.icon||"",h=n.name?n.name:n.entity?o.states[d].attributes.friendly_name:"",u=n.width_desktop||"540px",g=u?u.match(/(\d+)(\D+)/):"",b=n.is_sidebar_hidden||!1,_=d?o.states[d].state:"";!function(e,t,n){e.hasState=t.states[n],e.hasState&&(e.newState=[e.hasState.state,e.hasState.attributes.rgb_color],e.oldState&&e.newState[0]===e.oldState[0]&&e.newState[1]===e.oldState[1]?e.stateChanged=!1:(e.oldState=e.newState,e.stateChanged=!0),e.stateChanged)}(e,o,d);let m=e.stateChanged,f=["on","open","cleaning","true","home","playing"].includes(_)||0!==Number(_)&&!isNaN(Number(_)),y=void 0===n.rise_animation||n.rise_animation,v=n.margin?"0"!==n.margin?n.margin:"0px":"7px",w=void 0!==n.bg_opacity?n.bg_opacity:"88",x=void 0!==n.shadow_opacity?n.shadow_opacity:"0",k=void 0!==n.bg_blur?n.bg_blur:"10",{iconColorOpacity:$,iconColor:S,iconFilter:C}=(0,t.mk)(o,d,f,t.wW),E=(0,t.G)(d,f,S,C),O=getComputedStyle(document.body),I=O.getPropertyValue("--ha-card-background")||O.getPropertyValue("--card-background-color"),L=n.bg_color?n.bg_color:I;if(L&&(!e.color||L!==e.color)){const n=1.02;s=(0,t._k)(L,w/100,n),document.body.style.setProperty("--bubble-pop-up-background",s),e.color=L,window.color=L}return{customStyles:a,entityId:d,icon:p,name:h,widthDesktop:u,widthDesktopDivided:g,isSidebarHidden:b,state:_,stateChanged:m,stateOn:f,formatedState:c,riseAnimation:y,marginCenter:v,popUpOpen:r,rgbaColor:s,rgbColor:l,bgOpacity:w,shadowOpacity:x,bgBlur:k,iconColorOpacity:$,iconColor:S,iconFilter:C,iconStyles:E,haStyle:O,themeBgColor:I,color:L}}function h(e){const n=e._hass,r=e.editor,s=e.config;if(!n)return;let l,c,{customStyles:d,entityId:h,icon:u,name:g,widthDesktop:b,widthDesktopDivided:_,isSidebarHidden:m,state:f,stateChanged:y,stateOn:v,formatedState:w,riseAnimation:x,marginCenter:k,popUpOpen:$,rgbaColor:S,rgbColor:C,bgOpacity:E,shadowOpacity:O,bgBlur:I,iconColorOpacity:L,iconColor:T,iconFilter:A,iconStyles:V,haStyle:M,themeBgColor:q,color:U}=p(e,s,n),B=s.auto_close||!1,z=s.hash,D=s.trigger_entity?s.trigger_entity:"",P=s.trigger_state?s.trigger_state:"",j=!!s.trigger_close&&s.trigger_close;if(e.errorTriggered)return;e.initStyleAdded||e.popUp||r||(e.card.style.marginTop="4000px",e.initStyleAdded=!0);if(setTimeout((()=>{let i=e.getRootNode().querySelector("#root");if(i&&(!e.popUp||y||r&&!e.editorModeAdded)){e.popUp=i,(()=>{let i,p,x=e.popUp,C=s.text||"",E=s.state,L=s.margin_top_mobile&&"0"!==s.margin_top_mobile?s.margin_top_mobile:"0px",T=s.margin_top_desktop&&"0"!==s.margin_top_desktop?s.margin_top_desktop:"0px",A=s.entity?"flex":"none";if(f=E?n.states[E].state:"",w=E?n.formatEntityState(n.states[E]):"",e.headerAdded){if(h){const n=e.content.querySelector("#header-container .icon-container"),o=e.content.querySelector("#header-container h2"),i=e.content.querySelector("#header-container p"),a=e.content.querySelector("#header-container .power-button");n.innerHTML="",(0,t.IU)(e,h,u,n,r),o.textContent=g,i.textContent=w,a.setAttribute("style",`display: ${A};`)}}else{const n=document.createElement("div");n.setAttribute("id","header-container");const i=document.createElement("div");n.appendChild(i);const l=document.createElement("div");l.setAttribute("class","icon-container"),i.appendChild(l),(0,t.IU)(e,h,u,l,r),function(e,t,n,o){t.tap_action,t.double_tap_action,t.hold_action;let i,r=0,s=0,l=0;e.addEventListener("mousedown",(()=>{s=Date.now(),i=setTimeout((()=>{a(e,t,"hold")}),300)}),{passive:!0}),e.addEventListener("mouseup",(()=>{clearTimeout(i),l=Date.now(),l-s<300&&(r++,1===r&&setTimeout((()=>{1===r?a(e,t,"tap"):(a(e,t,"double_tap"),o("success")),r=0}),300)),s=0,l=0}),{passive:!0}),e.addEventListener("touchstart",(n=>{o("light"),s=Date.now(),i=setTimeout((()=>{a(e,t,"hold")}),300),n.preventDefault()}),{passive:!0}),e.addEventListener("touchend",(n=>{clearTimeout(i),l=Date.now(),l-s<300&&(r++,1===r&&setTimeout((()=>{a(e,t,1===r?"tap":"double_tap"),r=0}),300)),s=0,l=0,n.preventDefault()}),{passive:!0}),e.addEventListener("mouseout",(()=>{clearTimeout(i)}),{passive:!0}),e.addEventListener("touchcancel",(()=>{clearTimeout(i)}),{passive:!0})}(l,s,0,o);const c=document.createElement("h2");c.textContent=g,i.appendChild(c);const d=document.createElement("p");d.textContent=w,i.appendChild(d);const p=document.createElement("ha-icon");p.setAttribute("class","power-button"),p.setAttribute("icon","mdi:power"),p.setAttribute("style",`display: ${A};`),i.appendChild(p);const b=document.createElement("button");b.setAttribute("class","close-pop-up"),b.onclick=function(){history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+z,!0)},n.appendChild(b);const _=document.createElement("ha-icon");_.setAttribute("icon","mdi:close"),b.appendChild(_),e.content.appendChild(n),e.header=i,e.headerAdded=!0}function M(){!function(e,t){e.callService("homeassistant","toggle",{entity_id:t})}(n,h)}function q(e){"Escape"===e.key&&($=z+!1,history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+z,!0))}function D(e){window.hash===z&&R(),l=e.touches[0].clientY,c=l}function P(e){e.touches[0].clientY-l>300&&e.touches[0].clientY>c&&($=z+!1,history.replaceState(null,null,location.href.split("#")[0]),$=z+!1,localStorage.setItem("isManuallyClosed_"+z,!0)),c=e.touches[0].clientY}if(e.eventAdded||r||(window["checkHashRef_"+z]=function(){r||(window.hash=location.hash.split("?")[0],window.hash===z?setTimeout((function(){x.classList.remove("close-pop-up"),x.classList.add("open-pop-up"),j.querySelector(".power-button").addEventListener("click",M,{passive:!0}),window.addEventListener("keydown",q,{passive:!0}),x.addEventListener("touchstart",D,{passive:!0}),x.addEventListener("touchmove",P,{passive:!0}),$=z+!0,document.body.style.overflow="hidden",setTimeout((()=>{window.justOpened=!0}),10),W(x,!1),R()}),0):x.classList.contains("open-pop-up")&&(setTimeout((function(){x.classList.remove("open-pop-up"),x.classList.add("close-pop-up"),j.querySelector(".power-button").removeEventListener("click",M),window.removeEventListener("keydown",q),x.removeEventListener("touchstart",D),x.removeEventListener("touchmove",P),$=z+!1,document.body.style.overflow="",window.justOpened=!1,clearTimeout(i)}),0),setTimeout((function(){W(x,!0)}),320)))},window.addEventListener("urlChanged",window["checkHashRef_"+z],{passive:!0}),window.addEventListener("click",(function(e){if(location.hash===z&&R(),!window.justOpened)return;const t=e.composedPath();!t||t.some((e=>"HA-MORE-INFO-DIALOG"===e.nodeName))||t.some((e=>"root"===e.id&&!e.classList.contains("close-pop-up")))||$!==z+!0||setTimeout((function(){location.hash===z&&($=z+!1,history.replaceState(null,null,location.href.split("#")[0]),localStorage.setItem("isManuallyClosed_"+z,!0))}),0)}),{passive:!0}),e.eventAdded=!0),h){const o=n.states[h].attributes.rgb_color;e.rgbColor=o?(0,t.wW)(o)?"rgb(255,220,200)":`rgb(${o})`:v?h.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"rgba(255, 255, 255, 1",e.rgbColorOpacity=o?(0,t.wW)(o)?"rgba(255,220,200, 0.5)":`rgba(${o}, 0.5)`:h&&v?h.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"var(--background-color,var(--secondary-background-color))",p=(0,t._k)(U,0),e.iconFilter=o?(0,t.wW)(o)?"none":"brightness(1.1)":"none"}else p=(0,t._k)(U,0);let j=e.content;function W(e,t){for(var n=e.querySelectorAll("video"),o=0;o0&&!n[o].paused&&!n[o].ended&&n[o].readyState>n[o].HAVE_CURRENT_DATA;t&&i?n[o].pause():t||i||(n[o].play(),n[o].currentTime>0&&(n[o].currentTime=1e4))}var a=e.querySelectorAll("*");for(o=0;o0&&(i=setTimeout(H,B))}function H(){history.replaceState(null,null,location.href.split("#")[0])}const F=` \n ha-card {\n margin-top: 0 !important;\n background: none !important;\n border: none !important;\n }\n .card-content {\n width: 100% !important;\n padding: 0 !important;\n }\n #root {\n transition: all 1s !important;\n position: fixed !important;\n margin: 0 -${k}; /* 7px */\n width: 100%;\n ${s.bg_color||s.bg_opacity?"--bubble-pop-up-background-custom: "+S:""};\n background-color: var(--bubble-pop-up-background-custom, var(--bubble-pop-up-background));\n box-shadow: 0px 0px 50px rgba(0,0,0,${O/100});\n backdrop-filter: blur(${I}px);\n -webkit-backdrop-filter: blur(${I}px);\n border-radius: 42px;\n box-sizing: border-box;\n top: calc(120% + ${L} + var(--header-height));\n grid-gap: 12px !important;\n gap: 12px !important;\n grid-auto-rows: min-content;\n padding: 18px 18px 220px 18px !important;\n height: 100% !important;\n -ms-overflow-style: none; /* for Internet Explorer, Edge */\n scrollbar-width: none; /* for Firefox */\n overflow-y: auto; \n overflow-x: hidden; \n z-index: 1 !important; /* Higher value hide the more-info panel */\n /* For older Safari but not working with Firefox */\n /* display: grid !important; */ \n }\n #root.hidden {\n \tdisplay: none !important;\n }\n #root > :first-child::after {\n content: '';\n display: block;\n position: sticky;\n top: 0;\n left: -50px;\n margin: -70px 0 -36px -36px;\n overflow: visible;\n width: 200%;\n height: 100px;\n background: linear-gradient(0deg, ${p} 0%, ${S} 80%);\n z-index: 0;\n } \n #root::-webkit-scrollbar {\n display: none; /* for Chrome, Safari, and Opera */\n }\n #root > :first-child {\n position: sticky;\n top: 0;\n z-index: 1;\n background: none !important;\n overflow: visible;\n }\n #root.open-pop-up {\n /*will-change: transform;*/\n transform: translateY(-120%);\n transition: transform .36s !important;\n }\n #root.open-pop-up > * {\n /* Block child items to overflow and if they do clip them */\n /*max-width: calc(100vw - 38px);*/\n max-width: 100% !important;\n /*overflow-x: clip;*/\n }\n #root.close-pop-up { \n transform: translateY(-20%);\n transition: transform .4s !important;\n box-shadow: none;\n }\n @media only screen and (min-width: 600px) {\n #root {\n top: calc(120% + ${T} + var(--header-height));\n width: calc(${b}${"%"!==_[2]||m?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${_[1]/2}${_[2]});\n margin: 0 !important;\n }\n } \n @media only screen and (min-width: 870px) {\n #root {\n left: calc(50% - ${_[1]/2}${_[2]} + ${m?"0px":"var(--mdc-drawer-width) "+("%"===_[2]?"":"/ 2")});\n }\n } \n #root.editor {\n position: inherit !important;\n width: 100% !important;\n padding: 18px !important;\n }\n `,N=`\n ${V}\n\n ha-card {\n margin-top: 0 !important;\n }\n #header-container {\n display: inline-flex;\n ${u||g||h||f||C?"":"flex-direction: row-reverse;"}\n height: 50px;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n #header-container > div {\n display: ${u||g||h||f||C?"inline-flex":"none"};\n align-items: center;\n position: relative;\n padding-right: 6px;\n z-index: 1;\n flex-grow: 1;\n background-color: ${h?e.rgbColorOpacity:"var(--background-color,var(--secondary-background-color))"};\n transition: background 1s;\n border-radius: 25px;\n margin-right: 14px;\n backdrop-filter: blur(14px);\n -webkit-backdrop-filter: blur(14px);\n }\n #header-container h2 {\n display: inline-flex;\n margin: 0 18px 0 0;\n padding: 4px;\n z-index: 1;\n font-size: 18px;\n }\n #header-container p {\n display: inline-flex;\n font-size: 16px;\n min-width: fit-content ;\n }\n .power-button {\n cursor: pointer; \n flex-grow: inherit; \n width: 24px;\n height: 24px;\n border-radius: 12px;\n margin: 0 10px;\n background: none !important;\n justify-content: flex-end;\n background-color: var(--background-color,var(--secondary-background-color));\n }\n .close-pop-up {\n height: 50px;\n width: 50px;\n border: none;\n border-radius: 50%;\n z-index: 1;\n background: var(--background-color,var(--secondary-background-color));\n color: var(--primary-text-color);\n flex-shrink: 0;\n cursor: pointer;\n }\n `;e.popUpStyleAdded||((0,t.L2)(n,e,F,d,f,h,"","",x),e.popUpStyleAdded=!0),(0,t.L2)(n,e,N,d,f,h,y)})();const p=new Event("popUpInitialized");window.dispatchEvent(p),r&&(e.popUp.classList.add("editor"),e.editorModeAdded=!0)}else!r&&e.popUp&&(e.popUp.classList.remove("editor"),e.editorModeAdded=!1)}),0),e.popUp&&D&&y){null===localStorage.getItem("previousTriggerState_"+z)&&localStorage.setItem("previousTriggerState_"+z,""),null===localStorage.getItem("isManuallyClosed_"+z)&&localStorage.setItem("isManuallyClosed_"+z,"false"),null===localStorage.getItem("isTriggered_"+z)&&localStorage.setItem("isTriggered_"+z,"false");let t=localStorage.getItem("previousTriggerState_"+z),o="true"===localStorage.getItem("isManuallyClosed_"+z),a="true"===localStorage.getItem("isTriggered_"+z);n.states[D].state!==P||null!==t||a||(i(0,z),a=!0,localStorage.setItem("isTriggered_"+z,a)),n.states[D].state!==t&&(o=!1,localStorage.setItem("previousTriggerState_"+z,n.states[D].state),localStorage.setItem("isManuallyClosed_"+z,o)),n.states[D].state!==P||o?n.states[D].state!==P&&j&&e.popUp.classList.contains("open-pop-up")&&a&&!o&&(history.replaceState(null,null,location.href.split("#")[0]),$=z+!1,a=!1,o=!0,localStorage.setItem("isManuallyClosed_"+z,o),localStorage.setItem("isTriggered_"+z,a)):(i(0,z),a=!0,localStorage.setItem("isTriggered_"+z,a))}}new MutationObserver(((t,o)=>{if(customElements.get("ha-panel-lovelace")){const t=Object.getPrototypeOf(customElements.get("ha-panel-lovelace")),i=t.prototype.html,a=t.prototype.css;class r extends t{setConfig(e){this._config={...e}}static get properties(){return{hass:{},_config:{}}}get _entity(){return this._config.entity||""}get _name(){return this._config.name||""}get _icon(){return this._config.icon||""}get _state(){return this._config.state||""}get _text(){return this._config.text||""}get _hash(){return this._config.hash||"#pop-up-name"}get _trigger_entity(){return this._config.trigger_entity||""}get _trigger_state(){return this._config.trigger_state||""}get _trigger_close(){return this._config.trigger_close||!1}get _margin(){return this._config.margin||"7px"}get _margin_top_mobile(){return this._config.margin_top_mobile||"0px"}get _margin_top_desktop(){return this._config.margin_top_desktop||"0px"}get _width_desktop(){return this._config.width_desktop||"540px"}get _bg_color(){return this._config.bg_color||window.color}get _bg_opacity(){return void 0!==this._config.bg_opacity?this._config.bg_opacity:"88"}get _bg_blur(){return void 0!==this._config.bg_blur?this._config.bg_blur:"14"}get _shadow_opacity(){return void 0!==this._config.shadow_opacity?this._config.shadow_opacity:"0"}get _is_sidebar_hidden(){return this._config.is_sidebar_hidden||!1}get _auto_close(){return this._config.auto_close||""}get _back_open(){return this._config.back_open||!1}render(){if(!this.hass)return i``;if(!this.listsUpdated){const e=e=>({label:e,value:e});this.allEntitiesList=Object.keys(this.hass.states).map(e),this.lightList=Object.keys(this.hass.states).filter((e=>"light"===e.substr(0,e.indexOf(".")))).map(e),this.sensorList=Object.keys(this.hass.states).filter((e=>"sensor"===e.substr(0,e.indexOf(".")))).map(e),this.binarySensorList=Object.keys(this.hass.states).filter((e=>"binary_sensor"===e.substr(0,e.indexOf(".")))).map(e),this.coverList=Object.keys(this.hass.states).filter((e=>"cover"===e.substr(0,e.indexOf(".")))).map(e),this.cardTypeList=[{label:"Button",value:"button"},{label:"Cover",value:"cover"},{label:"Empty column",value:"empty-column"},{label:"Horizontal buttons stack",value:"horizontal-buttons-stack"},{label:"Pop-up",value:"pop-up"},{label:"Separator",value:"separator"}],this.buttonTypeList=[{label:"Switch",value:"switch"},{label:"Slider",value:"slider"}],this.listsUpdated=!0}const e=this.allEntitiesList;return this.lightList,this.sensorList,this.coverList,this.cardTypeList,this.buttonTypeList,i` +(()=>{"use strict";var __webpack_modules__={946:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{G:()=>getIconStyles,IU:()=>createIcon,L2:()=>addStyles,_k:()=>convertToRGBA,mk:()=>getIconColor,wW:()=>isColorCloseToWhite});const addStyles=function(hass,context,styles,customStyles,state,entityId,stateChanged,path="",element=context.content){const customStylesEval=customStyles?eval("`"+customStyles+"`"):"";let styleAddedKey=styles+"Added";if(!context[styleAddedKey]||context.previousStyle!==customStylesEval||stateChanged||context.previousConfig!==context.config){if(!context[styleAddedKey]){if(context.styleElement=element.querySelector("style"),!context.styleElement){context.styleElement=document.createElement("style");const e=path?element.querySelector(path):element;e?.appendChild(context.styleElement)}context[styleAddedKey]=!0}context.styleElement.innerHTML!==customStylesEval+styles&&(context.styleElement.innerHTML=customStylesEval+styles),context.previousStyle=customStylesEval,context.previousConfig=context.config}};function createIcon(e,t,n,o,i){let a=e._hass,r=!(!t||!a.states[t].attributes)&&a.states[t].attributes;e.imageUrl=!!r.entity_picture&&r.entity_picture,updateIcon(e,a,t,n,o),i||setInterval((()=>{a=e._hass,t&&a.states[t]&&(e.currentEntityPicture=a.states[t].attributes.entity_picture,e.currentEntityPicture!==e.previousEntityPicture&&(e.imageUrl=e.currentEntityPicture,updateIcon(e,a,t,n,o),e.previousEntityPicture=e.currentEntityPicture))}),1e3)}function updateIcon(e,t,n,o,i){for(;i.firstChild;)i.removeChild(i.firstChild);let a=e.config.icon&&e.config.icon.includes("/")?e.config.icon:e.imageUrl?e.imageUrl:"";if(a&&(r=t.states[n].state,n.startsWith("media_player.")&&!["off","unknown","idle",void 0].includes(r)||!n.startsWith("media_player."))){const e=document.createElement("div");e.setAttribute("class","entity-picture"),e.setAttribute("alt","Icon"),i&&(i.appendChild(e),i.style.background="center / cover no-repeat url("+a+"), var(--card-background-color,var(--ha-card-background))")}else{const e=document.createElement("ha-icon");e.setAttribute("icon",o),e.setAttribute("class","icon"),i&&i.appendChild(e)}var r}function isColorCloseToWhite(e){let t=[220,220,190];for(let n=0;n<3;n++)if(e[n]{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{var e="v1.6.0-beta.3";const t=function(){try{return document.querySelector("body > home-assistant").shadowRoot.querySelector("home-assistant-main").shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace").shadowRoot.querySelector("hui-root").shadowRoot.querySelector("div")}catch(e){return}}();var n=__webpack_require__(946);const o=(e,t,n,o)=>{o=o||{},n=null==n?{}:n;const i=new Event(t,{bubbles:void 0===o.bubbles||o.bubbles,cancelable:Boolean(o.cancelable),composed:void 0===o.composed||o.composed});return i.detail=n,e.dispatchEvent(i),i},i=e=>{o(window,"haptic",e)},a=(e,t,n=!1)=>{n?history.replaceState(null,"",t):history.pushState(null,"",t),o(window,"location-changed",{replace:n})};function r(e,t,n){const o={entity:t.entity,tap_action:{action:"more-info"},double_tap_action:{action:"toggle"},hold_action:{action:"toggle"}},i=new Event("hass-action",{bubbles:!0,composed:!0});i.detail={config:o,action:n},e.dispatchEvent(i)}let s,l,c,d,p;function h(e,t,o,i){let a=t.styles?t.styles:"",r=t.entity&&o.states[t.entity]?t.entity:"",p=!t.icon&&r?o.states[r].attributes.icon||o.states[r].attributes.entity_picture||"":t.icon||"",h=t.name?t.name:r?o.states[r].attributes.friendly_name:"",u=t.width_desktop||"540px",g=u?u.match(/(\d+)(\D+)/):"",b=t.is_sidebar_hidden||!1,_=r?o.states[r].state:"";!function(e,t,n){e.hasState=t.states[n],e.hasState&&(e.newState=[e.hasState.state,e.hasState.attributes.rgb_color],e.oldState&&e.newState[0]===e.oldState[0]&&e.newState[1]===e.oldState[1]?e.stateChanged=!1:(e.oldState=e.newState,e.stateChanged=!0),e.stateChanged)}(e,o,r);let m=e.stateChanged,f=["on","open","cleaning","true","home","playing"].includes(_)||0!==Number(_)&&!isNaN(Number(_)),y=void 0===t.rise_animation||t.rise_animation,w=t.margin?"0"!==t.margin?t.margin:"0px":"7px",v=void 0!==t.bg_opacity?t.bg_opacity:"88",x=void 0!==t.shadow_opacity?t.shadow_opacity:"0",k=void 0!==t.bg_blur?t.bg_blur:"10",{iconColorOpacity:S,iconColor:$,iconFilter:C}=(0,n.mk)(o,r,f,n.wW),E=(0,n.G)(r,f,$,C),I=getComputedStyle(document.body),T=I.getPropertyValue("--ha-card-background")||I.getPropertyValue("--card-background-color"),O=t.bg_color?t.bg_color:T;if(O&&(!e.color||O!==e.color)){const t=1.02;l=(0,n._k)(O,v/100,t),document.body.style.setProperty("--bubble-pop-up-background",l),e.color=O,window.color=O}return{customStyles:a,entityId:r,icon:p,name:h,widthDesktop:u,widthDesktopDivided:g,isSidebarHidden:b,state:_,stateChanged:m,stateOn:f,formatedState:d,riseAnimation:y,marginCenter:w,popUpOpen:s,rgbaColor:l,rgbColor:c,bgOpacity:v,shadowOpacity:x,bgBlur:k,iconColorOpacity:S,iconColor:$,iconFilter:C,iconStyles:E,haStyle:I,themeBgColor:T,color:O}}function u(e){const t=e._hass,s=e.editor,l=e.config;if(!t)return;let c,d,{customStyles:p,entityId:u,icon:g,name:b,widthDesktop:_,widthDesktopDivided:m,isSidebarHidden:f,state:y,stateChanged:w,stateOn:v,formatedState:x,riseAnimation:k,marginCenter:S,popUpOpen:$,rgbaColor:C,rgbColor:E,bgOpacity:I,shadowOpacity:T,bgBlur:O,iconColorOpacity:A,iconColor:L,iconFilter:M,iconStyles:V,haStyle:U,themeBgColor:q,color:D}=h(e,l,t),z=l.auto_close||!1,P=l.hash,R=l.trigger_entity?l.trigger_entity:"",W=l.trigger_state?l.trigger_state:"",B=!!l.trigger_close&&l.trigger_close;if(e.errorTriggered)return;e.initStyleAdded||e.popUp||s||(e.card.style.marginTop="4000px",e.initStyleAdded=!0);setTimeout((()=>{let a=e.getRootNode().querySelector("#root");if(a&&(!e.popUp||w||s&&!e.editorModeAdded)){e.popUp=a,(()=>{let a,h,k=e.popUp,E=l.text||"",I=l.state,A=l.margin_top_mobile&&"0"!==l.margin_top_mobile?l.margin_top_mobile:"0px",L=l.margin_top_desktop&&"0"!==l.margin_top_desktop?l.margin_top_desktop:"0px",M=l.entity?"flex":"none";if(y=I&&t.states[I]?t.states[I].state:"",x=I?t.formatEntityState(t.states[I]):"",e.headerAdded){if(u){const t=e.content.querySelector("#header-container .icon-container"),o=e.content.querySelector("#header-container h2"),i=e.content.querySelector("#header-container p"),a=e.content.querySelector("#header-container .power-button");t.innerHTML="",(0,n.IU)(e,u,g,t,s),o.textContent=b,i.textContent=x,a.setAttribute("style",`display: ${M};`)}}else{const t=document.createElement("div");t.setAttribute("id","header-container");const a=document.createElement("div");t.appendChild(a);const c=document.createElement("div");c.setAttribute("class","icon-container"),a.appendChild(c),(0,n.IU)(e,u,g,c,s),function(e,t,n,o){t.tap_action,t.double_tap_action,t.hold_action;let i,a,s=!1,l=0,c=0,d=0,p=0;e.addEventListener("mousedown",(()=>{d=Date.now(),a=setTimeout((()=>{r(e,t,"hold")}),300)}),{passive:!0}),e.addEventListener("mouseup",(()=>{clearTimeout(a),p=Date.now(),p-d<300&&(c++,1===c&&setTimeout((()=>{1===c?r(e,t,"tap"):(r(e,t,"double_tap"),o("success")),c=0}),300)),d=0,p=0}),{passive:!0}),e.addEventListener("touchstart",(n=>{s=!0,s&&o("light"),d=Date.now(),a=setTimeout((()=>{r(e,t,"hold")}),300),"touchstart"!==n.type&&n.preventDefault()}),{passive:!0}),e.addEventListener("touchend",(function(n){let o=(new Date).getTime(),s=o-l;clearTimeout(a),s<500&&s>0?(clearTimeout(i),r(e,t,"double_tap")):i=setTimeout((function(){r(e,t,"tap")}),300),l=o}),{passive:!0}),e.addEventListener("mouseout",(()=>{clearTimeout(a)}),{passive:!0}),e.addEventListener("touchcancel",(()=>{clearTimeout(a)}),{passive:!0})}(c,l,0,i);const d=document.createElement("h2");d.textContent=b,a.appendChild(d);const p=document.createElement("p");p.textContent=x,a.appendChild(p);const h=document.createElement("ha-icon");h.setAttribute("class","power-button"),h.setAttribute("icon","mdi:power"),h.setAttribute("style",`display: ${M};`),a.appendChild(h);const _=document.createElement("button");_.setAttribute("class","close-pop-up"),_.onclick=function(){history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+P,!0)},t.appendChild(_);const m=document.createElement("ha-icon");m.setAttribute("icon","mdi:close"),_.appendChild(m),e.content.appendChild(t),e.header=a,e.headerAdded=!0}function U(){!function(e,t){e.callService("homeassistant","toggle",{entity_id:t})}(t,u)}function q(e){"Escape"===e.key&&($=P+!1,history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+P,!0))}function R(e){window.hash===P&&j(),c=e.touches[0].clientY,d=c}function W(e){e.touches[0].clientY-c>300&&e.touches[0].clientY>d&&($=P+!1,history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+P,!0)),d=e.touches[0].clientY}if(e.eventAdded||s||(window["checkHashRef_"+P]=function(){s||(window.hash=location.hash.split("?")[0],window.hash===P?(k.classList.remove("close-pop-up"),k.classList.add("open-pop-up"),setTimeout((function(){B.querySelector(".power-button").addEventListener("click",U,{passive:!0}),window.addEventListener("keydown",q,{passive:!0}),k.addEventListener("touchstart",R,{passive:!0}),k.addEventListener("touchmove",W,{passive:!0}),$=P+!0,document.body.style.overflow="hidden",setTimeout((()=>{window.justOpened=!0}),10),H(k,!1),j()}),0)):k.classList.contains("open-pop-up")&&(k.classList.remove("open-pop-up"),k.classList.add("close-pop-up"),setTimeout((function(){B.querySelector(".power-button").removeEventListener("click",U),window.removeEventListener("keydown",q),k.removeEventListener("touchstart",R),k.removeEventListener("touchmove",W),$=P+!1,document.body.style.overflow="",window.justOpened=!1,clearTimeout(a)}),0),setTimeout((function(){H(k,!0)}),320)))},window.addEventListener("urlChanged",window["checkHashRef_"+P],{passive:!0}),window.addEventListener("click",(function(e){if(window.hash===P&&j(),!window.justOpened)return;const t=e.composedPath();!t||t.some((e=>"HA-MORE-INFO-DIALOG"===e.nodeName))||t.some((e=>"root"===e.id&&!e.classList.contains("close-pop-up")))||$!==P+!0||setTimeout((function(){window.hash===P&&($=P+!1,history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0),localStorage.setItem("isManuallyClosed_"+P,!0))}),10)}),{passive:!0}),e.eventAdded=!0),u){const o=t.states[u].attributes.rgb_color;e.rgbColor=o?(0,n.wW)(o)?"rgb(255,220,200)":`rgb(${o})`:v?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"rgba(255, 255, 255, 1",e.rgbColorOpacity=o?(0,n.wW)(o)?"rgba(255,220,200, 0.5)":`rgba(${o}, 0.5)`:u&&v?u.startsWith("light.")?"rgba(255,220,200, 0.5)":"var(--accent-color)":"var(--background-color,var(--secondary-background-color))",h=(0,n._k)(D,0),e.iconFilter=o?(0,n.wW)(o)?"none":"brightness(1.1)":"none"}else h=(0,n._k)(D,0);let B=e.content;function H(e,t){for(var n=e.querySelectorAll("video"),o=0;o0&&!n[o].paused&&!n[o].ended&&n[o].readyState>n[o].HAVE_CURRENT_DATA;t&&i?n[o].pause():t||i||(n[o].play(),n[o].currentTime>0&&(n[o].currentTime=1e4))}var a=e.querySelectorAll("*");for(o=0;o0&&(a=setTimeout(F,z))}function F(){history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0)}const N=` \n ha-card {\n margin-top: 0 !important;\n background: none !important;\n border: none !important;\n }\n .card-content {\n width: 100% !important;\n padding: 0 !important;\n }\n #root {\n \ttransition: transform .36s !important;\n position: fixed !important;\n margin: 0 -${S}; /* 7px */\n width: 100%;\n ${l.bg_color||l.bg_opacity?"--bubble-pop-up-background-custom: "+C:""};\n background-color: var(--bubble-pop-up-background-custom, var(--bubble-pop-up-background));\n box-shadow: 0px 0px 50px rgba(0,0,0,${T/100});\n backdrop-filter: blur(${O}px);\n -webkit-backdrop-filter: blur(${O}px);\n border-radius: 42px;\n box-sizing: border-box;\n top: calc(120% + ${A} + var(--header-height));\n grid-gap: 12px !important;\n gap: 12px !important;\n grid-auto-rows: min-content;\n padding: 18px 18px 220px 18px !important;\n height: 100% !important;\n -ms-overflow-style: none; /* for Internet Explorer, Edge */\n scrollbar-width: none; /* for Firefox */\n overflow-y: auto; \n overflow-x: hidden; \n z-index: 1 !important; /* Higher value hide the more-info panel */\n /* For older Safari but not working with Firefox */\n /* display: grid !important; */ \n }\n #root.hidden {\n \tdisplay: none !important;\n }\n #root > :first-child::after {\n content: '';\n display: block;\n position: sticky;\n top: 0;\n left: -50px;\n margin: -70px 0 -36px -36px;\n overflow: visible;\n width: 200%;\n height: 100px;\n background: linear-gradient(0deg, ${h} 0%, ${C} 80%);\n z-index: 0;\n } \n #root::-webkit-scrollbar {\n display: none; /* for Chrome, Safari, and Opera */\n }\n #root > :first-child {\n position: sticky;\n top: 0;\n z-index: 1;\n background: none !important;\n overflow: visible;\n }\n #root.open-pop-up {\n will-change: transform, backdrop-filter;\n transform: translateY(-120%);\n }\n #root.open-pop-up > * {\n /* Block child items to overflow and if they do clip them */\n /*max-width: calc(100vw - 38px);*/\n max-width: 100% !important;\n /*overflow-x: clip;*/\n }\n #root.close-pop-up { \n transform: translateY(-20%);\n box-shadow: none;\n backdrop-filter: none !important;\n }\n @media only screen and (min-width: 600px) {\n #root {\n top: calc(120% + ${L} + var(--header-height));\n width: calc(${_}${"%"!==m[2]||f?"":" - var(--mdc-drawer-width)"}) !important;\n left: calc(50% - ${m[1]/2}${m[2]});\n margin: 0 !important;\n }\n } \n @media only screen and (min-width: 870px) {\n #root {\n left: calc(50% - ${m[1]/2}${m[2]} + ${f?"0px":"var(--mdc-drawer-width) "+("%"===m[2]?"":"/ 2")});\n }\n } \n #root.editor {\n position: inherit !important;\n width: 100% !important;\n padding: 18px !important;\n backdrop-filter: none !important;\n }\n `,Y=`\n ${V}\n\n ha-card {\n margin-top: 0 !important;\n }\n #header-container {\n display: inline-flex;\n ${g||b||u||y||E?"":"flex-direction: row-reverse;"}\n height: 50px;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n #header-container > div {\n display: ${g||b||u||y||E?"inline-flex":"none"};\n align-items: center;\n position: relative;\n padding-right: 6px;\n z-index: 1;\n flex-grow: 1;\n background-color: ${u?e.rgbColorOpacity:"var(--background-color,var(--secondary-background-color))"};\n transition: background 1s;\n border-radius: 25px;\n margin-right: 14px;\n backdrop-filter: blur(14px);\n -webkit-backdrop-filter: blur(14px);\n }\n #header-container h2 {\n display: inline-flex;\n margin: 0 18px 0 0;\n padding: 4px;\n z-index: 1;\n font-size: 18px;\n }\n #header-container p {\n display: inline-flex;\n font-size: 16px;\n min-width: fit-content ;\n }\n .power-button {\n cursor: pointer; \n flex-grow: inherit; \n width: 24px;\n height: 24px;\n border-radius: 12px;\n margin: 0 10px;\n background: none !important;\n justify-content: flex-end;\n background-color: var(--background-color,var(--secondary-background-color));\n }\n .close-pop-up {\n height: 50px;\n width: 50px;\n border: none;\n border-radius: 50%;\n z-index: 1;\n background: var(--background-color,var(--secondary-background-color));\n color: var(--primary-text-color);\n flex-shrink: 0;\n cursor: pointer;\n }\n `;e.popUpStyleAdded||((0,n.L2)(t,e,N,p,y,u,"","",k),e.popUpStyleAdded=!0),(0,n.L2)(t,e,Y,p,y,u,w)})();const h=new Event("popUpInitialized");window.dispatchEvent(h),s&&e.popUp&&!e.editorModeAdded&&(e.popUp.classList.add("editor"),e.popUp.classList.remove("close-pop-up","open-pop-up"),e.editorModeAdded=!0)}else!s&&e.popUp&&e.editorModeAdded&&(e.popUp.classList.remove("editor"),e.editorModeAdded=!1)}),0),setTimeout((()=>{if(e.popUp&&R&&w){null===localStorage.getItem("previousTriggerState_"+P)&&localStorage.setItem("previousTriggerState_"+P,""),null===localStorage.getItem("isManuallyClosed_"+P)&&localStorage.setItem("isManuallyClosed_"+P,"false"),null===localStorage.getItem("isTriggered_"+P)&&localStorage.setItem("isTriggered_"+P,"false");let n=localStorage.getItem("previousTriggerState_"+P),i="true"===localStorage.getItem("isManuallyClosed_"+P),r="true"===localStorage.getItem("isTriggered_"+P);t.states[R].state!==W||null!==n||r||(a(0,P),r=!0,localStorage.setItem("isTriggered_"+P,r)),t.states[R].state!==n&&(i=!1,localStorage.setItem("previousTriggerState_"+P,t.states[R].state),localStorage.setItem("isManuallyClosed_"+P,i)),t.states[R].state!==W||i?t.states[R].state!==W&&B&&e.popUp.classList.contains("open-pop-up")&&r&&!i&&(history.replaceState(null,null,location.href.split("#")[0]),o(window,"location-changed",!0),$=P+!1,r=!1,i=!0,localStorage.setItem("isManuallyClosed_"+P,i),localStorage.setItem("isTriggered_"+P,r)):(a(0,P),r=!0,localStorage.setItem("isTriggered_"+P,r))}}),0)}new MutationObserver(((t,n)=>{if(customElements.get("ha-panel-lovelace")){const t=Object.getPrototypeOf(customElements.get("ha-panel-lovelace")),i=t.prototype.html,a=t.prototype.css;class r extends t{setConfig(e){this._config={...e}}static get properties(){return{hass:{},_config:{}}}get _entity(){return this._config.entity||""}get _name(){return this._config.name||""}get _icon(){return this._config.icon||""}get _state(){return this._config.state||""}get _text(){return this._config.text||""}get _hash(){return this._config.hash||"#pop-up-name"}get _trigger_entity(){return this._config.trigger_entity||""}get _trigger_state(){return this._config.trigger_state||""}get _trigger_close(){return this._config.trigger_close||!1}get _margin(){return this._config.margin||"7px"}get _margin_top_mobile(){return this._config.margin_top_mobile||"0px"}get _margin_top_desktop(){return this._config.margin_top_desktop||"0px"}get _width_desktop(){return this._config.width_desktop||"540px"}get _bg_color(){return this._config.bg_color||window.color}get _bg_opacity(){return void 0!==this._config.bg_opacity?this._config.bg_opacity:"88"}get _bg_blur(){return void 0!==this._config.bg_blur?this._config.bg_blur:"14"}get _shadow_opacity(){return void 0!==this._config.shadow_opacity?this._config.shadow_opacity:"0"}get _is_sidebar_hidden(){return this._config.is_sidebar_hidden||!1}get _auto_close(){return this._config.auto_close||""}get _back_open(){return this._config.back_open||!1}render(){if(!this.hass)return i``;if(!this.listsUpdated){const e=e=>({label:e,value:e});this.allEntitiesList=Object.keys(this.hass.states).map(e),this.listsUpdated=!0}const e=this.allEntitiesList;return this.lightList,this.cardTypeList,this.buttonTypeList,i`

Pop-up You can't set a value to 0 with the sliders for now, just change it to 0 in the text field if you need to. -

Advanced settings

- - -
- -
-
- Back button/event support : This allow you to navigate through your pop-ups history when you press the back button of your browser. This setting can be applied only once, you don't need to change it in all pop-ups. If it's not working just turn it on for each pop-ups. ${this.makeVersion()}

`}makeDropdown(e,t,n){return this.hass,e.includes("icon")||e.includes("Icon")?i` @@ -199,51 +186,7 @@ @value-changed="${this._valueChanged}" >

- `}makeButton(){let e=[];for(let t=1;t<=this.buttonIndex;t++)e.push(i` -
-
- this.removeButton(t)}> - Button ${t} -
- - - - - -
- `);return e}makeVersion(){return i` + `}makeVersion(){return i`

{t<10?(window.dispatchEvent(e),t++):clearInterval(n)}),1e3)}window.popUpInitialized=!1,["click","mousedown","touchstart","focus","location-changed","connection-status"].forEach((e=>{window.addEventListener(e,t)}),{passive:!0});const n=()=>{window.dispatchEvent(e),window.addEventListener("popstate",t,{passive:!0})};window.addEventListener("popUpInitialized",n,{passive:!0}),window.eventAdded=!0}}();class u extends HTMLElement{set hass(e){var t;this._hass=e,d=document.querySelector("body > home-assistant").shadowRoot.querySelector("home-assistant-main").shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace").shadowRoot.querySelector("hui-root").shadowRoot.querySelector("div").classList.contains("edit-mode"),this.editor=d,async function(e){if(!window.resourcesChecked){window.resourcesChecked=!0;let t=(await e.callWS({type:"lovelace/resources"})).find((e=>e.url.includes("bubble-pop-up.js")));t&&await e.callWS({type:"lovelace/resources/delete",resource_id:t.id})}}(e),(t=this).content||(t.attachShadow({mode:"open"}),t.shadowRoot.innerHTML='\n \n
\n
\n
\n ',t.card=t.shadowRoot.querySelector("ha-card"),t.content=t.shadowRoot.querySelector("div")),h(this)}setConfig(e){if(!e.hash)throw new Error("You need to define an hash. Please note that this card must be placed inside a vertical_stack to work as a pop-up.");this.config=e}getCardSize(){return-1e4}static getConfigElement(){return document.createElement("bubble-pop-up-editor")}}new MutationObserver(((e,t)=>{customElements.get("ha-panel-lovelace")&&(customElements.define("bubble-pop-up",u),t.disconnect())})).observe(document,{childList:!0,subtree:!0}),window.customCards=window.customCards||[],window.customCards.push({type:"bubble-pop-up",name:"Bubble Pop-up",preview:!1,description:"Just add it in a vertical-stack first."}),console.info(`%c Bubble Card - Pop-up %c ${e} `,"background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 14px 0 0 14px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)","background-color: #506eac;color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 14px 14px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)")})()})(); \ No newline at end of file + `}}customElements.define("bubble-pop-up-editor",r),n.disconnect()}})).observe(document,{childList:!0,subtree:!0}),function(){if(!window.eventAdded){const e=new Event("urlChanged");function t(){let t=0;window.dispatchEvent(e);const n=setInterval((()=>{t<10?(window.dispatchEvent(e),t++):clearInterval(n)}),1e3)}window.popUpInitialized=!1,["location-changed","connection-status"].forEach((e=>{window.addEventListener(e,t)}),{passive:!0});const n=()=>{window.dispatchEvent(e),window.addEventListener("popstate",t,{passive:!0})};window.addEventListener("popUpInitialized",n,{passive:!0}),window.eventAdded=!0}}();class g extends HTMLElement{set hass(e){var n;this._hass=e,p=function(){if(t)return t.classList.contains("edit-mode")}(),this.editor=p,(n=this).content||(n.attachShadow({mode:"open"}),n.shadowRoot.innerHTML='\n \n
\n
\n
\n ',n.card=n.shadowRoot.querySelector("ha-card"),n.content=n.shadowRoot.querySelector("div")),u(this)}setConfig(e){if(!e.hash)throw new Error("You need to define an hash. Please note that this card must be placed inside a vertical_stack to work as a pop-up.");this.config=e}getCardSize(){return-1e4}static getConfigElement(){return document.createElement("bubble-pop-up-editor")}}new MutationObserver(((e,t)=>{customElements.get("ha-panel-lovelace")&&(customElements.define("bubble-pop-up",g),t.disconnect())})).observe(document,{childList:!0,subtree:!0}),window.customCards=window.customCards||[],window.customCards.push({type:"bubble-pop-up",name:"Bubble Pop-up",preview:!1,description:"Just add it in a vertical-stack first."}),console.info(`%c Bubble Card - Pop-up %c ${e} `,"background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 14px 0 0 14px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)","background-color: #506eac;color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 14px 14px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)")})()})(); \ No newline at end of file diff --git a/src/bubble-card.ts b/src/bubble-card.ts index 71e48d2b..27fa2dec 100644 --- a/src/bubble-card.ts +++ b/src/bubble-card.ts @@ -1,6 +1,6 @@ import { version } from './var/version.ts'; import { addUrlListener } from './tools/url-listener.ts'; -import { initializeContent, checkEditor } from './tools/init.ts'; +import { initializeContent, checkEditor, checkResources } from './tools/init.ts'; import { handlePopUp } from './cards/pop-up.ts'; import { handleHorizontalButtonsStack } from './cards/horizontal-buttons-stack.ts'; import { handleButton } from './cards/button.ts'; @@ -17,10 +17,12 @@ class BubbleCard extends HTMLElement { set hass(hass) { this._hass = hass; - + editor = checkEditor(); this.editor = editor; + checkResources(hass); + initializeContent(this); switch (this.config.card_type) { diff --git a/src/bubble-pop-up.ts b/src/bubble-pop-up.ts index dbb745d2..3ddbb647 100644 --- a/src/bubble-pop-up.ts +++ b/src/bubble-pop-up.ts @@ -1,6 +1,6 @@ import { version } from './var/version.ts'; import { addUrlListener } from './tools/url-listener.ts'; -import { initializeContent, checkEditor, checkResources } from './tools/init.ts'; +import { initializeContent, checkEditor } from './tools/init.ts'; import { handlePopUp } from './cards/pop-up.ts'; import { bubblePopUpEditor } from './editor/bubble-pop-up-editor.ts'; @@ -12,12 +12,10 @@ class BubblePopUp extends HTMLElement { set hass(hass) { this._hass = hass; - + editor = checkEditor(); this.editor = editor; - checkResources(hass); - initializeContent(this); // Initialize pop-up card diff --git a/src/cards/button.ts b/src/cards/button.ts index 7f24e980..daab21fd 100644 --- a/src/cards/button.ts +++ b/src/cards/button.ts @@ -8,14 +8,7 @@ import { getIconStyles } from '../tools/style.ts'; import { - initializeContent, - checkEditor, - checkResources -} from '../tools/init.ts'; -import { - fireEvent, forwardHaptic, - navigate, toggleEntity, hasStateChanged } from '../tools/utils.ts'; @@ -56,7 +49,7 @@ export function handleButton(context) { color, } = getVariables(context, context.config, hass, editor); - formatedState = stateChanged || editor ? hass.formatEntityState(hass.states[entityId]) : formatedState || ''; + formatedState = entityId && (stateChanged || editor) ? hass.formatEntityState(hass.states[entityId]) : ''; const buttonType = context.config.button_type || 'switch'; const showState = !context.config.show_state ? false : context.config.show_state; let currentBrightness = !entityId ? '' : hass.states[entityId].attributes.brightness || 0; diff --git a/src/cards/horizontal-buttons-stack.ts b/src/cards/horizontal-buttons-stack.ts index 68bae294..2d300f1e 100644 --- a/src/cards/horizontal-buttons-stack.ts +++ b/src/cards/horizontal-buttons-stack.ts @@ -3,21 +3,12 @@ import { createIcon, updateIcon, isColorCloseToWhite, - convertToRGBA, - getIconColor, - getIconStyles + convertToRGBA } from '../tools/style.ts'; +import { checkEditor } from '../tools/init.ts'; import { - initializeContent, - checkEditor, - checkResources -} from '../tools/init.ts'; -import { - fireEvent, forwardHaptic, - navigate, - toggleEntity, - hasStateChanged + navigate } from '../tools/utils.ts'; import { addActions } from '../tools/tap-actions.ts'; import { getVariables } from '../var/cards.ts'; @@ -25,7 +16,7 @@ import { getVariables } from '../var/cards.ts'; export function handleHorizontalButtonsStack(context) { const hass = context._hass; - const editor = context.editor; + let editor; let { customStyles, @@ -55,6 +46,20 @@ export function handleHorizontalButtonsStack(context) { color, } = getVariables(context, context.config, hass, editor); + let editorMode = setInterval(() => { + editor = checkEditor(); + + if (editor && !context.editorModeAdded) { + context.buttonsContainer.classList.add('editor'); + context.card.classList.add('editor'); + context.editorModeAdded = true; + } else if (!editor && context.editorModeAdded) { + context.buttonsContainer.classList.remove('editor'); + context.card.classList.remove('editor'); + context.editorModeAdded = false; + } + }, 100); + const createButton = (button, link, icon) => { const buttonElement = document.createElement("button"); buttonElement.setAttribute("class", `button ${link.substring(1)}`); @@ -65,8 +70,6 @@ export function handleHorizontalButtonsStack(context) { if (!buttonElement.hasListener) { buttonElement.addEventListener('click', (event) => { - event.stopPropagation(); - forwardHaptic("light"); popUpOpen = location.hash + true; const manuallyClosed = localStorage.getItem('isManuallyClosed_' + link) === 'true'; if (popUpOpen !== link + true) { @@ -76,6 +79,8 @@ export function handleHorizontalButtonsStack(context) { history.replaceState(null, null, location.href.split('#')[0]); popUpOpen = link + false; } + event.stopPropagation(); + forwardHaptic("light"); }, { passive: true }); window.addEventListener('urlChanged', highlightButton, { passive: true }); @@ -180,9 +185,6 @@ export function handleHorizontalButtonsStack(context) { while (context.buttonsContainer.firstChild) { context.buttonsContainer.removeChild(context.buttonsContainer.firstChild); } - localStorage.setItem('editorMode', true); - } else { - localStorage.setItem('editorMode', false); } // End of fix @@ -199,8 +201,8 @@ export function handleHorizontalButtonsStack(context) { let currentPosition = 0; let buttonMargin = 12; - - async function updateButtons(context) { + + function updateButtons(context) { if (context.buttonsUpdated) { return; } @@ -213,29 +215,31 @@ export function handleHorizontalButtonsStack(context) { promises.push(localStorage.getItem(`buttonContent-${button.link}`)); } } - let results = await Promise.all(promises); - let index = 0; - for (let button of buttonsList) { - let buttonElement = context.buttons[button.link]; - if (buttonElement) { - let buttonWidth = results[index]; - let buttonContent = results[index + 1]; - index += 2; - if (!buttonWidth || buttonWidth === '0' || buttonContent !== buttonElement.innerHTML || editor) { - buttonWidth = buttonElement.offsetWidth; - await localStorage.setItem(`buttonWidth-${button.link}`, buttonWidth); - await localStorage.setItem(`buttonContent-${button.link}`, buttonElement.innerHTML); - context.previousConfig = context.config; + + Promise.all(promises).then(results => { + let index = 0; + for (let button of buttonsList) { + let buttonElement = context.buttons[button.link]; + if (buttonElement) { + let buttonWidth = results[index]; + let buttonContent = results[index + 1]; + index += 2; + if (!buttonWidth || buttonWidth === '0' || buttonContent !== buttonElement.innerHTML || editor) { + buttonWidth = buttonElement.offsetWidth; + localStorage.setItem(`buttonWidth-${button.link}`, buttonWidth); + localStorage.setItem(`buttonContent-${button.link}`, buttonElement.innerHTML); + context.previousConfig = context.config; + } + buttonElement.style.transform = `translateX(${currentPosition}px)`; + currentPosition += parseInt(buttonWidth) + buttonMargin; + } + if (button.lightEntity) { + updateButtonStyle(buttonElement, button.lightEntity, button.link); } - buttonElement.style.transform = `translateX(${currentPosition}px)`; - currentPosition += parseInt(buttonWidth) + buttonMargin; - } - if (button.lightEntity) { - updateButtonStyle(buttonElement, button.lightEntity, button.link); } - } - context.buttonsAdded = true; + context.buttonsAdded = true; + }); } updateButtons(context); @@ -379,12 +383,4 @@ export function handleHorizontalButtonsStack(context) { } addStyles(hass, context, horizontalButtonsStackStyles, customStyles); - - if (editor) { - context.buttonsContainer.classList.add('editor'); - context.card.classList.add('editor'); - } else { - context.buttonsContainer.classList.remove('editor'); - context.card.classList.remove('editor'); - } } \ No newline at end of file diff --git a/src/cards/pop-up-old.ts b/src/cards/pop-up-old.ts index 1fb64924..c7cd8fce 100644 --- a/src/cards/pop-up-old.ts +++ b/src/cards/pop-up-old.ts @@ -1,3 +1,17 @@ + //

Advanced settings

+ // + // + //
+ // + //
+ //
+ // Back button/event support : This allow you to navigate through your pop-ups history when you press the back button of your browser. This setting can be applied only once, you don't need to change it in all pop-ups. If it's not working just turn it on for each pop-ups. + import { addStyles, createIcon, diff --git a/src/cards/pop-up.ts b/src/cards/pop-up.ts index fe5a7ab2..b3f12e39 100644 --- a/src/cards/pop-up.ts +++ b/src/cards/pop-up.ts @@ -90,7 +90,7 @@ export function handlePopUp(context) { ? (config.margin_top_desktop !== '0' ? config.margin_top_desktop : '0px') : '0px'; let displayPowerButton = config.entity ? 'flex' : 'none'; - state = stateEntityId ? hass.states[stateEntityId].state : ''; + state = stateEntityId && hass.states[stateEntityId] ? hass.states[stateEntityId].state : ''; formatedState = stateEntityId ? hass.formatEntityState(hass.states[stateEntityId]) : ''; let closeTimeout; let rgbaBgColor; @@ -125,7 +125,11 @@ export function handlePopUp(context) { const button = document.createElement("button"); button.setAttribute("class", "close-pop-up"); - button.onclick = function() { history.replaceState(null, null, location.href.split('#')[0]); localStorage.setItem('isManuallyClosed_' + popUpHash, true); }; + button.onclick = function() { + history.replaceState(null, null, location.href.split('#')[0]); + fireEvent(window, "location-changed", true); + localStorage.setItem('isManuallyClosed_' + popUpHash, true); + }; headerContainer.appendChild(button); const haIcon3 = document.createElement("ha-icon"); @@ -149,36 +153,39 @@ export function handlePopUp(context) { p.textContent = formatedState; haIcon2.setAttribute("style", `display: ${displayPowerButton};`); } + + function closePopUpByClickingOutside(e) { + // Reset auto close + window.hash === popUpHash && resetAutoClose(); + + if (!window.justOpened) { + return; + } + + const target = e.composedPath(); + + if ( + target + && !target.some(el => el.nodeName === 'HA-MORE-INFO-DIALOG') + && !target.some(el => el.id === 'root' + && !el.classList.contains('close-pop-up')) + && popUpOpen === popUpHash + true + ){ + setTimeout(function() { + if (window.hash === popUpHash) { + popUpOpen = popUpHash + false; + history.replaceState(null, null, location.href.split('#')[0]); + fireEvent(window, "location-changed", true); + localStorage.setItem('isManuallyClosed_' + popUpHash, true); + } + }, 10); + } + } if (!context.eventAdded && !editor) { window['checkHashRef_' + popUpHash] = checkHash; window.addEventListener('urlChanged', window['checkHashRef_' + popUpHash], { passive: true }); - window.addEventListener('click', function(e) { - // Reset auto close - location.hash === popUpHash && resetAutoClose(); - - if (!window.justOpened) { - return; - } - - const target = e.composedPath(); - - if ( - target - && !target.some(el => el.nodeName === 'HA-MORE-INFO-DIALOG') - && !target.some(el => el.id === 'root' - && !el.classList.contains('close-pop-up')) - && popUpOpen === popUpHash + true - ){ - setTimeout(function() { - if (location.hash === popUpHash) { - popUpOpen = popUpHash + false; - history.replaceState(null, null, location.href.split('#')[0]); - localStorage.setItem('isManuallyClosed_' + popUpHash, true); - } - }, 0); - } - }, { passive: true }); + window.addEventListener('click', closePopUpByClickingOutside, { passive: true }); context.eventAdded = true; } @@ -191,6 +198,7 @@ export function handlePopUp(context) { if (e.key === 'Escape') { popUpOpen = popUpHash + false; history.replaceState(null, null, location.href.split('#')[0]); + fireEvent(window, "location-changed", true); localStorage.setItem('isManuallyClosed_' + popUpHash, true) } } @@ -214,7 +222,7 @@ export function handlePopUp(context) { if (touchMoveDistance > 300 && event.touches[0].clientY > lastTouchY) { popUpOpen = popUpHash + false; history.replaceState(null, null, location.href.split('#')[0]); - popUpOpen = popUpHash + false; + fireEvent(window, "location-changed", true); localStorage.setItem('isManuallyClosed_' + popUpHash, true) } @@ -284,25 +292,25 @@ export function handlePopUp(context) { } function openPopUp() { + popUp.classList.remove('close-pop-up'); + popUp.classList.add('open-pop-up'); setTimeout(function() { - popUp.classList.remove('close-pop-up'); - popUp.classList.add('open-pop-up'); - content.querySelector('.power-button').addEventListener('click', powerButtonClickHandler, { passive: true }); - window.addEventListener('keydown', windowKeydownHandler, { passive: true }); - popUp.addEventListener('touchstart', popUpTouchstartHandler, { passive: true }); - popUp.addEventListener('touchmove', popUpTouchmoveHandler, { passive: true }); - popUpOpen = popUpHash + true; - document.body.style.overflow = 'hidden'; // Fix scroll inside pop-ups only - setTimeout(() => { window.justOpened = true; }, 10); - pauseVideos(popUp, false); - resetAutoClose(); + content.querySelector('.power-button').addEventListener('click', powerButtonClickHandler, { passive: true }); + window.addEventListener('keydown', windowKeydownHandler, { passive: true }); + popUp.addEventListener('touchstart', popUpTouchstartHandler, { passive: true }); + popUp.addEventListener('touchmove', popUpTouchmoveHandler, { passive: true }); + popUpOpen = popUpHash + true; + document.body.style.overflow = 'hidden'; // Fix scroll inside pop-ups only + setTimeout(() => { window.justOpened = true; }, 10); + pauseVideos(popUp, false); + resetAutoClose(); }, 0); } function closePopUp() { - setTimeout(function() { - popUp.classList.remove('open-pop-up'); - popUp.classList.add('close-pop-up'); + popUp.classList.remove('open-pop-up'); + popUp.classList.add('close-pop-up'); + setTimeout(function() { content.querySelector('.power-button').removeEventListener('click', powerButtonClickHandler); window.removeEventListener('keydown', windowKeydownHandler); popUp.removeEventListener('touchstart', popUpTouchstartHandler); @@ -329,6 +337,7 @@ export function handlePopUp(context) { function autoClosePopUp(){ history.replaceState(null, null, location.href.split('#')[0]); + fireEvent(window, "location-changed", true); } const popUpStyles = ` @@ -342,7 +351,7 @@ export function handlePopUp(context) { padding: 0 !important; } #root { - transition: all 1s !important; + transition: transform .36s !important; position: fixed !important; margin: 0 -${marginCenter}; /* 7px */ width: 100%; @@ -394,9 +403,8 @@ export function handlePopUp(context) { overflow: visible; } #root.open-pop-up { - /*will-change: transform;*/ + will-change: transform, backdrop-filter; transform: translateY(-120%); - transition: transform .36s !important; } #root.open-pop-up > * { /* Block child items to overflow and if they do clip them */ @@ -406,8 +414,8 @@ export function handlePopUp(context) { } #root.close-pop-up { transform: translateY(-20%); - transition: transform .4s !important; box-shadow: none; + backdrop-filter: none !important; } @media only screen and (min-width: 600px) { #root { @@ -426,6 +434,7 @@ export function handlePopUp(context) { position: inherit !important; width: 100% !important; padding: 18px !important; + backdrop-filter: none !important; } `; @@ -505,24 +514,22 @@ export function handlePopUp(context) { let initPopUp = setTimeout(() => { let element = context.getRootNode().querySelector('#root'); - if ( - element && - ( - !context.popUp - || stateChanged - || (editor && !context.editorModeAdded) - ) - ){ + if (element && ( + !context.popUp + || stateChanged + || (editor && !context.editorModeAdded) + )){ context.popUp = element; createPopUp(); const initEvent = new Event('popUpInitialized'); window.dispatchEvent(initEvent); - if (editor) { + if (editor && context.popUp && !context.editorModeAdded) { context.popUp.classList.add('editor'); + context.popUp.classList.remove('close-pop-up', 'open-pop-up'); context.editorModeAdded = true; } - } else if (!editor && context.popUp) { + } else if (!editor && context.popUp && context.editorModeAdded) { context.popUp.classList.remove('editor'); context.editorModeAdded = false; } @@ -530,44 +537,47 @@ export function handlePopUp(context) { // Pop-up triggers - if (context.popUp && triggerEntity && stateChanged) { - if (localStorage.getItem('previousTriggerState_' + popUpHash) === null) { - localStorage.setItem('previousTriggerState_' + popUpHash, ''); - } - if (localStorage.getItem('isManuallyClosed_' + popUpHash) === null) { - localStorage.setItem('isManuallyClosed_' + popUpHash, 'false'); - } - if (localStorage.getItem('isTriggered_' + popUpHash) === null) { - localStorage.setItem('isTriggered_' + popUpHash, 'false'); - } - - let previousTriggerState = localStorage.getItem('previousTriggerState_' + popUpHash); - let isManuallyClosed = localStorage.getItem('isManuallyClosed_' + popUpHash) === 'true'; - let isTriggered = localStorage.getItem('isTriggered_' + popUpHash) === 'true'; - - if (hass.states[triggerEntity].state === triggerState && previousTriggerState === null && !isTriggered) { - navigate('', popUpHash); - isTriggered = true; - localStorage.setItem('isTriggered_' + popUpHash, isTriggered); - } + let popUpTriggers = setTimeout(() => { + if (context.popUp && triggerEntity && stateChanged) { + if (localStorage.getItem('previousTriggerState_' + popUpHash) === null) { + localStorage.setItem('previousTriggerState_' + popUpHash, ''); + } + if (localStorage.getItem('isManuallyClosed_' + popUpHash) === null) { + localStorage.setItem('isManuallyClosed_' + popUpHash, 'false'); + } + if (localStorage.getItem('isTriggered_' + popUpHash) === null) { + localStorage.setItem('isTriggered_' + popUpHash, 'false'); + } + + let previousTriggerState = localStorage.getItem('previousTriggerState_' + popUpHash); + let isManuallyClosed = localStorage.getItem('isManuallyClosed_' + popUpHash) === 'true'; + let isTriggered = localStorage.getItem('isTriggered_' + popUpHash) === 'true'; + + if (hass.states[triggerEntity].state === triggerState && previousTriggerState === null && !isTriggered) { + navigate('', popUpHash); + isTriggered = true; + localStorage.setItem('isTriggered_' + popUpHash, isTriggered); + } - if (hass.states[triggerEntity].state !== previousTriggerState) { - isManuallyClosed = false; - localStorage.setItem('previousTriggerState_' + popUpHash, hass.states[triggerEntity].state); - localStorage.setItem('isManuallyClosed_' + popUpHash, isManuallyClosed); - } - - if (hass.states[triggerEntity].state === triggerState && !isManuallyClosed) { - navigate('', popUpHash); - isTriggered = true; - localStorage.setItem('isTriggered_' + popUpHash, isTriggered); - } else if (hass.states[triggerEntity].state !== triggerState && triggerClose && context.popUp.classList.contains('open-pop-up') && isTriggered && !isManuallyClosed) { - history.replaceState(null, null, location.href.split('#')[0]); - popUpOpen = popUpHash + false; - isTriggered = false; - isManuallyClosed = true; - localStorage.setItem('isManuallyClosed_' + popUpHash, isManuallyClosed); - localStorage.setItem('isTriggered_' + popUpHash, isTriggered); - } - } + if (hass.states[triggerEntity].state !== previousTriggerState) { + isManuallyClosed = false; + localStorage.setItem('previousTriggerState_' + popUpHash, hass.states[triggerEntity].state); + localStorage.setItem('isManuallyClosed_' + popUpHash, isManuallyClosed); + } + + if (hass.states[triggerEntity].state === triggerState && !isManuallyClosed) { + navigate('', popUpHash); + isTriggered = true; + localStorage.setItem('isTriggered_' + popUpHash, isTriggered); + } else if (hass.states[triggerEntity].state !== triggerState && triggerClose && context.popUp.classList.contains('open-pop-up') && isTriggered && !isManuallyClosed) { + history.replaceState(null, null, location.href.split('#')[0]); + fireEvent(window, "location-changed", true); + popUpOpen = popUpHash + false; + isTriggered = false; + isManuallyClosed = true; + localStorage.setItem('isManuallyClosed_' + popUpHash, isManuallyClosed); + localStorage.setItem('isTriggered_' + popUpHash, isTriggered); + } + } + }, 0); } \ No newline at end of file diff --git a/src/editor/bubble-card-editor.ts b/src/editor/bubble-card-editor.ts index 37186a23..9a2c4034 100644 --- a/src/editor/bubble-card-editor.ts +++ b/src/editor/bubble-card-editor.ts @@ -234,7 +234,7 @@ export default class BubbleCardEditor extends LitElement { Regular mode - This card allows you to convert any vertical stack into a pop-up. Each pop-up can be opened by targeting its link (e.g. '#pop-up-name'), with navigation_path or with the horizontal buttons stack that is included.
It must be placed within a vertical-stack card at the top most position to function properly. The pop-up will be hidden by default until you open it.

How to get the optimized mode?
+ This card allows you to convert any vertical stack into a pop-up. Each pop-up can be opened by targeting its link (e.g. '#pop-up-name'), with navigation_path or with the horizontal buttons stack that is included.
It must be placed within a vertical-stack card at the top most position to function properly. The pop-up will be hidden by default until you open it.

How to get the optimized mode?
+ Set ‘Background blur’ to 0 if your pop-up animations are rendering at low FPS. You can't set a value to 0 with the sliders for now, just change it to 0 in the text field if you need to. -

Advanced settings

- - -
- -
-
- Back button/event support : This allow you to navigate through your pop-ups history when you press the back button of your browser. This setting can be applied only once, you don't need to change it in all pop-ups. If it's not working just turn it on for each pop-ups. ${this.makeVersion()}
`; @@ -451,8 +439,8 @@ export default class BubbleCardEditor extends LitElement { `; } else if (this._config.card_type === 'horizontal-buttons-stack') { if (!this.buttonAdded && this.shadowRoot.querySelector("#add-button")) { + this.buttonAdded = true; const addButton = this.shadowRoot.querySelector("#add-button"); - this.buttonIndex = 0; while (this._config[(this.buttonIndex + 1) + '_link']) { @@ -474,8 +462,6 @@ export default class BubbleCardEditor extends LitElement { addButton.innerText = originalText; }, 5000); }, { passive: true }); - - this.buttonAdded = true; } return html` @@ -618,8 +604,11 @@ export default class BubbleCardEditor extends LitElement { ${this.makeDropdown("Card type", "card_type", cardTypeList)} You need to add a card type first. +

The Bubble Card ${version} changelog is available here. +


Almost everything is available in the GUI editor, but in the YAML editor you can add your own custom styles, create custom buttons or modify the tap actions of all cards. You can find more details on my GitHub page.

+

And if you like my project and want to support me, please consider making a donation. Any amount is welcome and very much appreciated! 🍻

@@ -815,37 +804,53 @@ export default class BubbleCardEditor extends LitElement { static get styles() { return css` - div { - display: grid; - grid-gap: 12px; - } - #add-button { - height: 32px; - border-radius: 16px; - border: none; - background-color: var(--accent-color); - } - .button-header { - height: auto; - width: 100%; - display: inline-flex; - align-items: center; - - } - .button-number { - display: inline-flex; - width: auto; - } - .remove-button { - display: inline-flex; - border-radius: 50%; - width: 24px; - height: 24px; - text-align: center; - line-height: 24px; - vertical-align: middle; - cursor: pointer; - } - `; + div { + display: grid; + grid-gap: 12px; + } + #add-button, #clear-cache { + margin-top: 12px; + width: 100%; + height: 32px; + border-radius: 16px; + border: none; + background-color: var(--accent-color); + cursor: pointer; + } + a { + color: var(--primary-text-color); + } + p { + margin-bottom: 4px; + } + hr { + display: inline-block; + width: 100%; + background-color: var(--text-primary-color); + opacity: .15; + margin: 8px 0 0 0; + } + .button-header { + height: auto; + width: 100%; + display: inline-flex; + align-items: center; + + } + .button-number { + display: inline-flex; + width: auto; + } + .remove-button { + display: inline-flex; + border-radius: 50%; + width: 24px; + height: 24px; + text-align: center; + line-height: 24px; + vertical-align: middle; + cursor: pointer; + } + `; } } \ No newline at end of file diff --git a/src/editor/bubble-pop-up-editor.ts b/src/editor/bubble-pop-up-editor.ts index c8d58945..4ae1aee8 100644 --- a/src/editor/bubble-pop-up-editor.ts +++ b/src/editor/bubble-pop-up-editor.ts @@ -115,66 +115,11 @@ let bubblePopUpEditor = new MutationObserver((mutationsList, observer) => { }); this.allEntitiesList = Object.keys(this.hass.states).map(formateList); - - this.lightList = Object.keys(this.hass.states).filter( - (eid) => eid.substr(0, eid.indexOf(".")) === "light" - ).map(formateList); - - this.sensorList = Object.keys(this.hass.states).filter( - (eid) => eid.substr(0, eid.indexOf(".")) === "sensor" - ).map(formateList); - - this.binarySensorList = Object.keys(this.hass.states).filter( - (eid) => eid.substr(0, eid.indexOf(".")) === "binary_sensor" - ).map(formateList); - - this.coverList = Object.keys(this.hass.states).filter( - (eid) => eid.substr(0, eid.indexOf(".")) === "cover" - ).map(formateList); - - this.cardTypeList = [{ - 'label': 'Button', - 'value': 'button' - }, - { - 'label': 'Cover', - 'value': 'cover' - }, - { - 'label': 'Empty column', - 'value': 'empty-column' - }, - { - 'label': 'Horizontal buttons stack', - 'value': 'horizontal-buttons-stack' - }, - { - 'label': 'Pop-up', - 'value': 'pop-up' - }, - { - 'label': 'Separator', - 'value': 'separator' - } - ]; - - this.buttonTypeList = [{ - 'label': 'Switch', - 'value': 'switch' - }, - { - 'label': 'Slider', - 'value': 'slider' - } - ]; - this.listsUpdated = true; } const allEntitiesList = this.allEntitiesList; const lightList = this.lightList; - const sensorList = this.sensorList; - const coverList = this.coverList; const cardTypeList = this.cardTypeList; const buttonTypeList = this.buttonTypeList; @@ -343,19 +288,6 @@ let bubblePopUpEditor = new MutationObserver((mutationsList, observer) => { >
You can't set a value to 0 with the sliders for now, just change it to 0 in the text field if you need to. -

Advanced settings

- - -
- -
-
- Back button/event support : This allow you to navigate through your pop-ups history when you press the back button of your browser. This setting can be applied only once, you don't need to change it in all pop-ups. If it's not working just turn it on for each pop-ups. ${this.makeVersion()} `; @@ -391,59 +323,6 @@ let bubblePopUpEditor = new MutationObserver((mutationsList, observer) => { `; } } - - makeButton() { - let buttons = []; - - for (let i = 1; i <= this.buttonIndex; i++) { - buttons.push(html` -
-
- this.removeButton(i)}> - Button ${i} -
- - - - - -
- `); - } - return buttons; - } makeVersion() { return html` @@ -468,38 +347,6 @@ let bubblePopUpEditor = new MutationObserver((mutationsList, observer) => { `; } - - removeButton(index) { - // Removing button fields - delete this._config[index + '_name']; - delete this._config[index + '_icon']; - delete this._config[index + '_link']; - delete this._config[index + '_entity']; - delete this._config[index + '_pir_sensor']; - - // Updating indexes of following buttons - for (let i = index; i < this.buttonIndex; i++) { - this._config[i + '_name'] = this._config[(i + 1) + '_name']; - this._config[i + '_icon'] = this._config[(i + 1) + '_icon']; - this._config[i + '_link'] = this._config[(i + 1) + '_link']; - this._config[i + '_entity'] = this._config[(i + 1) + '_entity']; - this._config[i + '_pir_sensor'] = this._config[(i + 1) + '_pir_sensor']; - } - - // Removing fields of the last button - delete this._config[this.buttonIndex + '_name']; - delete this._config[this.buttonIndex + '_icon']; - delete this._config[this.buttonIndex + '_link']; - delete this._config[this.buttonIndex + '_entity']; - delete this._config[this.buttonIndex + '_pir_sensor']; - - // Updating index of the last button - this.buttonIndex--; - - fireEvent(this, "config-changed", { - config: this._config - }); - } // Working for sliders (setting to 0) but add more issues, to be fixed // _valueChanged(ev) { @@ -549,33 +396,6 @@ let bubblePopUpEditor = new MutationObserver((mutationsList, observer) => { display: grid; grid-gap: 12px; } - #add-button { - height: 32px; - border-radius: 16px; - border: none; - background-color: var(--accent-color); - } - .button-header { - height: auto; - width: 100%; - display: inline-flex; - align-items: center; - - } - .button-number { - display: inline-flex; - width: auto; - } - .remove-button { - display: inline-flex; - border-radius: 50%; - width: 24px; - height: 24px; - text-align: center; - line-height: 24px; - vertical-align: middle; - cursor: pointer; - } `; } } diff --git a/src/tools/init.ts b/src/tools/init.ts index b3cab78d..56972f36 100644 --- a/src/tools/init.ts +++ b/src/tools/init.ts @@ -1,12 +1,14 @@ +import { version } from '../var/version.ts'; + // Initialize the content if it's not there yet. -export function initializeContent(context) { // Ajout du mot-clé async +export function initializeContent(context) { if (!context.content) { context.attachShadow({ mode: 'open' }); context.shadowRoot.innerHTML = ` - +
@@ -18,39 +20,45 @@ export function initializeContent(context) { // Ajout du mot-clé async // Check for edit mode -// export async function checkEditor(editor) { -// if (!window.editorElement) { -// const editorElementPromise = new Promise((resolve) => { -// resolve(document.querySelector("body > home-assistant") -// .shadowRoot.querySelector("home-assistant-main") -// .shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace") -// .shadowRoot.querySelector("hui-root") -// .shadowRoot.querySelector("div")); -// }); +function selectElement() { + try { + return document.querySelector("body > home-assistant") + .shadowRoot.querySelector("home-assistant-main") + .shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace") + .shadowRoot.querySelector("hui-root") + .shadowRoot.querySelector("div"); + } catch (error) { + return undefined; + } +} -// window.editorElement = await editorElementPromise; -// } else { -// editor = window.editorElement.classList.contains('edit-mode'); -// } -// return editor; -// } +const editorElement = selectElement(); export function checkEditor() { - const editorElement = - document.querySelector("body > home-assistant") - .shadowRoot.querySelector("home-assistant-main") - .shadowRoot.querySelector("ha-drawer > partial-panel-resolver > ha-panel-lovelace") - .shadowRoot.querySelector("hui-root") - .shadowRoot.querySelector("div"); - + if (!editorElement) { + return; + } return editorElement.classList.contains('edit-mode'); } -// Check if bubble-pop-up.js is installed as a resource and remove it (fix for the previous 1.5.0/1 users) - export async function checkResources(hass) { if (!window.resourcesChecked) { + window.resourcesChecked = true; + + // Check if bubble-pop-up.js is installed as a module and reload the cache after every updates + + let currentVersion = version; + const storedVersion = localStorage.getItem('version'); + const component = customElements.get("bubble-pop-up"); + + if (storedVersion !== currentVersion) { + localStorage.setItem('version', currentVersion); + location.reload(); + } + + // Check if bubble-pop-up.js is installed as a resource and remove it (fix for the previous 1.5.0/1 users) + let resources = await hass.callWS({ type: "lovelace/resources" }); let resource = resources.find(r => r.url.includes("bubble-pop-up.js")); if (resource) { @@ -61,4 +69,3 @@ export async function checkResources(hass) { } } } - diff --git a/src/tools/style.ts b/src/tools/style.ts index 764d3213..8ea21133 100644 --- a/src/tools/style.ts +++ b/src/tools/style.ts @@ -1,12 +1,13 @@ export const addStyles = function(hass, context, styles, customStyles, state, entityId, stateChanged, path = '', element = context.content) { + // Evaluate customStyles if it exists, else assign an empty string const customStylesEval = customStyles ? eval('`' + customStyles + '`') : ''; - let styleAddedKey = styles + 'Added'; // Add 'Added' at the end of the styles value + let styleAddedKey = styles + 'Added'; // Append 'Added' to the styles value // Check if the style has changed if (!context[styleAddedKey] || context.previousStyle !== customStylesEval || stateChanged || context.previousConfig !== context.config) { if (!context[styleAddedKey]) { // Check if the style element already exists - context.styleElement = element.querySelector('style'); //context.content + context.styleElement = element.querySelector('style'); if (!context.styleElement) { // If not, create a new style element context.styleElement = document.createElement('style'); diff --git a/src/tools/tap-actions.ts b/src/tools/tap-actions.ts index 2a09bf3f..a57a71af 100644 --- a/src/tools/tap-actions.ts +++ b/src/tools/tap-actions.ts @@ -1,4 +1,3 @@ -// Définir une fonction qui crée et envoie un événement hass-action avec la configuration et l'action à effectuer export function sendActionEvent(element, config, action) { const actionConfig = { entity: config.entity, @@ -13,7 +12,6 @@ export function sendActionEvent(element, config, action) { } }; - // Créer un événement de type hass-action avec les détails de la configuration et de l'action const event = new Event('hass-action', { bubbles: true, composed: true, @@ -22,110 +20,80 @@ export function sendActionEvent(element, config, action) { config: actionConfig, action: action, }; - // Envoyer l'événement au gestionnaire d'événements de Home Assistant avec la méthode dispatchEvent element.dispatchEvent(event); } -// Définir une fonction qui ajoute des actions à un élément en fonction de la configuration export function addActions(element, config, hass, forwardHaptic) { - // Extraire les actions possibles de la configuration let tap_action = config.tap_action; let double_tap_action = config.double_tap_action; let hold_action = config.hold_action; - - // Définir des variables pour compter le nombre de clics et le temps écoulé entre les clics + let userGesture = false; + let lastTap = 0; let clickCount = 0; let startTime = 0; let endTime = 0; - - // Définir une variable pour le timeout de l'action de maintien + let tapTimeout; let holdTimeout; - // Ajouter un écouteur d'événement pour le clic sur l'élément element.addEventListener('mousedown', () => { - // Enregistrer le temps de départ au moment du clic startTime = Date.now(); - // Définir un timeout pour déclencher l'action de maintien après 300 ms holdTimeout = setTimeout(() => { - // Envoyer l'événement de type hold sendActionEvent(element, config, 'hold'); }, 300); }, { passive: true }); element.addEventListener('mouseup', () => { - // Annuler le timeout de l'action de maintien clearTimeout(holdTimeout); - // Enregistrer le temps de fin au moment où le bouton de la souris est relâché endTime = Date.now(); - // Si le temps écoulé entre le clic et le relâchement du bouton de la souris est inférieur à 300 ms, considérer comme un clic simple ou double if (endTime - startTime < 300) { clickCount++; if (clickCount === 1) { setTimeout(() => { if (clickCount === 1) { - // Envoyer l'événement de type tap sendActionEvent(element, config, 'tap'); } else { - // Envoyer l'événement de type double_tap sendActionEvent(element, config, 'double_tap'); forwardHaptic("success"); } - // Réinitialiser le compteur de clics clickCount = 0; }, 300); } } - // Réinitialiser les temps de départ et de fin startTime = 0; endTime = 0; }, { passive: true }); - // Ajouter un écouteur d'événement pour le toucher sur l'élément element.addEventListener('touchstart', (e) => { - forwardHaptic("light"); - // Enregistrer le temps de départ au moment du toucher + userGesture = true; + if (userGesture) { + forwardHaptic("light"); + } startTime = Date.now(); - // Définir un timeout pour déclencher l'action de maintien après 300 ms holdTimeout = setTimeout(() => { - // Envoyer l'événement de type hold sendActionEvent(element, config, 'hold'); }, 300); - // Empêcher le comportement par défaut pour éviter un double événement - e.preventDefault(); + if (e.type !== 'touchstart') { + e.preventDefault(); + } }, { passive: true }); - element.addEventListener('touchend', (e) => { - // Annuler le timeout de l'action de maintien - clearTimeout(holdTimeout); - // Enregistrer le temps de fin au moment où le toucher est relâché - endTime = Date.now(); - - // Si le temps écoulé entre le toucher et le relâchement du toucher est inférieur à 300 ms, considérer comme un toucher simple ou double - if (endTime - startTime < 300) { - clickCount++; - if (clickCount === 1) { - setTimeout(() => { - if (clickCount === 1) { - // Envoyer l'événement de type tap - sendActionEvent(element, config, 'tap'); - } else { - // Envoyer l'événement de type double_tap - sendActionEvent(element, config, 'double_tap'); - } - // Réinitialiser le compteur de clics - clickCount = 0; - }, 300); + element.addEventListener('touchend', function(e) { + let currentTime = new Date().getTime(); + let tapLength = currentTime - lastTap; + clearTimeout(holdTimeout); + + if (tapLength < 500 && tapLength > 0) { + clearTimeout(tapTimeout); + sendActionEvent(element, config, 'double_tap'); + } else { + tapTimeout = setTimeout(function() { + sendActionEvent(element, config, 'tap'); + }, 300); } - } - // Réinitialiser les temps de départ et de fin - startTime = 0; - endTime = 0; - // Empêcher le comportement par défaut pour éviter un double événement - e.preventDefault(); + lastTap = currentTime; }, { passive: true }); - // Ajouter des écouteurs d'événements pour annuler l'action de maintien si l'utilisateur arrête de toucher ou de cliquer sur l'élément element.addEventListener('mouseout', () => { clearTimeout(holdTimeout); }, { passive: true }); diff --git a/src/tools/url-listener.ts b/src/tools/url-listener.ts index 75e3438c..175764b0 100644 --- a/src/tools/url-listener.ts +++ b/src/tools/url-listener.ts @@ -6,7 +6,7 @@ export function addUrlListener() { const event = new Event('urlChanged'); window.popUpInitialized = false; - ['click', 'mousedown', 'touchstart', 'focus', 'location-changed', 'connection-status'].forEach((eventType) => { + ['location-changed', 'connection-status'].forEach((eventType) => { window.addEventListener(eventType, urlChanged); }, { passive: true }); diff --git a/src/var/cards.ts b/src/var/cards.ts index 9e7fc919..9429dabb 100644 --- a/src/var/cards.ts +++ b/src/var/cards.ts @@ -18,12 +18,12 @@ export function getVariables(context, config, hass, editor) { let entityId = config.entity && hass.states[config.entity] ? config.entity : ''; - let icon = !config.icon && config.entity + let icon = !config.icon && entityId ? hass.states[entityId].attributes.icon || hass.states[entityId].attributes.entity_picture || '' : config.icon || ''; let name = config.name ? config.name - : config.entity + : entityId ? hass.states[entityId].attributes.friendly_name : ''; let widthDesktop = config.width_desktop || '540px'; diff --git a/src/var/version.ts b/src/var/version.ts index 0d5c91da..13d1f5e4 100644 --- a/src/var/version.ts +++ b/src/var/version.ts @@ -1 +1 @@ -export var version = 'v1.6.0-beta.2'; \ No newline at end of file +export var version = 'v1.6.0-beta.3'; \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 3ba57e4d..e6c956e0 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -24,5 +24,4 @@ module.exports = [ filename: '[name].js', }, } -]; - +]; \ No newline at end of file