/** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const t$2=window,e$2=t$2.ShadowRoot&&(void 0===t$2.ShadyCSS||t$2.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$3=Symbol(),n$3=new WeakMap;class o$3{constructor(t,e,n){if(this._$cssResult$=!0,n!==s$3)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$2&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=n$3.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&n$3.set(s,t));}return t}toString(){return this.cssText}}const r$3=t=>new o$3("string"==typeof t?t:t+"",void 0,s$3),i$1=(t,...e)=>{const n=1===t.length?t[0]:e.reduce(((e,s,n)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(s)+t[n+1]),t[0]);return new o$3(n,t,s$3)},S$1=(s,n)=>{e$2?s.adoptedStyleSheets=n.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):n.forEach((e=>{const n=document.createElement("style"),o=t$2.litNonce;void 0!==o&&n.setAttribute("nonce",o),n.textContent=e.cssText,s.appendChild(n);}));},c$1=e$2?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$3(e)})(t):t; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */var s$2;const e$1=window,r$2=e$1.trustedTypes,h$1=r$2?r$2.emptyScript:"",o$2=e$1.reactiveElementPolyfillSupport,n$2={toAttribute(t,i){switch(i){case Boolean:t=t?h$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,i){let s=t;switch(i){case Boolean:s=null!==t;break;case Number:s=null===t?null:Number(t);break;case Object:case Array:try{s=JSON.parse(t);}catch(t){s=null;}}return s}},a$1=(t,i)=>i!==t&&(i==i||t==t),l$2={attribute:!0,type:String,converter:n$2,reflect:!1,hasChanged:a$1};class d$1 extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this.u();}static addInitializer(t){var i;null!==(i=this.h)&&void 0!==i||(this.h=[]),this.h.push(t);}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((i,s)=>{const e=this._$Ep(s,i);void 0!==e&&(this._$Ev.set(e,s),t.push(e));})),t}static createProperty(t,i=l$2){if(i.state&&(i.attribute=!1),this.finalize(),this.elementProperties.set(t,i),!i.noAccessor&&!this.prototype.hasOwnProperty(t)){const s="symbol"==typeof t?Symbol():"__"+t,e=this.getPropertyDescriptor(t,s,i);void 0!==e&&Object.defineProperty(this.prototype,t,e);}}static getPropertyDescriptor(t,i,s){return {get(){return this[i]},set(e){const r=this[t];this[i]=e,this.requestUpdate(t,r,s);},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||l$2}static finalize(){if(this.hasOwnProperty("finalized"))return !1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,i=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const s of i)this.createProperty(s,t[s]);}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(i){const s=[];if(Array.isArray(i)){const e=new Set(i.flat(1/0).reverse());for(const i of e)s.unshift(c$1(i));}else void 0!==i&&s.push(c$1(i));return s}static _$Ep(t,i){const s=i.attribute;return !1===s?void 0:"string"==typeof s?s:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)));}addController(t){var i,s;(null!==(i=this._$ES)&&void 0!==i?i:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(s=t.hostConnected)||void 0===s||s.call(t));}removeController(t){var i;null===(i=this._$ES)||void 0===i||i.splice(this._$ES.indexOf(t)>>>0,1);}_$Eg(){this.constructor.elementProperties.forEach(((t,i)=>{this.hasOwnProperty(i)&&(this._$Ei.set(i,this[i]),delete this[i]);}));}createRenderRoot(){var t;const s=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return S$1(s,this.constructor.elementStyles),s}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostConnected)||void 0===i?void 0:i.call(t)}));}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostDisconnected)||void 0===i?void 0:i.call(t)}));}attributeChangedCallback(t,i,s){this._$AK(t,s);}_$EO(t,i,s=l$2){var e;const r=this.constructor._$Ep(t,s);if(void 0!==r&&!0===s.reflect){const h=(void 0!==(null===(e=s.converter)||void 0===e?void 0:e.toAttribute)?s.converter:n$2).toAttribute(i,s.type);this._$El=t,null==h?this.removeAttribute(r):this.setAttribute(r,h),this._$El=null;}}_$AK(t,i){var s;const e=this.constructor,r=e._$Ev.get(t);if(void 0!==r&&this._$El!==r){const t=e.getPropertyOptions(r),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(s=t.converter)||void 0===s?void 0:s.fromAttribute)?t.converter:n$2;this._$El=r,this[r]=h.fromAttribute(i,t.type),this._$El=null;}}requestUpdate(t,i,s){let e=!0;void 0!==t&&(((s=s||this.constructor.getPropertyOptions(t)).hasChanged||a$1)(this[t],i)?(this._$AL.has(t)||this._$AL.set(t,i),!0===s.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,s))):e=!1),!this.isUpdatePending&&e&&(this._$E_=this._$Ej());}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach(((t,i)=>this[i]=t)),this._$Ei=void 0);let i=!1;const s=this._$AL;try{i=this.shouldUpdate(s),i?(this.willUpdate(s),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostUpdate)||void 0===i?void 0:i.call(t)})),this.update(s)):this._$Ek();}catch(t){throw i=!1,this._$Ek(),t}i&&this._$AE(s);}willUpdate(t){}_$AE(t){var i;null===(i=this._$ES)||void 0===i||i.forEach((t=>{var i;return null===(i=t.hostUpdated)||void 0===i?void 0:i.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t);}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return !0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,i)=>this._$EO(i,this[i],t))),this._$EC=void 0),this._$Ek();}updated(t){}firstUpdated(t){}}d$1.finalized=!0,d$1.elementProperties=new Map,d$1.elementStyles=[],d$1.shadowRootOptions={mode:"open"},null==o$2||o$2({ReactiveElement:d$1}),(null!==(s$2=e$1.reactiveElementVersions)&&void 0!==s$2?s$2:e$1.reactiveElementVersions=[]).push("1.4.1"); /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ var t$1;const i=window,s$1=i.trustedTypes,e=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,o$1=`lit$${(Math.random()+"").slice(9)}$`,n$1="?"+o$1,l$1=`<${n$1}>`,h=document,r$1=(t="")=>h.createComment(t),d=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,c=t=>u(t)||"function"==typeof(null==t?void 0:t[Symbol.iterator]),v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,a=/-->/g,f=/>/g,_=RegExp(">|[ \t\n\f\r](?:([^\\s\"'>=/]+)([ \t\n\f\r]*=[ \t\n\f\r]*(?:[^ \t\n\f\r\"'`<>=]|(\"|')|))|$)","g"),m=/'/g,p=/"/g,$=/^(?:script|style|textarea|title)$/i,g=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),y=g(1),x=Symbol.for("lit-noChange"),b=Symbol.for("lit-nothing"),T=new WeakMap,A=(t,i,s)=>{var e,o;const n=null!==(e=null==s?void 0:s.renderBefore)&&void 0!==e?e:i;let l=n._$litPart$;if(void 0===l){const t=null!==(o=null==s?void 0:s.renderBefore)&&void 0!==o?o:null;n._$litPart$=l=new S(i.insertBefore(r$1(),t),t,void 0,null!=s?s:{});}return l._$AI(t),l},E$1=h.createTreeWalker(h,129,null,!1),C=(t,i)=>{const s=t.length-1,n=[];let h,r=2===i?"":"",d=v;for(let i=0;i"===u[0]?(d=null!=h?h:v,c=-1):void 0===u[1]?c=-2:(c=d.lastIndex-u[2].length,e=u[1],d=void 0===u[3]?_:'"'===u[3]?p:m):d===p||d===m?d=_:d===a||d===f?d=v:(d=_,h=void 0);const y=d===_&&t[i+1].startsWith("/>")?" ":"";r+=d===v?s+l$1:c>=0?(n.push(e),s.slice(0,c)+"$lit$"+s.slice(c)+o$1+y):s+o$1+(-2===c?(n.push(void 0),i):y);}const u=r+(t[s]||"")+(2===i?"":"");if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return [void 0!==e?e.createHTML(u):u,n]};class P{constructor({strings:t,_$litType$:i},e){let l;this.parts=[];let h=0,d=0;const u=t.length-1,c=this.parts,[v,a]=C(t,i);if(this.el=P.createElement(v,e),E$1.currentNode=this.el.content,2===i){const t=this.el.content,i=t.firstChild;i.remove(),t.append(...i.childNodes);}for(;null!==(l=E$1.nextNode())&&c.length0){l.textContent=s$1?s$1.emptyScript:"";for(let s=0;s2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=b;}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,i=this,s,e){const o=this.strings;let n=!1;if(void 0===o)t=V(this,t,i,0),n=!d(t)||t!==this._$AH&&t!==x,n&&(this._$AH=t);else {const e=t;let l,h;for(t=o[0],l=0;l { if(!array) return; return attribute in array ? array[attribute] : defaultValue; }; if (!config.entity) { throw new Error('You need to define an entity'); } this._config = config; this.config = { type: config.type, entity: config.entity, name: getConfigAttribute("name", false), invert_position: getConfigAttribute("invert_position", false), invert_position_label: getConfigAttribute("invert_position_label", false) || getConfigAttribute("invert_position", false), state_confidence: getConfigAttribute("state_confidence", true), state_color: getConfigAttribute("state_color", false), move_down_button: { tap_action: getConfigAttribute("tap_action", false, getConfigAttribute("move_down_button", false)), double_tap_action: getConfigAttribute("double_tap_action", false, getConfigAttribute("move_down_button", false)), hold_action: getConfigAttribute("hold_action", false, getConfigAttribute("move_down_button", false)), }, move_stop_button: { tap_action: getConfigAttribute("tap_action", false, getConfigAttribute("move_stop_button", false)), double_tap_action: getConfigAttribute("double_tap_action", false, getConfigAttribute("move_stop_button", false)), hold_action: getConfigAttribute("hold_action", false, getConfigAttribute("move_stop_button", false)), }, move_up_button: { tap_action: getConfigAttribute("tap_action", false, getConfigAttribute("move_up_button", false)), double_tap_action: getConfigAttribute("double_tap_action", false, getConfigAttribute("move_up_button", false)), hold_action: getConfigAttribute("hold_action", false, getConfigAttribute("move_up_button", false)), }, preset_buttons: getConfigAttribute("preset_buttons", false), }; this.entityId = this.config.entity; } // Calls custom action if defined callCustomAction(config, action) { // Check if defined if(!config[action]) return; // Run custom action switch(action) { case "tap_action": be(this, this.hass, config, false, false); break; case "double_tap_action": be(this, this.hass, config, false, true); break; case "hold_action": be(this, this.hass, config, true, false); break; } } /* Card functions */ // Returns CSS style static get styles() { return css_248z; } // Get entity name getName() { if(this.config.name) return this.config.name; return this.state.attributes.friendly_name; } // Get position value getPosition() { if(this.config.invert_position) return (100 - this.state.attributes.current_position); return this.state.attributes.current_position; } // Get position text for label getPositionLabel() { if( (this.config.invert_position_label && this.getPosition() == 100) || (!this.config.invert_position_label && this.getPosition() == 0) ) return this.hass.localize("component.cover.state._.closed"); if( (this.config.invert_position_label && this.getPosition() == 0) || (!this.config.invert_position_label && this.getPosition() == 100) ) return this.hass.localize("component.cover.state._.open"); return `${this.getPosition()} %`; } // Sets meta for variables setMeta(force=false) { // Only on change if(this.state == this.hass.states[this.entityId] && !force) return; this.state = this.hass.states[this.entityId]; this.stateDisplay = this.state ? this.state.state : 'unavailable'; } // Checks if cover is fully opened upReached() { if(!this.config.invert_position_label && this.getPosition() == 100 || this.config.invert_position_label && this.getPosition() == 0) return true; return false; } // Checks if cover is fully closed downReached() { if(this.config.invert_position_label && this.getPosition() == 100 || !this.config.invert_position_label && this.getPosition() == 0) return true; return false; } // Render entity icon renderIcon() { let icon = ""; // Check for entity defined icon if(this.state.attributes.icon != undefined) icon = this.state.attributes.icon; else { // Use dynamic icon if(this.downReached()) icon = "lsr:shutter-4"; else if(this.upReached()) icon = "lsr:shutter-0"; else if(this.stateDisplay == "opening") icon = "lsr:shutter-opening"; else if(this.stateDisplay == "closing") icon = "lsr:shutter-closing"; else { if (this.getPosition() <= 25) icon = (this.config.invert_position_label) ? "lsr:shutter-1" : "lsr:shutter-3"; else if (this.getPosition() <= 50 ) icon = "lsr:shutter-2"; else if (this.getPosition() <= 75 ) icon = (this.config.invert_position_label) ? "lsr:shutter-3" : "lsr:shutter-1" else icon = "lsr:shutter-4" } } return y``; } renderFirstRow() { return y`
${this.renderIcon()}
${this.getName()}
`; } renderSecondRow() { return y`
${this.getPositionLabel()}
`; } renderPresetsRow() { if(!this.config.preset_buttons) return; let presetsHtml = []; this.config.preset_buttons.forEach(presetConfig => { presetsHtml.push(this.renderPreset(presetConfig)); }); return y`
${presetsHtml}
`; } renderPreset(presetConfig) { // Ripple effect let ripple = getRippleElement(); // Events let onPointerDownFunc = () => { ripple.startPress(); onHoldPointerDown(); }; let onPointerUpFunc = () => { ripple.endPress(); let onClickCallback = () => { this.callCustomAction(presetConfig, "tap_action"); }; let onHoldCallback = () => { this.callCustomAction(presetConfig, "hold_action"); }; onPointerUp(this, onClickCallback, onHoldCallback); }; let onDoubleClick = () => { this.callCustomAction(presetConfig, "double_tap_action"); }; return y`
${presetConfig.name} ${ripple}
`; } // Render lovelace card render() { this.setMeta(); return y` ${this.renderFirstRow()} ${this.renderSecondRow()} ${this.renderPresetsRow()} `; } /* DOM element handler */ // Get all important DOM elements _getElements() { return { controls: this.renderRoot.querySelector("div.card-row.first-row div.controls"), slider: this.renderRoot.querySelector("div.card-row.second-row ha-slider"), } } // On move up pointer up onMoveUpPointerUp() { let onClickCallback = (e) => { if(this.config.move_up_button && this.config.move_up_button.tap_action) { this.callCustomAction(this.config.move_up_button, "tap_action"); return; } // Run default action if(this.config.state_confidence) if(this.upReached()) return; this.hass.callService("cover", "open_cover", { entity_id: this.entityId, }); }; let onHoldCallback = (e) => { this.callCustomAction(this.config.move_up_button, "hold_action"); }; onPointerUp(this, onClickCallback, onHoldCallback); } // On move up double click onMoveUpDoubleClick() { this.callCustomAction(this.config.move_up_button, "double_tap_action"); } // On move stop pointer up onMoveStopPointerUp() { let onClickCallback = (e) => { if(this.config.move_stop_button && this.config.move_stop_button.tap_action) { this.callCustomAction(this.config.move_stop_button, "tap_action"); return; } // Run default action if(this.config.state_confidence) if(this.stateDisplay == "open" || this.stateDisplay == "closed") return; this.hass.callService("cover", "stop_cover", { entity_id: this.entityId, }); }; let onHoldCallback = (e) => { this.callCustomAction(this.config.move_stop_button, "hold_action"); }; onPointerUp(this, onClickCallback, onHoldCallback); } // On move down double click onMoveStopDoubleClick() { this.callCustomAction(this.config.move_stop_button, "double_tap_action"); } // On move down pointer up onMoveDownPointerUp() { let onClickCallback = (e) => { if(this.config.move_down_button && this.config.move_down_button.tap_action) { this.callCustomAction(this.config.move_down_button, "tap_action"); return; } // Run default action if(this.config.state_confidence) if(this.downReached()) return; this.hass.callService("cover", "close_cover", { entity_id: this.entityId, }); }; let onHoldCallback = (e) => { this.callCustomAction(this.config.move_down_button, "hold_action"); }; onPointerUp(this, onClickCallback, onHoldCallback); } // On move down double click onMoveDownDoubleClick() { this.callCustomAction(this.config.move_down_button, "double_tap_action"); } // On position input change onSliderChange() { let elements = this._getElements(); let value = parseInt(elements.slider.value); if(value == this.getPosition()) return; this.hass.callService("cover", "set_cover_position", { entity_id: this.entityId, position: this.config.invert_position ? (100 - value) : value, }); } // Open HA more info moreInfo() { let entityId = this.config.entity; ne(this, 'hass-more-info', { entityId, }, { bubbles: false, composed: true, }); } } customElements.define(HASSIO_CARD_ID, ShutterRow); console.info("%c" + HASSIO_CARD_NAME.toLocaleUpperCase() + " " + VERSION, "color: #ffa500");