From 25ec0354373899e4d88b598b9c17da26a2ec2e6e Mon Sep 17 00:00:00 2001 From: EpicLPer Date: Sat, 27 Jun 2026 23:12:36 +0200 Subject: [PATCH] feat: add visual blueprint editor for custom blueprints Introduce a self-contained blueprint editor view with live SVG preview, button placement, and save support for user-owned blueprints. --- custom_components/switch_manager/__init__.py | 2 + .../assets/switch_manager_panel.js | 671 ++++++++- .../switch_manager/connections.py | 60 +- custom_components/switch_manager/helpers.py | 68 +- custom_components/switch_manager/models.py | 3 +- custom_components/switch_manager/schema.py | 7 + custom_components/switch_manager/view.py | 6 +- frontend/src/dialogs/blueprint-selector.ts | 53 +- .../src/switch-manager-blueprint-editor.ts | 1303 +++++++++++++++++ frontend/src/switch-manager-panel.ts | 19 + frontend/src/types.ts | 1 + 11 files changed, 2124 insertions(+), 69 deletions(-) create mode 100644 frontend/src/switch-manager-blueprint-editor.ts diff --git a/custom_components/switch_manager/__init__.py b/custom_components/switch_manager/__init__.py index 374e8ed..6961381 100644 --- a/custom_components/switch_manager/__init__.py +++ b/custom_components/switch_manager/__init__.py @@ -12,6 +12,7 @@ from .store import SwitchManagerStore from .helpers import load_blueprints, VERSION, deploy_blueprints, check_blueprints_folder_exists, _get_blueprint, _get_switch_config, _set_switch_config from .view import async_setup_view, async_bind_blueprint_images +from homeassistant.components.frontend import async_remove_panel from . import models from .schema import BLUEPRINT_MQTT_SCHEMA, BLUEPRINT_EVENT_SCHEMA, SERVICE_SET_VARIABLES_SCHEMA from .connections import async_setup_connections @@ -77,6 +78,7 @@ async def async_unload_entry( hass: HomeAssistant, config_entry ): """Unload a config entry.""" for switch_id in hass.data[DOMAIN].get(CONF_MANAGED_SWITCHES, {}): hass.data[DOMAIN][CONF_MANAGED_SWITCHES][switch_id].unload() + async_remove_panel(hass, "switch_manager", warn_if_unknown=False) return True async def async_migrate( hass, in_dev ): diff --git a/custom_components/switch_manager/assets/switch_manager_panel.js b/custom_components/switch_manager/assets/switch_manager_panel.js index d02e33d..7ea085b 100644 --- a/custom_components/switch_manager/assets/switch_manager_panel.js +++ b/custom_components/switch_manager/assets/switch_manager_panel.js @@ -1,4 +1,4 @@ -function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,i,s);else for(var n=t.length-1;n>=0;n--)(o=t[n])&&(a=(r<3?o(a):r>3?o(e,i,a):o(e,i))||a);return r>3&&a&&Object.defineProperty(e,i,a),a}"function"==typeof SuppressedError&&SuppressedError;const e=globalThis,i=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s=Symbol(),o=new WeakMap;let r=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==s)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(i&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=o.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&o.set(e,t))}return t}toString(){return this.cssText}};const a=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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.")})(i)+t[s+1],t[0]);return new r(i,t,s)},n=i?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new r("string"==typeof t?t:t+"",void 0,s))(e)})(t):t,{is:c,defineProperty:l,getOwnPropertyDescriptor:h,getOwnPropertyNames:d,getOwnPropertySymbols:p,getPrototypeOf:u}=Object,g=globalThis,m=g.trustedTypes,v=m?m.emptyScript:"",_=g.reactiveElementPolyfillSupport,b=(t,e)=>t,f={toAttribute(t,e){switch(e){case Boolean:t=t?v:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!c(t,e),w={attribute:!0,type:String,converter:f,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),g.litPropertyMetadata??=new WeakMap;let x=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=w){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&l(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:o}=h(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const r=s?.call(this);o?.call(this,e),this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??w}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=u(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...d(t),...p(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(n(t))}else void 0!==t&&e.push(n(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((t,s)=>{if(i)t.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const i of s){const s=document.createElement("style"),o=e.litNonce;void 0!==o&&s.setAttribute("nonce",o),s.textContent=i.cssText,t.appendChild(s)}})(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const o=(void 0!==i.converter?.toAttribute?i.converter:f).toAttribute(e,i.type);this._$Em=t,null==o?this.removeAttribute(s):this.setAttribute(s,o),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),o="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:f;this._$Em=s;const r=o.fromAttribute(e,t.type);this[s]=r??this._$Ej?.get(s)??r,this._$Em=null}}requestUpdate(t,e,i,s=!1,o){if(void 0!==t){const r=this.constructor;if(!1===s&&(o=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??y)(o,e)||i.useDefault&&i.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:o},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),!0!==o||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};x.elementStyles=[],x.shadowRootOptions={mode:"open"},x[b("elementProperties")]=new Map,x[b("finalized")]=new Map,_?.({ReactiveElement:x}),(g.reactiveElementVersions??=[]).push("2.1.2");const $=globalThis,A=t=>t,C=$.trustedTypes,S=C?C.createPolicy("lit-html",{createHTML:t=>t}):void 0,k="$lit$",H=`lit$${Math.random().toFixed(9).slice(2)}$`,V="?"+H,E=`<${V}>`,L=document,M=()=>L.createComment(""),D=t=>null===t||"object"!=typeof t&&"function"!=typeof t,P=Array.isArray,T="[ \t\n\f\r]",O=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,N=/-->/g,U=/>/g,q=RegExp(`>|${T}(?:([^\\s"'>=/]+)(${T}*=${T}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),z=/'/g,R=/"/g,j=/^(?:script|style|textarea|title)$/i,I=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),B=Symbol.for("lit-noChange"),Z=Symbol.for("lit-nothing"),W=new WeakMap,F=L.createTreeWalker(L,129);function J(t,e){if(!P(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==S?S.createHTML(e):e}const K=(t,e)=>{const i=t.length-1,s=[];let o,r=2===e?"":3===e?"":"",a=O;for(let e=0;e"===c[0]?(a=o??O,l=-1):void 0===c[1]?l=-2:(l=a.lastIndex-c[2].length,n=c[1],a=void 0===c[3]?q:'"'===c[3]?R:z):a===R||a===z?a=q:a===N||a===U?a=O:(a=q,o=void 0);const d=a===q&&t[e+1].startsWith("/>")?" ":"";r+=a===O?i+E:l>=0?(s.push(n),i.slice(0,l)+k+i.slice(l)+H+d):i+H+(-2===l?e:d)}return[J(t,r+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class G{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let o=0,r=0;const a=t.length-1,n=this.parts,[c,l]=K(t,e);if(this.el=G.createElement(c,i),F.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=F.nextNode())&&n.length0){s.textContent=C?C.emptyScript:"";for(let i=0;iP(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==Z&&D(this._$AH)?this._$AA.nextSibling.data=t:this.T(L.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=G.createElement(J(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Q(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=W.get(t.strings);return void 0===e&&W.set(t.strings,e=new G(t)),e}k(t){P(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const o of t)s===e.length?e.push(i=new X(this.O(M()),this.O(M()),this,this.options)):i=e[s],i._$AI(o),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=Z}_$AI(t,e=this,i,s){const o=this.strings;let r=!1;if(void 0===o)t=Y(this,t,e,0),r=!D(t)||t!==this._$AH&&t!==B,r&&(this._$AH=t);else{const s=t;let a,n;for(t=o[0],a=0;a{const s=i?.renderBefore??e;let o=s._$litPart$;if(void 0===o){const t=i?.renderBefore??null;s._$litPart$=o=new X(e.insertBefore(M(),t),t,void 0,i??{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return B}};nt._$litElement$=!0,nt.finalized=!0,at.litElementHydrateSupport?.({LitElement:nt});const ct=at.litElementPolyfillSupport;ct?.({LitElement:nt}),(at.litElementVersions??=[]).push("4.2.2");const lt=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)}):customElements.define(t,e)},ht={attribute:!0,type:String,converter:f,reflect:!1,hasChanged:y},dt=(t=ht,e,i)=>{const{kind:s,metadata:o}=i;let r=globalThis.litPropertyMetadata.get(o);if(void 0===r&&globalThis.litPropertyMetadata.set(o,r=new Map),"setter"===s&&((t=Object.create(t)).wrapped=!0),r.set(i.name,t),"accessor"===s){const{name:s}=i;return{set(i){const o=e.get.call(this);e.set.call(this,i),this.requestUpdate(s,o,t,!0,i)},init(e){return void 0!==e&&this.C(s,void 0,t,e),e}}}if("setter"===s){const{name:s}=i;return function(i){const o=this[s];e.call(this,i),this.requestUpdate(s,o,t,!0,i)}}throw Error("Unsupported decorator location: "+s)};function pt(t){return(e,i)=>"object"==typeof i?dt(t,e,i):((t,e,i)=>{const s=e.hasOwnProperty(i);return e.constructor.createProperty(i,t),s?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i)}function ut(t){return pt({...t,state:!0,attribute:!1})}const gt=(t,e,i)=>(i.configurable=!0,i.enumerable=!0,Reflect.decorate&&"object"!=typeof e&&Object.defineProperty(t,e,i),i);function mt(t,e){return(i,s,o)=>{const r=e=>e.renderRoot?.querySelector(t)??null;if(e){const{get:t,set:e}="object"==typeof s?i:o??(()=>{const t=Symbol();return{get(){return this[t]},set(e){this[t]=e}}})();return gt(i,s,{get(){let i=t.call(this);return void 0===i&&(i=r(this),(null!==i||this.hasUpdated)&&e.call(this,i)),i}})}return gt(i,s,{get(){return r(this)}})}}const vt=["ha-form","ha-icon","ha-icon-button","ha-selector","ha-textfield","ha-icon-picker","ha-icon-button","ha-entity-picker","ha-select","ha-dialog","ha-sortable","ha-svg-icon","ha-alert","ha-button","ha-color-picker","ha-badge","ha-sankey-chart","mwc-button"],_t="switch_manager",bt=["single","restart","queued","parallel"];function ft(t){return t?`/${_t}/${t}`:`/${_t}`}function yt(t){return`/assets/${_t}/${t}`}function wt(t){return`${_t}/${t}`}function xt(t){history.pushState(null,"",t);const e=new Event("location-changed");window.dispatchEvent(e)}function $t(t,e,i){const s=new CustomEvent(e,{bubbles:!0,composed:!0,detail:i});t.dispatchEvent(s)}function At(t,e){$t(t,"hass-notification",{message:e})}function Ct(t,e,i,s){$t(t,"show-dialog",{dialogTag:e,dialogImport:i,dialogParams:s})}let St=class extends nt{constructor(){super(...arguments),this.heading="",this._onKeydown=t=>{"Escape"===t.key&&this._close()}}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._onKeydown)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("keydown",this._onKeydown)}render(){return I` +function t(t,e,i,s){var o,r=arguments.length,n=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(t,e,i,s);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(n=(r<3?o(n):r>3?o(e,i,n):o(e,i))||n);return r>3&&n&&Object.defineProperty(e,i,n),n}"function"==typeof SuppressedError&&SuppressedError;const e=globalThis,i=e.ShadowRoot&&(void 0===e.ShadyCSS||e.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s=Symbol(),o=new WeakMap;let r=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==s)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(i&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=o.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&o.set(e,t))}return t}toString(){return this.cssText}};const n=(t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,s)=>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.")})(i)+t[s+1],t[0]);return new r(i,t,s)},a=i?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new r("string"==typeof t?t:t+"",void 0,s))(e)})(t):t,{is:c,defineProperty:h,getOwnPropertyDescriptor:l,getOwnPropertyNames:d,getOwnPropertySymbols:p,getPrototypeOf:u}=Object,g=globalThis,_=g.trustedTypes,m=_?_.emptyScript:"",v=g.reactiveElementPolyfillSupport,b=(t,e)=>t,f={toAttribute(t,e){switch(e){case Boolean:t=t?m:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},y=(t,e)=>!c(t,e),x={attribute:!0,type:String,converter:f,reflect:!1,useDefault:!1,hasChanged:y};Symbol.metadata??=Symbol("metadata"),g.litPropertyMetadata??=new WeakMap;let w=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=x){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&h(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:o}=l(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const r=s?.call(this);o?.call(this,e),this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??x}static _$Ei(){if(this.hasOwnProperty(b("elementProperties")))return;const t=u(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(b("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(b("properties"))){const t=this.properties,e=[...d(t),...p(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(a(t))}else void 0!==t&&e.push(a(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((t,s)=>{if(i)t.adoptedStyleSheets=s.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const i of s){const s=document.createElement("style"),o=e.litNonce;void 0!==o&&s.setAttribute("nonce",o),s.textContent=i.cssText,t.appendChild(s)}})(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const o=(void 0!==i.converter?.toAttribute?i.converter:f).toAttribute(e,i.type);this._$Em=t,null==o?this.removeAttribute(s):this.setAttribute(s,o),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),o="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:f;this._$Em=s;const r=o.fromAttribute(e,t.type);this[s]=r??this._$Ej?.get(s)??r,this._$Em=null}}requestUpdate(t,e,i,s=!1,o){if(void 0!==t){const r=this.constructor;if(!1===s&&(o=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??y)(o,e)||i.useDefault&&i.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:o},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),!0!==o||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===s&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,s=this[e];!0!==t||this._$AL.has(e)||void 0===s||this.C(e,void 0,i,s)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};w.elementStyles=[],w.shadowRootOptions={mode:"open"},w[b("elementProperties")]=new Map,w[b("finalized")]=new Map,v?.({ReactiveElement:w}),(g.reactiveElementVersions??=[]).push("2.1.2");const $=globalThis,C=t=>t,S=$.trustedTypes,A=S?S.createPolicy("lit-html",{createHTML:t=>t}):void 0,k="$lit$",H=`lit$${Math.random().toFixed(9).slice(2)}$`,E="?"+H,V=`<${E}>`,M=document,L=()=>M.createComment(""),D=t=>null===t||"object"!=typeof t&&"function"!=typeof t,T=Array.isArray,P="[ \t\n\f\r]",B=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,U=/-->/g,q=/>/g,N=RegExp(`>|${P}(?:([^\\s"'>=/]+)(${P}*=${P}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),O=/'/g,z=/"/g,R=/^(?:script|style|textarea|title)$/i,F=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),j=F(1),I=F(2),Z=Symbol.for("lit-noChange"),W=Symbol.for("lit-nothing"),K=new WeakMap,J=M.createTreeWalker(M,129);function G(t,e){if(!T(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==A?A.createHTML(e):e}const Q=(t,e)=>{const i=t.length-1,s=[];let o,r=2===e?"":3===e?"":"",n=B;for(let e=0;e"===c[0]?(n=o??B,h=-1):void 0===c[1]?h=-2:(h=n.lastIndex-c[2].length,a=c[1],n=void 0===c[3]?N:'"'===c[3]?z:O):n===z||n===O?n=N:n===U||n===q?n=B:(n=N,o=void 0);const d=n===N&&t[e+1].startsWith("/>")?" ":"";r+=n===B?i+V:h>=0?(s.push(a),i.slice(0,h)+k+i.slice(h)+H+d):i+H+(-2===h?e:d)}return[G(t,r+(t[i]||"")+(2===e?"":3===e?"":"")),s]};class Y{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let o=0,r=0;const n=t.length-1,a=this.parts,[c,h]=Q(t,e);if(this.el=Y.createElement(c,i),J.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=J.nextNode())&&a.length0){s.textContent=S?S.emptyScript:"";for(let i=0;iT(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==W&&D(this._$AH)?this._$AA.nextSibling.data=t:this.T(M.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,s="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=Y.createElement(G(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new tt(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=K.get(t.strings);return void 0===e&&K.set(t.strings,e=new Y(t)),e}k(t){T(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const o of t)s===e.length?e.push(i=new et(this.O(L()),this.O(L()),this,this.options)):i=e[s],i._$AI(o),s++;s2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=W}_$AI(t,e=this,i,s){const o=this.strings;let r=!1;if(void 0===o)t=X(this,t,e,0),r=!D(t)||t!==this._$AH&&t!==Z,r&&(this._$AH=t);else{const s=t;let n,a;for(t=o[0],n=0;n{const s=i?.renderBefore??e;let o=s._$litPart$;if(void 0===o){const t=i?.renderBefore??null;s._$litPart$=o=new et(e.insertBefore(L(),t),t,void 0,i??{})}return o._$AI(t),o})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return Z}};ht._$litElement$=!0,ht.finalized=!0,ct.litElementHydrateSupport?.({LitElement:ht});const lt=ct.litElementPolyfillSupport;lt?.({LitElement:ht}),(ct.litElementVersions??=[]).push("4.2.2");const dt=t=>(e,i)=>{void 0!==i?i.addInitializer(()=>{customElements.define(t,e)}):customElements.define(t,e)},pt={attribute:!0,type:String,converter:f,reflect:!1,hasChanged:y},ut=(t=pt,e,i)=>{const{kind:s,metadata:o}=i;let r=globalThis.litPropertyMetadata.get(o);if(void 0===r&&globalThis.litPropertyMetadata.set(o,r=new Map),"setter"===s&&((t=Object.create(t)).wrapped=!0),r.set(i.name,t),"accessor"===s){const{name:s}=i;return{set(i){const o=e.get.call(this);e.set.call(this,i),this.requestUpdate(s,o,t,!0,i)},init(e){return void 0!==e&&this.C(s,void 0,t,e),e}}}if("setter"===s){const{name:s}=i;return function(i){const o=this[s];e.call(this,i),this.requestUpdate(s,o,t,!0,i)}}throw Error("Unsupported decorator location: "+s)};function gt(t){return(e,i)=>"object"==typeof i?ut(t,e,i):((t,e,i)=>{const s=e.hasOwnProperty(i);return e.constructor.createProperty(i,t),s?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i)}function _t(t){return gt({...t,state:!0,attribute:!1})}const mt=(t,e,i)=>(i.configurable=!0,i.enumerable=!0,Reflect.decorate&&"object"!=typeof e&&Object.defineProperty(t,e,i),i);function vt(t,e){return(i,s,o)=>{const r=e=>e.renderRoot?.querySelector(t)??null;if(e){const{get:t,set:e}="object"==typeof s?i:o??(()=>{const t=Symbol();return{get(){return this[t]},set(e){this[t]=e}}})();return mt(i,s,{get(){let i=t.call(this);return void 0===i&&(i=r(this),(null!==i||this.hasUpdated)&&e.call(this,i)),i}})}return mt(i,s,{get(){return r(this)}})}}const bt=["ha-form","ha-icon","ha-icon-button","ha-selector","ha-textfield","ha-icon-picker","ha-icon-button","ha-entity-picker","ha-select","ha-dialog","ha-sortable","ha-svg-icon","ha-alert","ha-button","ha-color-picker","ha-badge","ha-sankey-chart","mwc-button"],ft="switch_manager",yt=["single","restart","queued","parallel"];function xt(t){return t?`/${ft}/${t}`:`/${ft}`}function wt(t){return`/assets/${ft}/${t}`}function $t(t){return`${ft}/${t}`}function Ct(t){history.pushState(null,"",t);const e=new Event("location-changed");window.dispatchEvent(e)}function St(t,e,i){const s=new CustomEvent(e,{bubbles:!0,composed:!0,detail:i});t.dispatchEvent(s)}function At(t,e){St(t,"hass-notification",{message:e})}function kt(t,e,i,s){St(t,"show-dialog",{dialogTag:e,dialogImport:i,dialogParams:s})}let Ht=class extends ht{constructor(){super(...arguments),this.heading="",this._onKeydown=t=>{"Escape"===t.key&&this._close()}}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._onKeydown)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("keydown",this._onKeydown)}render(){return j`
@@ -13,7 +13,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro
- `}_stop(t){t.stopPropagation()}_close(){this.dispatchEvent(new CustomEvent("closed"))}static{this.styles=a` + `}_stop(t){t.stopPropagation()}_close(){this.dispatchEvent(new CustomEvent("closed"))}static{this.styles=n` .backdrop { position: fixed; inset: 0; @@ -72,7 +72,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro ::slotted(button.destructive) { color: var(--error-color, #db4437); } - `}};t([pt()],St.prototype,"heading",void 0),St=t([lt("switch-manager-dialog")],St);let kt=class extends nt{constructor(){super(...arguments),this._blueprints=[],this._filter=""}showDialog(t){this._params=t,this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._loadBlueprints()}closeDialog(){this._params=void 0,this._blueprints=[],this._filter=""}async _loadBlueprints(){const t=await this.hass.callWS({type:wt("blueprints")});this._blueprints=Object.values(t.blueprints)}render(){if(!this._params)return I``;const t=this._filter?this._blueprints.filter(t=>t.name.toLowerCase().includes(this._filter.toLowerCase())||t.service.toLowerCase().includes(this._filter.toLowerCase())):this._blueprints;return I` + `}};t([gt()],Ht.prototype,"heading",void 0),Ht=t([dt("switch-manager-dialog")],Ht);let Et=class extends ht{constructor(){super(...arguments),this._blueprints=[],this._filter=""}showDialog(t){this._params=t,this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._loadBlueprints()}closeDialog(){this._params=void 0,this._blueprints=[],this._filter=""}async _loadBlueprints(){const t=await this.hass.callWS({type:$t("blueprints")});this._blueprints=Object.values(t.blueprints)}render(){if(!this._params)return j``;const t=this._filter?this._blueprints.filter(t=>t.name.toLowerCase().includes(this._filter.toLowerCase())||t.service.toLowerCase().includes(this._filter.toLowerCase())):this._blueprints;return j` this._filter=t.target.value} />
- ${t.map(t=>I` + ${t.map(t=>j` this._selectBlueprint(t)} >
+ ${t.editable?j` + + `:W}
- ${t.has_image?I``:I``:j``}
@@ -102,9 +111,10 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro `)}
+ - `}_selectBlueprint(t){this.closeDialog(),xt(ft(`new/${t.id}`))}static{this.styles=a` + `}_selectBlueprint(t){this.closeDialog(),Ct(xt(`new/${t.id}`))}_createBlueprint(){this.closeDialog(),Ct(xt("blueprint/new"))}_editBlueprint(t,e){t.preventDefault(),t.stopPropagation(),this.closeDialog(),Ct(xt(`blueprint/edit/${e.id}`))}static{this.styles=n` .blueprints { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); @@ -122,6 +132,31 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro .card-content { text-align: center; padding: 8px; + position: relative; + } + .edit-btn { + position: absolute; + top: 4px; + right: 4px; + border: none; + background: var(--secondary-background-color); + border-radius: 50%; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + padding: 0; + z-index: 1; + } + .edit-btn:hover { + background: var(--primary-color); + color: var(--text-primary-color, #fff); + } + .edit-btn ha-svg-icon { + width: 18px; + height: 18px; } .image { height: 80px; @@ -158,7 +193,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro color: var(--primary-text-color); font: inherit; } - `}};t([ut()],kt.prototype,"_params",void 0),t([ut()],kt.prototype,"_blueprints",void 0),t([ut()],kt.prototype,"_filter",void 0),kt=t([lt("switch-manager-dialog-blueprint-selector")],kt);var Ht=Object.freeze({__proto__:null,get SwitchManagerDialogBlueprintSelector(){return kt}});let Vt=class extends nt{constructor(){super(...arguments),this.path="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z",this.label="Menu",this.align="left",this._open=!1,this._onDocClick=t=>{t.composedPath().includes(this)||(this._open=!1)}}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this._onDocClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this._onDocClick)}render(){return I` + `}};t([_t()],Et.prototype,"_params",void 0),t([_t()],Et.prototype,"_blueprints",void 0),t([_t()],Et.prototype,"_filter",void 0),Et=t([dt("switch-manager-dialog-blueprint-selector")],Et);var Vt=Object.freeze({__proto__:null,get SwitchManagerDialogBlueprintSelector(){return Et}});let Mt=class extends ht{constructor(){super(...arguments),this.path="M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z",this.label="Menu",this.align="left",this._open=!1,this._onDocClick=t=>{t.composedPath().includes(this)||(this._open=!1)}}connectedCallback(){super.connectedCallback(),document.addEventListener("click",this._onDocClick)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("click",this._onDocClick)}render(){return j`
- `}_toggle(t){t.stopPropagation(),this._open=!this._open}_onSurfaceClick(t){const e=t.target.closest(".menu-item");e&&e.hasAttribute("disabled")?t.stopPropagation():this._open=!1}static{this.styles=a` + `}_toggle(t){t.stopPropagation(),this._open=!this._open}_onSurfaceClick(t){const e=t.target.closest(".menu-item");e&&e.hasAttribute("disabled")?t.stopPropagation():this._open=!1}static{this.styles=n` :host { position: relative; display: inline-flex; @@ -222,9 +257,9 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro ::slotted(.menu-item.warning) { color: var(--error-color, #db4437); } - `}};t([pt()],Vt.prototype,"path",void 0),t([pt()],Vt.prototype,"label",void 0),t([pt()],Vt.prototype,"align",void 0),t([ut()],Vt.prototype,"_open",void 0),Vt=t([lt("switch-manager-menu")],Vt);let Et=class extends nt{constructor(){super(...arguments),this.narrow=!1,this._data=[],this._filter="",this._sortColumn="name",this._sortDirection="asc"}connectedCallback(){super.connectedCallback();try{const t=JSON.parse(localStorage.getItem("switchManagerSort")||"{}");t.column&&(this._sortColumn=t.column),t.direction&&(this._sortDirection=t.direction)}catch{}this._populateSwitches()}get _filteredSortedData(){let t=this._data;if(this._filter){const e=this._filter.toLowerCase();t=t.filter(t=>t.name.toLowerCase().includes(e)||t.service.toLowerCase().includes(e)||t.type.toLowerCase().includes(e))}const e=this._sortColumn,i="asc"===this._sortDirection?1:-1;return[...t].sort((t,s)=>{if("enabled"===e)return((t.enabled?1:0)-(s.enabled?1:0))*i;const o=String(t[e]||"").toLowerCase(),r=String(s[e]||"").toLowerCase();return o.localeCompare(r)*i})}_toggleSort(t){this._sortColumn===t?this._sortDirection="asc"===this._sortDirection?"desc":"asc":(this._sortColumn=t,this._sortDirection="asc"),localStorage.setItem("switchManagerSort",JSON.stringify({column:this._sortColumn,direction:this._sortDirection}))}_sortIcon(t){return this._sortColumn!==t?Z:I`t.name.toLowerCase().includes(e)||t.service.toLowerCase().includes(e)||t.type.toLowerCase().includes(e))}const e=this._sortColumn,i="asc"===this._sortDirection?1:-1;return[...t].sort((t,s)=>{if("enabled"===e)return((t.enabled?1:0)-(s.enabled?1:0))*i;const o=String(t[e]||"").toLowerCase(),r=String(s[e]||"").toLowerCase();return o.localeCompare(r)*i})}_toggleSort(t){this._sortColumn===t?this._sortDirection="asc"===this._sortDirection?"desc":"asc":(this._sortColumn=t,this._sortDirection="asc"),localStorage.setItem("switchManagerSort",JSON.stringify({column:this._sortColumn,direction:this._sortDirection}))}_sortIcon(t){return this._sortColumn!==t?W:j``}_getOverflowItems(t){return[{path:t.enabled?"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4M9,9V15H15V9":"M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z",label:t.enabled?"Disable":"Enable",action:()=>this._toggleEnabled(t.switch_id,t.enabled)},{path:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z",label:"Duplicate",action:()=>this._duplicate(t.switch_id)},{path:"M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z",label:"Delete",action:()=>this._deleteConfirm(t),warning:!0}]}render(){const t=this._filteredSortedData;return I` + >`}_getOverflowItems(t){return[{path:t.enabled?"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4M9,9V15H15V9":"M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z",label:t.enabled?"Disable":"Enable",action:()=>this._toggleEnabled(t.switch_id,t.enabled)},{path:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z",label:"Duplicate",action:()=>this._duplicate(t.switch_id)},{path:"M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z",label:"Delete",action:()=>this._deleteConfirm(t),warning:!0}]}render(){const t=this._filteredSortedData;return j`
Name ${this._sortIcon("name")}
- ${this.narrow?Z:I` + ${this.narrow?W:j`
this._toggleSort("service")} @@ -272,31 +307,31 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro
- ${0===t.length?I`
+ ${0===t.length?j`
${0===this._data.length?"No Switches configured":"No matches found"} -
`:t.map(t=>I` +
`:t.map(t=>j`
this._editSwitch(t.switch_id)} >
- ${t.switch.valid_blueprint&&t.switch.blueprint.has_image?I``:I``:j``}
- ${t.error?I`${t.name} (${t.error})`:t.name} - ${t.enabled?Z:I`Disabled`}
- ${this.narrow?Z:I` + ${this.narrow?W:j`
${t.service}
@@ -304,7 +339,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro `}
t.stopPropagation()}> - ${this._getOverflowItems(t).map(t=>I` + ${this._getOverflowItems(t).map(t=>j`
- `}_populateSwitches(){this.hass.callWS({type:wt("configs")}).then(t=>{const e=[];Object.values(t.configs).forEach(t=>{const i=t.valid_blueprint?t.blueprint:{id:t.blueprint,service:"",name:""};e.push({switch:t,blueprint_id:i.id,switch_id:t.id,error:t._error,enabled:t.enabled,name:t.name,service:i.service||"",type:i.name||"",actions:t.id})}),this._data=e})}_editSwitch(t){xt(ft(`edit/${t}`))}async _toggleEnabled(t,e){try{const i=await this.hass.callWS({type:wt("config/enabled"),enabled:!e,config_id:t});this._populateSwitches(),At(this,"Switch "+(i.enabled?"Enabled":"Disabled"))}catch(t){At(this,t.message)}}async _duplicate(t){try{const e=await this.hass.callWS({type:wt("config/duplicate"),config_id:t});At(this,"Switch Duplicated"),xt(ft(`edit/${e.config_id}`))}catch(t){At(this,t.message)}}async _deleteConfirm(t){Ct(this,"switch-manager-dialog-confirm",()=>Promise.resolve().then(function(){return qt}),{title:"Delete switch?",text:`${t.name} will be permanently deleted.`,confirmText:"Delete",dismissText:"Cancel",confirm:()=>this._delete(t.switch_id),confirmation:!0,destructive:!0})}async _delete(t){try{await this.hass.callWS({type:wt("config/delete"),config_id:t.toString()}),this._populateSwitches(),At(this,"Switch Deleted")}catch(t){At(this,t.message)}}_showBlueprintDialog(){Ct(this,"switch-manager-dialog-blueprint-selector",()=>Promise.resolve().then(function(){return Ht}),{})}static{this.styles=a` + `}_populateSwitches(){this.hass.callWS({type:$t("configs")}).then(t=>{const e=[];Object.values(t.configs).forEach(t=>{const i=t.valid_blueprint?t.blueprint:{id:t.blueprint,service:"",name:""};e.push({switch:t,blueprint_id:i.id,switch_id:t.id,error:t._error,enabled:t.enabled,name:t.name,service:i.service||"",type:i.name||"",actions:t.id})}),this._data=e})}_editSwitch(t){Ct(xt(`edit/${t}`))}async _toggleEnabled(t,e){try{const i=await this.hass.callWS({type:$t("config/enabled"),enabled:!e,config_id:t});this._populateSwitches(),At(this,"Switch "+(i.enabled?"Enabled":"Disabled"))}catch(t){At(this,t.message)}}async _duplicate(t){try{const e=await this.hass.callWS({type:$t("config/duplicate"),config_id:t});At(this,"Switch Duplicated"),Ct(xt(`edit/${e.config_id}`))}catch(t){At(this,t.message)}}async _deleteConfirm(t){kt(this,"switch-manager-dialog-confirm",()=>Promise.resolve().then(function(){return jt}),{title:"Delete switch?",text:`${t.name} will be permanently deleted.`,confirmText:"Delete",dismissText:"Cancel",confirm:()=>this._delete(t.switch_id),confirmation:!0,destructive:!0})}async _delete(t){try{await this.hass.callWS({type:$t("config/delete"),config_id:t.toString()}),this._populateSwitches(),At(this,"Switch Deleted")}catch(t){At(this,t.message)}}_showBlueprintDialog(){kt(this,"switch-manager-dialog-blueprint-selector",()=>Promise.resolve().then(function(){return Vt}),{})}static{this.styles=n` :host { display: block; } @@ -523,9 +558,9 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro padding: 1.2em; z-index: 1; } - `}};t([pt({attribute:!1})],Et.prototype,"hass",void 0),t([pt({type:Boolean})],Et.prototype,"narrow",void 0),t([pt({attribute:!1})],Et.prototype,"panel",void 0),t([pt({attribute:!1})],Et.prototype,"route",void 0),t([ut()],Et.prototype,"_data",void 0),t([ut()],Et.prototype,"_filter",void 0),t([ut()],Et.prototype,"_sortColumn",void 0),t([ut()],Et.prototype,"_sortDirection",void 0),Et=t([lt("switch-manager-index")],Et);const Lt=1;class Mt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}const Dt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends Mt{constructor(t){if(super(t),t.type!==Lt||"class"!==t.name||t.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter(e=>t[e]).join(" ")+" "}update(t,[e]){if(void 0===this.st){this.st=new Set,void 0!==t.strings&&(this.nt=new Set(t.strings.join(" ").split(/\s/).filter(t=>""!==t)));for(const t in e)e[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(e)}const i=t.element.classList;for(const t of this.st)t in e||(i.remove(t),this.st.delete(t));for(const t in e){const s=!!e[t];s===this.st.has(t)||this.nt?.has(t)||(s?(i.add(t),this.st.add(t)):(i.remove(t),this.st.delete(t)))}return B}});let Pt=class extends nt{constructor(){super(...arguments),this.index=0}render(){return!this.blueprint_actions||this.blueprint_actions.length<=1?I``:I` + `}};t([gt({attribute:!1})],Lt.prototype,"hass",void 0),t([gt({type:Boolean})],Lt.prototype,"narrow",void 0),t([gt({attribute:!1})],Lt.prototype,"panel",void 0),t([gt({attribute:!1})],Lt.prototype,"route",void 0),t([_t()],Lt.prototype,"_data",void 0),t([_t()],Lt.prototype,"_filter",void 0),t([_t()],Lt.prototype,"_sortColumn",void 0),t([_t()],Lt.prototype,"_sortDirection",void 0),Lt=t([dt("switch-manager-index")],Lt);const Dt=1;class Tt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}const Pt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends Tt{constructor(t){if(super(t),t.type!==Dt||"class"!==t.name||t.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return" "+Object.keys(t).filter(e=>t[e]).join(" ")+" "}update(t,[e]){if(void 0===this.st){this.st=new Set,void 0!==t.strings&&(this.nt=new Set(t.strings.join(" ").split(/\s/).filter(t=>""!==t)));for(const t in e)e[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(e)}const i=t.element.classList;for(const t of this.st)t in e||(i.remove(t),this.st.delete(t));for(const t in e){const s=!!e[t];s===this.st.has(t)||this.nt?.has(t)||(s?(i.add(t),this.st.add(t)):(i.remove(t),this.st.delete(t)))}return Z}});let Bt=class extends ht{constructor(){super(...arguments),this.index=0}render(){return!this.blueprint_actions||this.blueprint_actions.length<=1?j``:j`
- ${this.blueprint_actions.map((t,e)=>{const i=this.config_actions?.[e]?.sequence?.length||0;return I` + ${this.blueprint_actions.map((t,e)=>{const i=this.config_actions?.[e]?.sequence?.length||0;return j` `})}
- `}flash(t){const e=this.tabs?.querySelector(`[index="${t}"]`);e&&(e.removeAttribute("feedback"),e.setAttribute("feedback",""),setTimeout(()=>e.removeAttribute("feedback"),1e3))}_select(t){this.dispatchEvent(new CustomEvent("changed",{detail:{index:t}}))}static{this.styles=a` + `}flash(t){const e=this.tabs?.querySelector(`[index="${t}"]`);e&&(e.removeAttribute("feedback"),e.setAttribute("feedback",""),setTimeout(()=>e.removeAttribute("feedback"),1e3))}_select(t){this.dispatchEvent(new CustomEvent("changed",{detail:{index:t}}))}static{this.styles=n` @keyframes feedback { to { border-color: #00e903; @@ -600,7 +635,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro .init-icon { --mdc-icon-size: 18px; } - `}};t([pt({attribute:!1})],Pt.prototype,"hass",void 0),t([pt({attribute:!1})],Pt.prototype,"blueprint_actions",void 0),t([pt({attribute:!1})],Pt.prototype,"config_actions",void 0),t([pt({type:Number,reflect:!0})],Pt.prototype,"index",void 0),t([mt(".tabs",!0)],Pt.prototype,"tabs",void 0),Pt=t([lt("switch-manager-button-actions")],Pt);let Tt=class extends nt{constructor(){super(...arguments),this.narrow=!1,this.disabled=!1,this.sequence=[],this.button_index=0,this.action_index=0,this.is_new=!0,this._is_yaml=!1,this._dirty=!1,this._debug=!1,this._block_save=!1}render(){if(!this.config)return I``;const t=!!this.config._error;return I` + `}};t([gt({attribute:!1})],Bt.prototype,"hass",void 0),t([gt({attribute:!1})],Bt.prototype,"blueprint_actions",void 0),t([gt({attribute:!1})],Bt.prototype,"config_actions",void 0),t([gt({type:Number,reflect:!0})],Bt.prototype,"index",void 0),t([vt(".tabs",!0)],Bt.prototype,"tabs",void 0),Bt=t([dt("switch-manager-button-actions")],Bt);let Ut=class extends ht{constructor(){super(...arguments),this.narrow=!1,this.disabled=!1,this.sequence=[],this.button_index=0,this.action_index=0,this.is_new=!0,this._is_yaml=!1,this._dirty=!1,this._debug=!1,this._block_save=!1}render(){if(!this.config)return j``;const t=!!this.config._error;return j`
- ${t?Z:I`

${this.blueprint?.service} / ${this.blueprint?.name}

`} + ${t?W:j`

${this.blueprint?.service} / ${this.blueprint?.name}

`}
- ${!this.blueprint||this.blueprint?.has_image?I``:I``} + ${!this.blueprint||this.blueprint?.has_image?j``:j``}
- ${t?Z:I` + ${t?W:j`
- ${this._errors?I` + ${this._errors?j` ${this._errors} - ${this.config.is_mismatch?I``:""} + ${this.config.is_mismatch?j``:""} `:""} - ${this.config&&!this.config.enabled?I` + ${this.config&&!this.config.enabled?j` Switch is disabled `:""} - ${t?Z:I` + ${t?W:j`

@@ -714,7 +749,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro .hass=${this.hass} .value=${this.config?.buttons[this.button_index]?.actions[this.action_index]?.mode} label="Mode" - .selector=${{select:{mode:"dropdown",options:bt.map(t=>({label:t.charAt(0).toUpperCase()+t.slice(1),value:t}))}}} + .selector=${{select:{mode:"dropdown",options:yt.map(t=>({label:t.charAt(0).toUpperCase()+t.slice(1),value:t}))}}} @value-changed=${this._modeValueChanged} >

@@ -725,11 +760,11 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro
- ${this._is_yaml?I``:I``:j` - ${t?Z:I` + ${t?W:j`
`}
- `}connectedCallback(){super.connectedCallback(),this._loadConfig(),this._startListeners()}disconnectedCallback(){this._killListener("_reloadListener"),this._killListener("_subscribedMonitor"),super.disconnectedCallback()}_killListener(t){return!!this[t]&&(this[t](),this[t]=void 0,!0)}async _startListeners(){this._reloadListener=await this.hass.connection.subscribeEvents(t=>{"switch_manager"===t.data.domain&&"reload"===t.data.service&&this._loadConfig()},"call_service")}_loadConfig(){"id"in this.params?(this.is_new=!1,this.hass.callWS({type:wt("configs"),config_id:this.params.id}).then(t=>this._setConfig(t.config))):(this.is_new=!0,this._dirty=!0,"blueprint"in this.params&&this._loadBlueprint(this.params.blueprint).then(t=>{this._setConfig(function(t){const e={id:null,name:"New Switch",enabled:!0,identifier:"",blueprint:t,valid_blueprint:!0,buttons:[],is_mismatch:!1,rotate:0};return t.buttons.forEach((t,i)=>{e.buttons[i]={actions:[]},t.actions.forEach((t,s)=>{e.buttons[i].actions[s]={mode:bt[0],sequence:[]}})}),e}(t.blueprint)),this._showRenameDialog()}))}_loadBlueprint(t){return this.hass.callWS({type:wt("blueprints"),blueprint_id:t})}_setConfig(t){if(this.config=t,t._error)return this._errors=t._error,void(this._block_save=!0);this._setBlueprint(t.blueprint),this._updateSequence(),this._monitor()}async _monitor(){this.is_new||(this._killListener("_subscribedMonitor"),this._subscribedMonitor=await this.hass.connection.subscribeMessage(t=>{if("action_triggered"===t.event){if(!this.config?.identifier)return;if(t.button===this.button_index&&(this.blueprint?.buttons[this.button_index]?.actions.length??0)>1&&this.button_actions.flash(t.action),1===this.blueprint?.buttons?.length)return void At(this,"Button Pressed");const e=this.svg?.querySelector(`[index="${t.button}"]`);e&&(e.removeAttribute("pressed"),e.setAttribute("pressed",""),setTimeout(()=>e.removeAttribute("pressed"),1e3))}"incoming"!==t.event&&"action_triggered"!==t.event||!this._debug||console.log(t)},{type:wt("config/monitor"),config_id:this.config.id}))}_setBlueprint(t){this.blueprint=t,this.requestUpdate(),this._drawSVG()}async _drawSVG(){if(!this.blueprint?.has_image)return;await this.updateComplete;const t=this.svg;if(t){const e=t.cloneNode(!1);t.parentNode.replaceChild(e,t)}const e=new Image;e.src=yt(`${this.blueprint.id}.png`),e.onload=()=>{const t=this.svg;if(!t)return;t.setAttributeNS(null,"viewBox",`0 0 ${e.width} ${e.height}`);const i=document.createElementNS("http://www.w3.org/2000/svg","image");i.setAttributeNS(null,"x","0"),i.setAttributeNS(null,"y","0"),i.setAttributeNS(null,"width",e.width.toString()),i.setAttributeNS(null,"height",e.height.toString()),i.setAttributeNS("http://www.w3.org/1999/xlink","href",e.src),i.setAttributeNS(null,"visibility","visible"),t.prepend(i)},this.blueprint.buttons.length>1&&this.blueprint.buttons.forEach((t,e)=>{let i;if(t.x>-1&&t.y>-1&&t.width>0&&t.height>0)i=document.createElementNS("http://www.w3.org/2000/svg","rect"),i.setAttributeNS(null,"x",t.x.toString()),i.setAttributeNS(null,"y",t.y.toString()),i.setAttributeNS(null,"width",t.width.toString()),i.setAttributeNS(null,"height",t.height.toString());else if(t.x>-1&&t.y>-1&&t.width>0)i=document.createElementNS("http://www.w3.org/2000/svg","circle"),i.setAttributeNS(null,"cx",t.x.toString()),i.setAttributeNS(null,"cy",t.y.toString()),i.setAttributeNS(null,"r",t.width.toString());else{if(!t.d)return;i=document.createElementNS("http://www.w3.org/2000/svg","path"),i.setAttributeNS(null,"d",t.d.toString())}i.setAttribute("class","button"),i.setAttribute("index",e.toString()),this.button_index===e&&i.setAttribute("selected",""),this._buttonTotalSequence(this.config.buttons[e])||i.setAttribute("empty",""),i.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this._setButtonIndex(parseInt(t.target.getAttribute("index")))}),this.svg?.append(i)})}_buttonTotalSequence(t){let e=0;return t.actions.forEach(t=>e+=t.sequence.length),e}_updateSequence(t){t&&(this.config.buttons[this.button_index].actions[this.action_index].sequence=t),this.sequence=[...this.config?.buttons[this.button_index]?.actions[this.action_index]?.sequence||[]]}_validate(){return this._errors=void 0,!!this.config?.identifier||(this._showIdentifierAutoDiscoveryDialog(!0),!1)}_save(){!this._block_save&&this._validate()&&this.config&&!this.config._error&&(this._block_save=!0,this._dirty=!1,this.hass.callWS({type:wt("config/save"),config:{...this.config,blueprint:this.config.blueprint.id}}).then(t=>{this.is_new&&(this.is_new=!1,this.config.id=t.config_id,xt(ft(`edit/${t.config_id}`)),this._monitor()),At(this,"Switch Saved")}).catch(t=>{At(this,t.message),this._errors=t.message,this._dirty=!0}).finally(()=>this._block_save=!1))}_backTapped(){xt(ft())}_actionChanged(t){this._setActionIndex(t.detail.index)}_setButtonIndex(t){t!==this.button_index&&(this.button_index=t,this.svg?.querySelector("[selected]")?.removeAttribute("selected"),this.svg?.querySelector(`[index="${t}"]`)?.setAttribute("selected",""),this._setActionIndex(0))}_setActionIndex(t){this.action_index=t,this._updateSequence(),this._is_yaml&&this._yamlEditor?.setValue(this.sequence)}_configSequenceChanged(t){let e=t.detail.value;!this._is_yaml||e&&Array.isArray(e)||(e=[]),this.requestUpdate("config"),this._updateSequence(e),this._errors=void 0,this._dirty=!0}_rotate(){this.config.rotate=this.config.rotate>=3?0:this.config.rotate+1,this.requestUpdate("config"),this._dirty=!0}_toggleDebug(){this._debug=!this._debug,At(this,"Debug "+(this._debug?"Enabled. View dev console":"Disabled"))}_toggleYaml(){this._is_yaml=!this._is_yaml,this.updateComplete.then(()=>{this._is_yaml&&this._yamlEditor?.setValue(this.sequence)})}_modeValueChanged(t){const e=this.config?.buttons[this.button_index]?.actions[this.action_index]?.mode;e!==t.detail.value&&(this.config.buttons[this.button_index].actions[this.action_index].mode=t.detail.value,this.requestUpdate("config"),this._dirty=!0)}_toggleEnabled(){this.config&&!this.is_new&&(this.config.enabled=!this.config.enabled,this.hass.callWS({type:wt("config/enabled"),enabled:this.config.enabled,config_id:this.config.id}),this.requestUpdate("config"))}_fixMismatch(){this.config&&this.hass.callWS({type:wt("config/save"),config:{...this.config,blueprint:this.config.blueprint.id},fix_mismatch:!0}).then(()=>{this._errors=void 0,this.config.is_mismatch=!1,this.requestUpdate(),At(this,"Mismatch Fixed")})}_deleteConfirm(){this.is_new||Ct(this,"switch-manager-dialog-confirm",()=>Promise.resolve().then(function(){return qt}),{title:"Delete switch?",text:`${this.config?.name} will be permanently deleted.`,confirmText:"Delete",dismissText:"Cancel",confirm:()=>{this.hass.callWS({type:wt("config/delete"),config_id:this.config.id.toString()}).then(()=>xt(ft()))},confirmation:!0,destructive:!0})}_showIdentifierAutoDiscoveryDialog(t=!1){Ct(this,"switch-manager-dialog-identifier-auto-discovery",()=>Promise.resolve().then(function(){return Rt}),{switch_id:this.config?.id,identifier:this.config?.identifier,blueprint:this.blueprint,update:e=>{this.config.identifier=e.identifier,this._dirty=!0,this.requestUpdate(),t&&e.identifier&&this._save()},onClose:()=>{}})}_showRenameDialog(){Ct(this,"switch-manager-dialog-rename-switch",()=>Promise.resolve().then(function(){return It}),{config:this.config,update:t=>{this.config.name=t.name,this._dirty=!0,this.requestUpdate()},onClose:()=>{this.is_new&&this._showIdentifierAutoDiscoveryDialog()}})}_showCopyFromDialog(){Ct(this,"switch-manager-dialog-copy-from",()=>Promise.resolve().then(function(){return Zt}),{blueprint_id:this.config?.blueprint?.id,current_switch_id:this.config?.id,update:t=>{this.config.buttons=t.buttons,!1!==t.variables&&(this.config.variables=t.variables),this._dirty=!0,this._updateSequence(),this._drawSVG()},onClose:()=>{}})}_showVariablesEditorDialog(){Ct(this,"switch-manager-dialog-variables-editor",()=>Promise.resolve().then(function(){return Ft}),{config:this.config,update:t=>{this.config.variables=t.variables,this._dirty=!0,this.requestUpdate()},onClose:()=>{}})}static{this.styles=a` + `}connectedCallback(){super.connectedCallback(),this._loadConfig(),this._startListeners()}disconnectedCallback(){this._killListener("_reloadListener"),this._killListener("_subscribedMonitor"),super.disconnectedCallback()}_killListener(t){return!!this[t]&&(this[t](),this[t]=void 0,!0)}async _startListeners(){this._reloadListener=await this.hass.connection.subscribeEvents(t=>{"switch_manager"===t.data.domain&&"reload"===t.data.service&&this._loadConfig()},"call_service")}_loadConfig(){"id"in this.params?(this.is_new=!1,this.hass.callWS({type:$t("configs"),config_id:this.params.id}).then(t=>this._setConfig(t.config))):(this.is_new=!0,this._dirty=!0,"blueprint"in this.params&&this._loadBlueprint(this.params.blueprint).then(t=>{this._setConfig(function(t){const e={id:null,name:"New Switch",enabled:!0,identifier:"",blueprint:t,valid_blueprint:!0,buttons:[],is_mismatch:!1,rotate:0};return t.buttons.forEach((t,i)=>{e.buttons[i]={actions:[]},t.actions.forEach((t,s)=>{e.buttons[i].actions[s]={mode:yt[0],sequence:[]}})}),e}(t.blueprint)),this._showRenameDialog()}))}_loadBlueprint(t){return this.hass.callWS({type:$t("blueprints"),blueprint_id:t})}_setConfig(t){if(this.config=t,t._error)return this._errors=t._error,void(this._block_save=!0);this._setBlueprint(t.blueprint),this._updateSequence(),this._monitor()}async _monitor(){this.is_new||(this._killListener("_subscribedMonitor"),this._subscribedMonitor=await this.hass.connection.subscribeMessage(t=>{if("action_triggered"===t.event){if(!this.config?.identifier)return;if(t.button===this.button_index&&(this.blueprint?.buttons[this.button_index]?.actions.length??0)>1&&this.button_actions.flash(t.action),1===this.blueprint?.buttons?.length)return void At(this,"Button Pressed");const e=this.svg?.querySelector(`[index="${t.button}"]`);e&&(e.removeAttribute("pressed"),e.setAttribute("pressed",""),setTimeout(()=>e.removeAttribute("pressed"),1e3))}"incoming"!==t.event&&"action_triggered"!==t.event||!this._debug||console.log(t)},{type:$t("config/monitor"),config_id:this.config.id}))}_setBlueprint(t){this.blueprint=t,this.requestUpdate(),this._drawSVG()}async _drawSVG(){if(!this.blueprint?.has_image)return;await this.updateComplete;const t=this.svg;if(t){const e=t.cloneNode(!1);t.parentNode.replaceChild(e,t)}const e=new Image;e.src=wt(`${this.blueprint.id}.png`),e.onload=()=>{const t=this.svg;if(!t)return;t.setAttributeNS(null,"viewBox",`0 0 ${e.width} ${e.height}`);const i=document.createElementNS("http://www.w3.org/2000/svg","image");i.setAttributeNS(null,"x","0"),i.setAttributeNS(null,"y","0"),i.setAttributeNS(null,"width",e.width.toString()),i.setAttributeNS(null,"height",e.height.toString()),i.setAttributeNS("http://www.w3.org/1999/xlink","href",e.src),i.setAttributeNS(null,"visibility","visible"),t.prepend(i)},this.blueprint.buttons.length>1&&this.blueprint.buttons.forEach((t,e)=>{let i;if(t.x>-1&&t.y>-1&&t.width>0&&t.height>0)i=document.createElementNS("http://www.w3.org/2000/svg","rect"),i.setAttributeNS(null,"x",t.x.toString()),i.setAttributeNS(null,"y",t.y.toString()),i.setAttributeNS(null,"width",t.width.toString()),i.setAttributeNS(null,"height",t.height.toString());else if(t.x>-1&&t.y>-1&&t.width>0)i=document.createElementNS("http://www.w3.org/2000/svg","circle"),i.setAttributeNS(null,"cx",t.x.toString()),i.setAttributeNS(null,"cy",t.y.toString()),i.setAttributeNS(null,"r",t.width.toString());else{if(!t.d)return;i=document.createElementNS("http://www.w3.org/2000/svg","path"),i.setAttributeNS(null,"d",t.d.toString())}i.setAttribute("class","button"),i.setAttribute("index",e.toString()),this.button_index===e&&i.setAttribute("selected",""),this._buttonTotalSequence(this.config.buttons[e])||i.setAttribute("empty",""),i.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this._setButtonIndex(parseInt(t.target.getAttribute("index")))}),this.svg?.append(i)})}_buttonTotalSequence(t){let e=0;return t.actions.forEach(t=>e+=t.sequence.length),e}_updateSequence(t){t&&(this.config.buttons[this.button_index].actions[this.action_index].sequence=t),this.sequence=[...this.config?.buttons[this.button_index]?.actions[this.action_index]?.sequence||[]]}_validate(){return this._errors=void 0,!!this.config?.identifier||(this._showIdentifierAutoDiscoveryDialog(!0),!1)}_save(){!this._block_save&&this._validate()&&this.config&&!this.config._error&&(this._block_save=!0,this._dirty=!1,this.hass.callWS({type:$t("config/save"),config:{...this.config,blueprint:this.config.blueprint.id}}).then(t=>{this.is_new&&(this.is_new=!1,this.config.id=t.config_id,Ct(xt(`edit/${t.config_id}`)),this._monitor()),At(this,"Switch Saved")}).catch(t=>{At(this,t.message),this._errors=t.message,this._dirty=!0}).finally(()=>this._block_save=!1))}_backTapped(){Ct(xt())}_actionChanged(t){this._setActionIndex(t.detail.index)}_setButtonIndex(t){t!==this.button_index&&(this.button_index=t,this.svg?.querySelector("[selected]")?.removeAttribute("selected"),this.svg?.querySelector(`[index="${t}"]`)?.setAttribute("selected",""),this._setActionIndex(0))}_setActionIndex(t){this.action_index=t,this._updateSequence(),this._is_yaml&&this._yamlEditor?.setValue(this.sequence)}_configSequenceChanged(t){let e=t.detail.value;!this._is_yaml||e&&Array.isArray(e)||(e=[]),this.requestUpdate("config"),this._updateSequence(e),this._errors=void 0,this._dirty=!0}_rotate(){this.config.rotate=this.config.rotate>=3?0:this.config.rotate+1,this.requestUpdate("config"),this._dirty=!0}_toggleDebug(){this._debug=!this._debug,At(this,"Debug "+(this._debug?"Enabled. View dev console":"Disabled"))}_toggleYaml(){this._is_yaml=!this._is_yaml,this.updateComplete.then(()=>{this._is_yaml&&this._yamlEditor?.setValue(this.sequence)})}_modeValueChanged(t){const e=this.config?.buttons[this.button_index]?.actions[this.action_index]?.mode;e!==t.detail.value&&(this.config.buttons[this.button_index].actions[this.action_index].mode=t.detail.value,this.requestUpdate("config"),this._dirty=!0)}_toggleEnabled(){this.config&&!this.is_new&&(this.config.enabled=!this.config.enabled,this.hass.callWS({type:$t("config/enabled"),enabled:this.config.enabled,config_id:this.config.id}),this.requestUpdate("config"))}_fixMismatch(){this.config&&this.hass.callWS({type:$t("config/save"),config:{...this.config,blueprint:this.config.blueprint.id},fix_mismatch:!0}).then(()=>{this._errors=void 0,this.config.is_mismatch=!1,this.requestUpdate(),At(this,"Mismatch Fixed")})}_deleteConfirm(){this.is_new||kt(this,"switch-manager-dialog-confirm",()=>Promise.resolve().then(function(){return jt}),{title:"Delete switch?",text:`${this.config?.name} will be permanently deleted.`,confirmText:"Delete",dismissText:"Cancel",confirm:()=>{this.hass.callWS({type:$t("config/delete"),config_id:this.config.id.toString()}).then(()=>Ct(xt()))},confirmation:!0,destructive:!0})}_showIdentifierAutoDiscoveryDialog(t=!1){kt(this,"switch-manager-dialog-identifier-auto-discovery",()=>Promise.resolve().then(function(){return Zt}),{switch_id:this.config?.id,identifier:this.config?.identifier,blueprint:this.blueprint,update:e=>{this.config.identifier=e.identifier,this._dirty=!0,this.requestUpdate(),t&&e.identifier&&this._save()},onClose:()=>{}})}_showRenameDialog(){kt(this,"switch-manager-dialog-rename-switch",()=>Promise.resolve().then(function(){return Kt}),{config:this.config,update:t=>{this.config.name=t.name,this._dirty=!0,this.requestUpdate()},onClose:()=>{this.is_new&&this._showIdentifierAutoDiscoveryDialog()}})}_showCopyFromDialog(){kt(this,"switch-manager-dialog-copy-from",()=>Promise.resolve().then(function(){return Gt}),{blueprint_id:this.config?.blueprint?.id,current_switch_id:this.config?.id,update:t=>{this.config.buttons=t.buttons,!1!==t.variables&&(this.config.variables=t.variables),this._dirty=!0,this._updateSequence(),this._drawSVG()},onClose:()=>{}})}_showVariablesEditorDialog(){kt(this,"switch-manager-dialog-variables-editor",()=>Promise.resolve().then(function(){return Yt}),{config:this.config,update:t=>{this.config.variables=t.variables,this._dirty=!0,this.requestUpdate()},onClose:()=>{}})}static{this.styles=n` @keyframes pressed { to { fill: #3ff17975; @@ -919,7 +954,517 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro ha-fab.blocked { bottom: calc(-80px - env(safe-area-inset-bottom)); } - `}};t([pt({attribute:!1})],Tt.prototype,"hass",void 0),t([pt({type:Boolean})],Tt.prototype,"narrow",void 0),t([pt({attribute:!1})],Tt.prototype,"panel",void 0),t([pt({attribute:!1})],Tt.prototype,"route",void 0),t([pt({attribute:!1})],Tt.prototype,"params",void 0),t([pt({attribute:!1})],Tt.prototype,"blueprint",void 0),t([pt({attribute:!1})],Tt.prototype,"config",void 0),t([pt({type:Boolean})],Tt.prototype,"disabled",void 0),t([ut()],Tt.prototype,"_subscribedMonitor",void 0),t([ut()],Tt.prototype,"_reloadListener",void 0),t([ut()],Tt.prototype,"sequence",void 0),t([ut()],Tt.prototype,"button_index",void 0),t([ut()],Tt.prototype,"action_index",void 0),t([ut()],Tt.prototype,"is_new",void 0),t([ut()],Tt.prototype,"_is_yaml",void 0),t([ut()],Tt.prototype,"_dirty",void 0),t([ut()],Tt.prototype,"_debug",void 0),t([ut()],Tt.prototype,"_block_save",void 0),t([ut()],Tt.prototype,"_errors",void 0),t([mt("#switch-svg")],Tt.prototype,"svg",void 0),t([mt("switch-manager-button-actions")],Tt.prototype,"button_actions",void 0),t([mt("ha-yaml-editor")],Tt.prototype,"_yamlEditor",void 0),Tt=t([lt("switch-manager-switch-editor")],Tt);const Ot=["ha-automation-action","ha-service-control","ha-selector","ha-yaml-editor","ha-card","ha-fab","ha-alert","ha-svg-icon","ha-icon-button","ha-menu-button"];let Nt=class extends nt{constructor(){super(...arguments),this.narrow=!1,this._params={},this._componentsLoaded=!1}set route(t){this._route=t;const e=t.path.split("/");"new"===e[1]?this._params={action:"new",blueprint:e[2]}:"edit"===e[1]?this._params={action:"edit",id:e[2]}:this._params={}}get route(){return this._route}render(){return this._componentsLoaded?"action"in this._params?I` + `}};t([gt({attribute:!1})],Ut.prototype,"hass",void 0),t([gt({type:Boolean})],Ut.prototype,"narrow",void 0),t([gt({attribute:!1})],Ut.prototype,"panel",void 0),t([gt({attribute:!1})],Ut.prototype,"route",void 0),t([gt({attribute:!1})],Ut.prototype,"params",void 0),t([gt({attribute:!1})],Ut.prototype,"blueprint",void 0),t([gt({attribute:!1})],Ut.prototype,"config",void 0),t([gt({type:Boolean})],Ut.prototype,"disabled",void 0),t([_t()],Ut.prototype,"_subscribedMonitor",void 0),t([_t()],Ut.prototype,"_reloadListener",void 0),t([_t()],Ut.prototype,"sequence",void 0),t([_t()],Ut.prototype,"button_index",void 0),t([_t()],Ut.prototype,"action_index",void 0),t([_t()],Ut.prototype,"is_new",void 0),t([_t()],Ut.prototype,"_is_yaml",void 0),t([_t()],Ut.prototype,"_dirty",void 0),t([_t()],Ut.prototype,"_debug",void 0),t([_t()],Ut.prototype,"_block_save",void 0),t([_t()],Ut.prototype,"_errors",void 0),t([vt("#switch-svg")],Ut.prototype,"svg",void 0),t([vt("switch-manager-button-actions")],Ut.prototype,"button_actions",void 0),t([vt("ha-yaml-editor")],Ut.prototype,"_yamlEditor",void 0),Ut=t([dt("switch-manager-switch-editor")],Ut);const qt="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z",Nt="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z";let Ot=class extends ht{constructor(){super(...arguments),this.narrow=!1,this.params={},this._id="custom-remote",this._name="Custom Remote",this._service="Zigbee2MQTT",this._eventType="mqtt",this._identifierKey="",this._mqttTopicFormat="zigbee2mqtt/+/action",this._mqttSubTopics=!1,this._imageWidth=0,this._imageHeight=0,this._imageChanged=!1,this._buttons=[],this._selectedButton=0,this._saving=!1,this._loading=!1,this._isEdit=!1,this._canUndo=!1,this._canRedo=!1,this._dirty=!1,this._undoStack=[],this._redoStack=[],this._restoringHistory=!1,this._textHistoryPending=!1,this._leavePath="",this._boundPointerMove=t=>this._onPointerMove(t),this._boundPointerUp=()=>this._onPointerUp(),this._boundBeforeUnload=t=>this._onBeforeUnload(t),this._boundPopState=()=>this._onPopState(),this._boundKeyDown=t=>this._onKeyDown(t)}connectedCallback(){super.connectedCallback(),this._leavePath=window.location.pathname,window.addEventListener("pointermove",this._boundPointerMove),window.addEventListener("pointerup",this._boundPointerUp),window.addEventListener("beforeunload",this._boundBeforeUnload),window.addEventListener("popstate",this._boundPopState),window.addEventListener("keydown",this._boundKeyDown),"blueprint-edit"===this.params?.action&&this.params.id?(this._isEdit=!0,this._loadForEdit(this.params.id)):this._baselineSnapshot=this._snapshot()}disconnectedCallback(){window.removeEventListener("pointermove",this._boundPointerMove),window.removeEventListener("pointerup",this._boundPointerUp),window.removeEventListener("beforeunload",this._boundBeforeUnload),window.removeEventListener("popstate",this._boundPopState),window.removeEventListener("keydown",this._boundKeyDown),this._historyDebounce&&clearTimeout(this._historyDebounce),super.disconnectedCallback()}render(){if(this._loading)return j`
Loading blueprint…
`;const t=this._buttons[this._selectedButton];return j` +
+ +
${this._isEdit?"Edit Blueprint":"Create Blueprint"}
+
+ + +
+
v${this.panel.config.version}
+
+
+
+
+

Remote Preview

+

+ Drag buttons to move them. Use the handle on the selected button to resize. +

+ + ${this._imageDataUrl?j` +
+ + + ${this._buttons.map((t,e)=>this._renderButtonShape(t,e))} + +
+
+ ${this._imageWidth}px x ${this._imageHeight}px +
+ `:j`
Upload an image to start.
`} +
+ +
+

Blueprint Details

+ ${this._error?j`${this._error}`:W} +
+ ${this._isEdit?j` + + `:this._textField("File id",this._id,t=>this._id=this._slug(t))} + ${this._textField("Name",this._name,t=>{this._name=t,this._isEdit||this._id&&"custom-remote"!==this._id||(this._id=this._slug(t))})} + ${this._textField("Service",this._service,t=>this._service=t)} + + ${"mqtt"===this._eventType?j` + ${this._textField("MQTT topic format",this._mqttTopicFormat,t=>this._mqttTopicFormat=t)} + + `:this._textField("Identifier key",this._identifierKey,t=>this._identifierKey=t)} +
+ +
+

Buttons

+
+ + +
+
+ + ${this._buttons.length?j` +
+ ${this._buttons.map((t,e)=>j` + + `)} +
+ ${t?this._renderButtonEditor(t,this._selectedButton):W} + `:j`

Add buttons after uploading an image.

`} + +
+ + +
+
+
+
+ `}_renderButtonShape(t,e){const i=e===this._selectedButton,s=i?"button selected":"button";if("path"===t.shape)return t.d&&this._isValidPath(t.d)?I` + this._startDrag(t,e,"move")} + > + `:W;if("circle"===t.shape)return I` + this._startDrag(t,e,"move")} + > + ${i?I` + this._startDrag(t,e,"resize")} + > + `:W} + `;const o=t.height||t.width;return I` + this._startDrag(t,e,"move")} + > + ${i?I` + this._startDrag(t,e,"resize")} + > + `:W} + `}_renderButtonEditor(t,e){return j` +
+
+

Button ${e+1}

+ +
+
+ + ${"path"===t.shape?W:j` + ${this._numberField("X",t.x,t=>this._updateButton(e,{x:t}))} + ${this._numberField("Y",t.y,t=>this._updateButton(e,{y:t}))} + ${this._numberField("circle"===t.shape?"Radius":"Width",t.width,t=>this._updateButton(e,{width:t}))} + ${"rectangle"===t.shape?this._numberField("Height",t.height||t.width,t=>this._updateButton(e,{height:t})):W} + `} +
+ ${"path"===t.shape?j` + + ${t.d&&!this._isValidPath(t.d)?j`

This path is not valid SVG. It must start with M/m and contain only path commands and numbers.

`:j`

Drag the shape in the preview to move it. Coordinates use the image's pixel space.

`} + `:W} + +

Button Conditions

+ ${this._renderConditions(t.conditions,t=>this._updateButton(e,{conditions:t}))} + +
+

Actions

+ +
+ ${t.actions.map((t,i)=>this._renderActionEditor(e,t,i))} +
+ `}_renderActionEditor(t,e,i){return j` +
+
+ ${this._textField("Action title",e.title,e=>this._updateAction(t,i,{title:e}))} + +
+ ${this._renderConditions(e.conditions,e=>this._updateAction(t,i,{conditions:e}))} +
+ `}_renderConditions(t,e){return j` +
+ ${t.map((i,s)=>j` +
+ ${this._textField("Key",i.key,o=>{const r=[...t];r[s]={...i,key:o},e(r)})} + ${this._textField("Value",i.value,o=>{const r=[...t];r[s]={...i,value:o},e(r)})} + +
+ `)} + +
+ `}_textField(t,e,i){return j` + + `}_numberField(t,e,i){return j` + + `}async _loadForEdit(t){this._loading=!0,this._error=void 0;try{const e=(await this.hass.callWS({type:$t("blueprints"),blueprint_id:t})).blueprint;if(!e)throw new Error("Blueprint not found");if(!e.editable)throw new Error("Bundled blueprints cannot be edited");if(this._id=e.id,this._name=e.name,this._service=e.service,this._eventType=e.event_type,this._identifierKey=e.identifier_key||"",this._mqttTopicFormat=e.mqtt_topic_format||"",this._mqttSubTopics=!!e.mqtt_sub_topics,this._buttons=e.buttons.map(t=>this._buttonFromBlueprint(t)),e.has_image){const t=await this._fetchImageAsDataUrl(wt(`${e.id}.png`)),i=await this._loadImage(t);this._imageDataUrl=t,this._imageWidth=i.width,this._imageHeight=i.height,this._imageChanged=!1}this._baselineSnapshot=this._snapshot(),this._clearHistory()}catch(t){this._error=t.message||"Unable to load blueprint."}finally{this._loading=!1}}_buttonFromBlueprint(t){const e=!!t.d,i=!e&&null!=t.height&&t.height>0,s=!e&&!i&&(t.width??0)>0;return{shape:e?"path":s?"circle":"rectangle",x:t.x??0,y:t.y??0,width:t.width??30,height:i?t.height:t.width??30,d:e?t.d:void 0,conditions:this._conditionsFromBlueprint(t.conditions),actions:t.actions.map(t=>({title:t.title,conditions:this._conditionsFromBlueprint(t.conditions)}))}}_conditionsFromBlueprint(t){return Array.isArray(t)?t.filter(t=>!!t&&"object"==typeof t&&"key"in t).map(t=>({key:String(t.key),value:String(t.value)})):[]}async _fetchImageAsDataUrl(t){const e=await fetch(t);if(!e.ok)throw new Error("Unable to load blueprint image");const i=await e.blob();return new Promise((t,e)=>{const s=new FileReader;s.onload=()=>t(String(s.result)),s.onerror=()=>e(s.error),s.readAsDataURL(i)})}async _imageSelected(t){const e=t.target.files?.[0];if(e){this._recordHistory();try{const t=await this._readFile(e),i=await this._loadImage(t),s=800,o=500,r=Math.min(1,s/i.width,o/i.height),n=Math.max(1,Math.round(i.width*r)),a=Math.max(1,Math.round(i.height*r)),c=document.createElement("canvas");c.width=n,c.height=a,c.getContext("2d").drawImage(i,0,0,n,a),this._imageDataUrl=c.toDataURL("image/png"),this._imageWidth=n,this._imageHeight=a,this._imageChanged=!0,this._buttons.length||this._addButton()}catch(t){At(this,t.message||"Unable to load image")}}}_readFile(t){return new Promise((e,i)=>{const s=new FileReader;s.onload=()=>e(String(s.result)),s.onerror=()=>i(s.error),s.readAsDataURL(t)})}_loadImage(t){return new Promise((e,i)=>{const s=new Image;s.onload=()=>e(s),s.onerror=()=>i(new Error("Unable to read image")),s.src=t})}_svgPoint(t,e,i){const s=t.createSVGPoint();s.x=e,s.y=i;const o=t.getScreenCTM();if(!o)return{x:0,y:0};const r=s.matrixTransform(o.inverse());return{x:r.x,y:r.y}}_startDrag(t,e,i){t.preventDefault(),t.stopPropagation(),this._recordHistory(),this._selectedButton=e;const s=t.currentTarget.ownerSVGElement;if(!s)return;t.currentTarget.setPointerCapture?.(t.pointerId);const o=this._svgPoint(s,t.clientX,t.clientY);this._drag={idx:e,mode:i,start:o,origin:{...this._buttons[e],actions:this._buttons[e].actions.map(t=>({...t,conditions:[...t.conditions]})),conditions:[...this._buttons[e].conditions]}}}_onPointerMove(t){if(!this._drag)return;const e=this.renderRoot.querySelector(".preview svg");if(!e)return;const i=this._svgPoint(e,t.clientX,t.clientY),{idx:s,mode:o,start:r,origin:n}=this._drag,a=i.x-r.x,c=i.y-r.y;if("move"!==o){if("circle"===n.shape){const t=Math.max(8,Math.round(n.width+a));this._updateButton(s,{width:t})}else if("rectangle"===n.shape){const t=n.height||n.width;this._updateButton(s,{width:Math.max(10,Math.round(n.width+a)),height:Math.max(10,Math.round(t+c))})}}else"path"===n.shape?n.d&&this._updateButton(s,{d:this._translatePath(n.d,a,c)}):this._updateButton(s,{x:Math.max(0,Math.round(n.x+a)),y:Math.max(0,Math.round(n.y+c))})}_translatePath(t,e,i){const s=/([MmLlHhVvCcSsQqTtAaZz])([^MmLlHhVvCcSsQqTtAaZz]*)/g,o=/-?\d*\.?\d+(?:[eE][-+]?\d+)?/g,r={M:["x","y"],L:["x","y"],T:["x","y"],H:["x"],V:["y"],C:["x","y","x","y","x","y"],S:["x","y","x","y"],Q:["x","y","x","y"],A:["o","o","o","o","o","x","y"],Z:[]};let n,a="",c=!0;for(;n=s.exec(t);){const t=n[1],s=t.toUpperCase(),h=t===s,l=r[s]||[],d=(n[2].match(o)||[]).map(Number);if(0===l.length)a+=t+" ";else{const o=d.map((t,o)=>{const r=l[o%l.length];if(h||c&&"M"===s&&o<2){if("x"===r)return t+e;if("y"===r)return t+i}return t});a+=t+o.join(" ")+" "}c=!1}return a.trim()}_isValidPath(t){return!(!t||!t.trim())&&(!!/^\s*[Mm]/.test(t)&&/^[MmLlHhVvCcSsQqTtAaZz0-9eE,.\s+-]+$/.test(t))}_changeShape(t,e){this._recordHistory();const i=this._buttons[t],s={shape:e};if("path"===e&&!i.d){const t=i.x||Math.round(this._imageWidth/2),e=i.y||Math.round(this._imageHeight/2),o=i.width||15;s.d=`M ${t},${e} m -${o},0 a ${o},${o} 0 1,0 ${2*o},0 a ${o},${o} 0 1,0 -${2*o},0`}this._updateButton(t,s)}_onPointerUp(){this._drag=void 0}_cloneButton(t,e=20){return{shape:t.shape,x:t.x+e,y:t.y+e,width:t.width,height:t.height,d:t.d&&"path"===t.shape?this._translatePath(t.d,e,e):t.d,conditions:t.conditions.map(t=>({...t})),actions:t.actions.map(t=>({title:t.title,conditions:t.conditions.map(t=>({...t}))}))}}_addButton(){this._recordHistory();const t=Math.max(30,Math.round(Math.min(this._imageWidth||120,this._imageHeight||120)/8)),e={shape:"rectangle",x:Math.max(0,Math.round((this._imageWidth-t)/2)),y:Math.max(0,Math.round((this._imageHeight-t)/2)),width:t,height:t,conditions:[],actions:[{title:"press",conditions:[]}]};this._buttons=[...this._buttons,e],this._selectedButton=this._buttons.length-1}_copyPreviousButton(){this._recordHistory();const t=this._selectedButton>0?this._selectedButton-1:this._buttons.length-1;if(t<0||!this._buttons[t])return void At(this,"No previous button to copy");const e=this._cloneButton(this._buttons[t]);this._buttons=[...this._buttons,e],this._selectedButton=this._buttons.length-1,At(this,`Copied button ${t+1}`)}_removeButton(t){this._recordHistory(),this._buttons=this._buttons.filter((e,i)=>i!==t),this._selectedButton=Math.max(0,Math.min(this._selectedButton,this._buttons.length-1))}_updateButton(t,e){this._buttons=this._buttons.map((i,s)=>s===t?{...i,...e}:i)}_addAction(t){this._recordHistory();const e=this._buttons[t];this._updateButton(t,{actions:[...e.actions,{title:"press",conditions:[]}]})}_removeAction(t,e){this._recordHistory();const i=this._buttons[t];this._updateButton(t,{actions:i.actions.filter((t,i)=>i!==e)})}_updateAction(t,e,i){const s=this._buttons[t];this._updateButton(t,{actions:s.actions.map((t,s)=>s===e?{...t,...i}:t)})}_buildBlueprint(){const t=this._buttons.map(t=>{const e={conditions:this._cleanConditions(t.conditions),actions:t.actions.map(t=>({title:t.title.trim(),conditions:this._cleanConditions(t.conditions)}))};return this._buttons.length>1&&("path"===t.shape?t.d&&(e.d=t.d.trim()):(e.x=t.x,e.y=t.y,e.width=t.width,"rectangle"===t.shape&&(e.height=t.height||t.width))),e}),e={name:this._name.trim(),service:this._service.trim(),event_type:this._eventType.trim(),buttons:t};return"mqtt"===this._eventType?(this._mqttTopicFormat.trim()&&(e.mqtt_topic_format=this._mqttTopicFormat.trim()),this._mqttSubTopics&&(e.mqtt_sub_topics=!0)):e.identifier_key=this._identifierKey.trim(),e}_cleanConditions(t){return t.filter(t=>t.key.trim()&&t.value.trim()).map(t=>({key:t.key.trim(),value:t.value.trim()}))}async _save(){if(this._error=void 0,this._imageDataUrl)if(this._buttons.length)if(this._buttons.some(t=>!t.actions.length||t.actions.some(t=>!t.title.trim())))this._error="Each button needs at least one titled action.";else if(this._buttons.some(t=>!("path"!==t.shape||t.d&&this._isValidPath(t.d))))this._error="One or more custom path buttons have an invalid SVG path.";else{this._saving=!0;try{const t={id:this._id,blueprint:this._buildBlueprint(),overwrite:this._isEdit};this._isEdit&&!this._imageChanged||(t.image=this._imageDataUrl);const e=await this.hass.callWS({type:$t("blueprint/save"),payload:t});At(this,this._isEdit?"Blueprint Updated":"Blueprint Saved"),this._baselineSnapshot=this._snapshot(),this._clearHistory(),Ct(xt(`new/${e.blueprint_id}`))}catch(t){this._error=t.message||"Unable to save blueprint."}finally{this._saving=!1}}else this._error="Add at least one button before saving.";else this._error="Upload a remote image before saving."}_snapshot(){return{id:this._id,name:this._name,service:this._service,eventType:this._eventType,identifierKey:this._identifierKey,mqttTopicFormat:this._mqttTopicFormat,mqttSubTopics:this._mqttSubTopics,imageDataUrl:this._imageDataUrl,imageWidth:this._imageWidth,imageHeight:this._imageHeight,imageChanged:this._imageChanged,buttons:JSON.parse(JSON.stringify(this._buttons)),selectedButton:this._selectedButton}}_restoreSnapshot(t){this._restoringHistory=!0,this._id=t.id,this._name=t.name,this._service=t.service,this._eventType=t.eventType,this._identifierKey=t.identifierKey,this._mqttTopicFormat=t.mqttTopicFormat,this._mqttSubTopics=t.mqttSubTopics,this._imageDataUrl=t.imageDataUrl,this._imageWidth=t.imageWidth,this._imageHeight=t.imageHeight,this._imageChanged=t.imageChanged,this._buttons=JSON.parse(JSON.stringify(t.buttons)),this._selectedButton=t.selectedButton,this._restoringHistory=!1}_syncHistoryFlags(){this._canUndo=this._undoStack.length>0,this._canRedo=this._redoStack.length>0}_clearHistory(){this._undoStack=[],this._redoStack=[],this._syncHistoryFlags(),this._updateDirty()}_updateDirty(){this._dirty=JSON.stringify(this._snapshot())!==JSON.stringify(this._baselineSnapshot)}_recordHistory(){this._restoringHistory||this._drag||(this._undoStack.push(this._snapshot()),this._undoStack.length>50&&this._undoStack.shift(),this._redoStack=[],this._updateDirty(),this._syncHistoryFlags())}_recordHistoryForText(){this._textHistoryPending||(this._recordHistory(),this._textHistoryPending=!0),this._historyDebounce&&clearTimeout(this._historyDebounce),this._historyDebounce=setTimeout(()=>{this._textHistoryPending=!1},800)}_undo(){if(!this._undoStack.length)return;this._redoStack.push(this._snapshot());const t=this._undoStack.pop();this._restoreSnapshot(t),this._updateDirty(),this._syncHistoryFlags()}_redo(){if(!this._redoStack.length)return;this._undoStack.push(this._snapshot());const t=this._redoStack.pop();this._restoreSnapshot(t),this._updateDirty(),this._syncHistoryFlags()}_onBeforeUnload(t){this._dirty&&(t.preventDefault(),t.returnValue="")}_onPopState(){this._dirty&&(history.pushState(null,"",this._leavePath),this._confirmDiscard(()=>Ct(xt())))}_onKeyDown(t){if(!t.ctrlKey&&!t.metaKey)return;const e=t.target;"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&("z"===t.key||"Z"===t.key?(t.preventDefault(),t.shiftKey?this._redo():this._undo()):"y"!==t.key&&"Y"!==t.key||(t.preventDefault(),this._redo()))}_confirmDiscard(t){this._dirty?kt(this,"switch-manager-dialog-confirm",()=>Promise.resolve().then(function(){return jt}),{title:"Discard unsaved changes?",text:"Your blueprint changes will be lost if you leave without saving.",confirmText:"Discard",dismissText:"Stay",destructive:!0,confirm:()=>{this._clearHistory(),t()}}):t()}_slug(t){return t.toLowerCase().trim().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)}_back(){this._confirmDiscard(()=>Ct(xt()))}static{this.styles=n` + :host { + display: block; + } + .loading { + padding: 24px; + color: var(--secondary-text-color); + } + .toolbar { + display: flex; + align-items: center; + height: var(--header-height, 56px); + box-sizing: border-box; + padding: 0 12px; + background-color: var(--app-header-background-color, var(--primary-color)); + color: var(--app-header-text-color, var(--text-primary-color, #fff)); + font-size: 20px; + font-weight: 400; + } + .main-title { + flex: 1; + margin: 0 16px; + } + .toolbar-actions { + display: flex; + align-items: center; + gap: 4px; + } + .version { + font-size: 14px; + opacity: 0.8; + } + .view { + display: block; + height: calc(100vh - var(--header-height, 56px)); + overflow-y: auto; + } + .grid { + display: grid; + grid-template-columns: minmax(280px, 1fr) minmax(320px, 520px); + gap: 16px; + padding: 16px; + } + .card { + background: var(--card-background-color, var(--ha-card-background, var(--secondary-background-color))); + border: 1px solid var(--divider-color); + border-radius: 12px; + padding: 16px; + box-sizing: border-box; + } + h2, h3 { + margin: 0 0 12px; + font-weight: 500; + } + .hint, .dimensions { + color: var(--secondary-text-color); + font-size: 0.9rem; + } + .file-picker { + display: inline-block; + margin: 8px 0 16px; + cursor: pointer; + } + .preview { + display: flex; + justify-content: center; + align-items: center; + min-height: 320px; + touch-action: none; + } + svg { + max-width: 100%; + max-height: 520px; + overflow: visible; + user-select: none; + } + svg image { + filter: drop-shadow(0px 0px 8px #00000033); + pointer-events: none; + } + svg .button { + fill: #00000000; + stroke: #00adff80; + stroke-width: 3; + cursor: grab; + touch-action: none; + } + svg .button.selected { + fill: #6bd3ff75; + stroke: #0082e9; + cursor: grabbing; + } + svg .resize-handle { + fill: #0082e9; + stroke: #fff; + stroke-width: 2; + cursor: nwse-resize; + touch-action: none; + } + .empty-preview { + min-height: 320px; + display: flex; + align-items: center; + justify-content: center; + color: var(--secondary-text-color); + border: 1px dashed var(--divider-color); + border-radius: 10px; + } + .fields { + display: grid; + gap: 12px; + } + .fields.two { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + label { + display: flex; + flex-direction: column; + gap: 4px; + color: var(--secondary-text-color); + font-size: 0.9rem; + } + label.checkbox { + flex-direction: row; + align-items: center; + color: var(--primary-text-color); + } + input, select, textarea { + box-sizing: border-box; + width: 100%; + border: 1px solid var(--divider-color, rgba(127, 127, 127, 0.3)); + border-radius: 6px; + background: var(--primary-background-color); + color: var(--primary-text-color); + font: inherit; + padding: 8px; + } + textarea { + font-family: var(--code-font-family, monospace); + font-size: 0.85rem; + resize: vertical; + } + .path-field { + margin-top: 12px; + } + .path-error { + color: var(--error-color); + font-size: 0.85rem; + margin: 4px 0 0; + } + input:disabled { + opacity: 0.7; + } + .section-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + margin-top: 20px; + } + .section-header.compact { + margin: 12px 0; + } + .header-actions { + display: flex; + gap: 8px; + flex-wrap: wrap; + } + .button-tabs { + display: flex; + gap: 8px; + flex-wrap: wrap; + margin: 12px 0; + } + button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + border: 1px solid var(--divider-color); + border-radius: 6px; + background: var(--secondary-background-color); + color: var(--primary-text-color); + padding: 8px 12px; + font: inherit; + cursor: pointer; + } + button.selected, button.primary { + background: var(--primary-color); + color: var(--text-primary-color, #fff); + border-color: var(--primary-color); + } + button.danger { + color: var(--error-color); + } + button.icon-only { + padding: 8px; + } + button:disabled { + opacity: 0.6; + cursor: default; + } + .conditions { + display: grid; + gap: 8px; + margin-bottom: 12px; + } + .condition { + display: grid; + grid-template-columns: 1fr 1fr auto; + gap: 8px; + align-items: end; + } + .action-editor { + border: 1px solid var(--divider-color); + border-radius: 8px; + padding: 12px; + margin: 8px 0; + } + .actions { + display: flex; + justify-content: flex-end; + gap: 8px; + margin-top: 24px; + } + ha-alert { + display: block; + margin: 0 0 12px; + } + ha-svg-icon { + width: 18px; + height: 18px; + } + @media (max-width: 900px) { + .grid { + grid-template-columns: 1fr; + } + .fields.two, .condition { + grid-template-columns: 1fr; + } + } + `}};t([gt({attribute:!1})],Ot.prototype,"hass",void 0),t([gt({type:Boolean})],Ot.prototype,"narrow",void 0),t([gt({attribute:!1})],Ot.prototype,"panel",void 0),t([gt({attribute:!1})],Ot.prototype,"route",void 0),t([gt({attribute:!1})],Ot.prototype,"params",void 0),t([_t()],Ot.prototype,"_id",void 0),t([_t()],Ot.prototype,"_name",void 0),t([_t()],Ot.prototype,"_service",void 0),t([_t()],Ot.prototype,"_eventType",void 0),t([_t()],Ot.prototype,"_identifierKey",void 0),t([_t()],Ot.prototype,"_mqttTopicFormat",void 0),t([_t()],Ot.prototype,"_mqttSubTopics",void 0),t([_t()],Ot.prototype,"_imageDataUrl",void 0),t([_t()],Ot.prototype,"_imageWidth",void 0),t([_t()],Ot.prototype,"_imageHeight",void 0),t([_t()],Ot.prototype,"_imageChanged",void 0),t([_t()],Ot.prototype,"_buttons",void 0),t([_t()],Ot.prototype,"_selectedButton",void 0),t([_t()],Ot.prototype,"_saving",void 0),t([_t()],Ot.prototype,"_loading",void 0),t([_t()],Ot.prototype,"_error",void 0),t([_t()],Ot.prototype,"_isEdit",void 0),t([_t()],Ot.prototype,"_canUndo",void 0),t([_t()],Ot.prototype,"_canRedo",void 0),Ot=t([dt("switch-manager-blueprint-editor")],Ot);const zt=["ha-automation-action","ha-service-control","ha-selector","ha-yaml-editor","ha-card","ha-fab","ha-alert","ha-svg-icon","ha-icon-button","ha-menu-button"];let Rt=class extends ht{constructor(){super(...arguments),this.narrow=!1,this._params={},this._componentsLoaded=!1}set route(t){this._route=t;const e=t.path.split("/");"new"===e[1]?this._params={action:"new",blueprint:e[2]}:"edit"===e[1]?this._params={action:"edit",id:e[2]}:"blueprint"===e[1]&&"new"===e[2]?this._params={action:"blueprint-new"}:"blueprint"===e[1]&&"edit"===e[2]&&e[3]?this._params={action:"blueprint-edit",id:e[3]}:this._params={}}get route(){return this._route}render(){return this._componentsLoaded?"blueprint-new"===this._params.action||"blueprint-edit"===this._params.action?j` + + `:"action"in this._params?j` - `:I` + `:j` - `:I`
Loading…
`}async firstUpdated(){this.hass.loadFragmentTranslation("config"),this.hass.loadBackendTranslation("title"),this.hass.loadBackendTranslation("device_automation"),this.hass.loadBackendTranslation("config"),this.hass.loadBackendTranslation("services"),this.hass.loadBackendTranslation("selector"),this.hass.loadBackendTranslation("entity_component"),this._applyTheme();try{await(async t=>{const e=t||vt;try{if(e.every(t=>customElements.get(t)))return;await Promise.race([customElements.whenDefined("partial-panel-resolver"),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout waiting for partial-panel-resolver")),1e4))]);const t=document.createElement("partial-panel-resolver");if(!t)throw new Error("Failed to create partial-panel-resolver element");if(t.hass={panels:[{url_path:"tmp",component_name:"config"}]},"function"!=typeof t._updateRoutes)throw new Error("partial-panel-resolver does not have _updateRoutes method");if(t._updateRoutes(),!t.routerOptions?.routes?.tmp?.load)throw new Error("Failed to create tmp route in partial-panel-resolver");await Promise.race([t.routerOptions.routes.tmp.load(),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout loading tmp route")),1e4))]),await Promise.race([customElements.whenDefined("ha-panel-config"),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout waiting for ha-panel-config")),1e4))]);const i=document.createElement("ha-panel-config");if(!i)throw new Error("Failed to create ha-panel-config element");if(!i.routerOptions?.routes?.automation?.load)throw new Error("ha-panel-config does not have automation route");await Promise.race([i.routerOptions.routes.automation.load(),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout loading automation components")),1e4))]);const s=e.filter(t=>!customElements.get(t));if(s.length>0)throw new Error(`Failed to load components: ${s.join(", ")}`)}catch(t){console.error("Error loading Home Assistant form components:",t);try{if(window.customElements&&window.customElements.get("home-assistant")){console.log("Attempting fallback loading method for HA components");const t=new CustomEvent("ha-request-load-components",{detail:{components:e},bubbles:!0,composed:!0});document.dispatchEvent(t)}}catch(t){console.error("Fallback loading method failed:",t)}}})(Ot)}catch(t){console.error("switch_manager: loadHaComponents failed",t)}this._componentsLoaded=!0}updated(t){super.updated(t);const e=t.get("hass");e&&e.themes!==this.hass.themes&&this._applyTheme()}provideHass(t){t.hass=this.hass}_applyTheme(){this.style.backgroundColor="var(--primary-background-color)",this.style.color="var(--primary-text-color)",this.style.fontFamily="var(--mdc-typography-headline6-font-family, var(--mdc-typography-font-family, Roboto, sans-serif))"}static{this.styles=a` + `:j`
Loading…
`}async firstUpdated(){this.hass.loadFragmentTranslation("config"),this.hass.loadBackendTranslation("title"),this.hass.loadBackendTranslation("device_automation"),this.hass.loadBackendTranslation("config"),this.hass.loadBackendTranslation("services"),this.hass.loadBackendTranslation("selector"),this.hass.loadBackendTranslation("entity_component"),this._applyTheme();try{await(async t=>{const e=t||bt;try{if(e.every(t=>customElements.get(t)))return;await Promise.race([customElements.whenDefined("partial-panel-resolver"),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout waiting for partial-panel-resolver")),1e4))]);const t=document.createElement("partial-panel-resolver");if(!t)throw new Error("Failed to create partial-panel-resolver element");if(t.hass={panels:[{url_path:"tmp",component_name:"config"}]},"function"!=typeof t._updateRoutes)throw new Error("partial-panel-resolver does not have _updateRoutes method");if(t._updateRoutes(),!t.routerOptions?.routes?.tmp?.load)throw new Error("Failed to create tmp route in partial-panel-resolver");await Promise.race([t.routerOptions.routes.tmp.load(),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout loading tmp route")),1e4))]),await Promise.race([customElements.whenDefined("ha-panel-config"),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout waiting for ha-panel-config")),1e4))]);const i=document.createElement("ha-panel-config");if(!i)throw new Error("Failed to create ha-panel-config element");if(!i.routerOptions?.routes?.automation?.load)throw new Error("ha-panel-config does not have automation route");await Promise.race([i.routerOptions.routes.automation.load(),new Promise((t,e)=>setTimeout(()=>e(new Error("Timeout loading automation components")),1e4))]);const s=e.filter(t=>!customElements.get(t));if(s.length>0)throw new Error(`Failed to load components: ${s.join(", ")}`)}catch(t){console.error("Error loading Home Assistant form components:",t);try{if(window.customElements&&window.customElements.get("home-assistant")){console.log("Attempting fallback loading method for HA components");const t=new CustomEvent("ha-request-load-components",{detail:{components:e},bubbles:!0,composed:!0});document.dispatchEvent(t)}}catch(t){console.error("Fallback loading method failed:",t)}}})(zt)}catch(t){console.error("switch_manager: loadHaComponents failed",t)}this._componentsLoaded=!0}updated(t){super.updated(t);const e=t.get("hass");e&&e.themes!==this.hass.themes&&this._applyTheme()}provideHass(t){t.hass=this.hass}_applyTheme(){this.style.backgroundColor="var(--primary-background-color)",this.style.color="var(--primary-text-color)",this.style.fontFamily="var(--mdc-typography-headline6-font-family, var(--mdc-typography-font-family, Roboto, sans-serif))"}static{this.styles=n` :host { display: block; } @@ -942,13 +1487,13 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro padding: 24px; color: var(--secondary-text-color); } - `}};t([pt({attribute:!1})],Nt.prototype,"hass",void 0),t([pt({type:Boolean})],Nt.prototype,"narrow",void 0),t([pt({attribute:!1})],Nt.prototype,"panel",void 0),t([ut()],Nt.prototype,"_params",void 0),t([ut()],Nt.prototype,"_componentsLoaded",void 0),t([pt({attribute:!1})],Nt.prototype,"route",null),Nt=t([lt("switch-manager-panel")],Nt);let Ut=class extends nt{showDialog(t){this._params=t}closeDialog(){this._params=void 0}render(){return this._params?I` + `}};t([gt({attribute:!1})],Rt.prototype,"hass",void 0),t([gt({type:Boolean})],Rt.prototype,"narrow",void 0),t([gt({attribute:!1})],Rt.prototype,"panel",void 0),t([_t()],Rt.prototype,"_params",void 0),t([_t()],Rt.prototype,"_componentsLoaded",void 0),t([gt({attribute:!1})],Rt.prototype,"route",null),Rt=t([dt("switch-manager-panel")],Rt);let Ft=class extends ht{showDialog(t){this._params=t}closeDialog(){this._params=void 0}render(){return this._params?j`
${this._params.text||""}
- ${this._params.prompt?I`
- `:I``}_dismiss(){this._params?.cancel?.(),this.closeDialog()}_confirm(){this._params?.confirm?.(),this.closeDialog()}static{this.styles=a` + `:j``}_dismiss(){this._params?.cancel?.(),this.closeDialog()}_confirm(){this._params?.confirm?.(),this.closeDialog()}static{this.styles=n` .text-input { width: 100%; box-sizing: border-box; @@ -977,7 +1522,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro color: var(--primary-text-color); font: inherit; } - `}};t([ut()],Ut.prototype,"_params",void 0),Ut=t([lt("switch-manager-dialog-confirm")],Ut);var qt=Object.freeze({__proto__:null,get SwitchManagerDialogConfirm(){return Ut}});let zt=class extends nt{constructor(){super(...arguments),this._identifier="",this._discovered=[],this._listening=!1}showDialog(t){this._params=t,this._identifier=t.identifier||"",this._discovered=[],this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._startDiscovery()}closeDialog(){this._stopDiscovery(),this._params?.onClose?.(),this._params=void 0}async _startDiscovery(){const t=this._params.blueprint;if(t){this._listening=!0;try{this._unsubscribe=await this.hass.connection.subscribeMessage(t=>{t.identifier&&!this._discovered.includes(t.identifier)&&(this._discovered=[...this._discovered,t.identifier])},{type:wt("blueprints/auto_discovery"),blueprint_id:t.id})}catch{this._listening=!1}}}_stopDiscovery(){this._unsubscribe?.(),this._unsubscribe=void 0,this._listening=!1}render(){return this._params?I` + `}};t([_t()],Ft.prototype,"_params",void 0),Ft=t([dt("switch-manager-dialog-confirm")],Ft);var jt=Object.freeze({__proto__:null,get SwitchManagerDialogConfirm(){return Ft}});let It=class extends ht{constructor(){super(...arguments),this._identifier="",this._discovered=[],this._listening=!1}showDialog(t){this._params=t,this._identifier=t.identifier||"",this._discovered=[],this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._startDiscovery()}closeDialog(){this._stopDiscovery(),this._params?.onClose?.(),this._params=void 0}async _startDiscovery(){const t=this._params.blueprint;if(t){this._listening=!0;try{this._unsubscribe=await this.hass.connection.subscribeMessage(t=>{t.identifier&&!this._discovered.includes(t.identifier)&&(this._discovered=[...this._discovered,t.identifier])},{type:$t("blueprints/auto_discovery"),blueprint_id:t.id})}catch{this._listening=!1}}}_stopDiscovery(){this._unsubscribe?.(),this._unsubscribe=void 0,this._listening=!1}render(){return this._params?j` this._identifier=t.target.value} /> - ${this._params.blueprint?.mqtt_topic_format?I`
+ ${this._params.blueprint?.mqtt_topic_format?j`
MQTT Discovery Topic: ${this._params.blueprint.mqtt_topic_format} | MQTT Tool -
`:this._params.blueprint?.event_type?I`
+
`:this._params.blueprint?.event_type?j`
Event Type: ${this._params.blueprint.event_type} |
`:""} - ${this._listening?I` + ${this._listening?j`

Press a button on your switch to auto-discover its identifier...

- ${this._discovered.length?I` + ${this._discovered.length?j`
- ${this._discovered.map(t=>I` + ${this._discovered.map(t=>j`
this._selectIdentifier(t)} @@ -1031,7 +1576,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro - `:I``}_selectIdentifier(t){this._identifier=t}_save(){this._params?.update?.({identifier:this._identifier}),this.closeDialog()}static{this.styles=a` + `:j``}_selectIdentifier(t){this._identifier=t}_save(){this._params?.update?.({identifier:this._identifier}),this.closeDialog()}static{this.styles=n` .content { min-width: 300px; } @@ -1087,7 +1632,7 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro transform: rotate(360deg); } } - `}};t([ut()],zt.prototype,"_params",void 0),t([ut()],zt.prototype,"_identifier",void 0),t([ut()],zt.prototype,"_discovered",void 0),t([ut()],zt.prototype,"_listening",void 0),zt=t([lt("switch-manager-dialog-identifier-auto-discovery")],zt);var Rt=Object.freeze({__proto__:null,get SwitchManagerDialogIdentifierAutoDiscovery(){return zt}});let jt=class extends nt{constructor(){super(...arguments),this._name=""}showDialog(t){this._params=t,this._name=t.config?.name||""}closeDialog(){this._params?.onClose?.(),this._params=void 0}render(){return this._params?I` + `}};t([_t()],It.prototype,"_params",void 0),t([_t()],It.prototype,"_identifier",void 0),t([_t()],It.prototype,"_discovered",void 0),t([_t()],It.prototype,"_listening",void 0),It=t([dt("switch-manager-dialog-identifier-auto-discovery")],It);var Zt=Object.freeze({__proto__:null,get SwitchManagerDialogIdentifierAutoDiscovery(){return It}});let Wt=class extends ht{constructor(){super(...arguments),this._name=""}showDialog(t){this._params=t,this._name=t.config?.name||""}closeDialog(){this._params?.onClose?.(),this._params=void 0}render(){return this._params?j` Cancel - `:I``}_save(){this._name.trim()&&this._params?.update?.({name:this._name.trim()}),this.closeDialog()}static{this.styles=a` + `:j``}_save(){this._name.trim()&&this._params?.update?.({name:this._name.trim()}),this.closeDialog()}static{this.styles=n` .text-input { width: 100%; box-sizing: border-box; @@ -1115,10 +1660,10 @@ function t(t,e,i,s){var o,r=arguments.length,a=r<3?e:null===s?s=Object.getOwnPro outline: none; border-color: var(--primary-color); } - `}};t([ut()],jt.prototype,"_params",void 0),t([ut()],jt.prototype,"_name",void 0),jt=t([lt("switch-manager-dialog-rename-switch")],jt);var It=Object.freeze({__proto__:null,get SwitchManagerDialogRenameSwitch(){return jt}});let Bt=class extends nt{constructor(){super(...arguments),this._switches=[],this._copyVariables=!0}showDialog(t){this._params=t,this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._loadSwitches()}closeDialog(){this._params?.onClose?.(),this._params=void 0,this._switches=[]}async _loadSwitches(){const t=await this.hass.callWS({type:wt("copy_from_list"),blueprint_id:this._params.blueprint_id,skip_config_id:this._params.current_switch_id||""});this._switches=t.switches}render(){return this._params?I` + `}};t([_t()],Wt.prototype,"_params",void 0),t([_t()],Wt.prototype,"_name",void 0),Wt=t([dt("switch-manager-dialog-rename-switch")],Wt);var Kt=Object.freeze({__proto__:null,get SwitchManagerDialogRenameSwitch(){return Wt}});let Jt=class extends ht{constructor(){super(...arguments),this._switches=[],this._copyVariables=!0}showDialog(t){this._params=t,this.hass=this.parentElement?.hass||document.querySelector("home-assistant")?.hass,this._loadSwitches()}closeDialog(){this._params?.onClose?.(),this._params=void 0,this._switches=[]}async _loadSwitches(){const t=await this.hass.callWS({type:$t("copy_from_list"),blueprint_id:this._params.blueprint_id,skip_config_id:this._params.current_switch_id||""});this._switches=t.switches}render(){return this._params?j`
- ${0===this._switches.length?I`

No other switches with this blueprint found.

`:I` + ${0===this._switches.length?j`

No other switches with this blueprint found.

`:j`