Files
2026-07-08 10:43:39 -04:00

1066 lines
50 KiB
JavaScript

/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const t$2=globalThis,e$2=t$2.ShadowRoot&&(void 0===t$2.ShadyCSS||t$2.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$2=Symbol(),o$4=new WeakMap;let n$3 = class n{constructor(t,e,o){if(this._$cssResult$=true,o!==s$2)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$2&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o$4.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$4.set(s,t));}return t}toString(){return this.cssText}};const r$3=t=>new n$3("string"==typeof t?t:t+"",void 0,s$2),i$3=(t,...e)=>{const o=1===t.length?t[0]:e.reduce((e,s,o)=>e+(t=>{if(true===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(s)+t[o+1],t[0]);return new n$3(o,t,s$2)},S$1=(s,o)=>{if(e$2)s.adoptedStyleSheets=o.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of o){const o=document.createElement("style"),n=t$2.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=e.cssText,s.appendChild(o);}},c$2=e$2?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$3(e)})(t):t;
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const{is:i$2,defineProperty:e$1,getOwnPropertyDescriptor:h$1,getOwnPropertyNames:r$2,getOwnPropertySymbols:o$3,getPrototypeOf:n$2}=Object,a$1=globalThis,c$1=a$1.trustedTypes,l$1=c$1?c$1.emptyScript:"",p$1=a$1.reactiveElementPolyfillSupport,d$1=(t,s)=>t,u$1={toAttribute(t,s){switch(s){case Boolean:t=t?l$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,s){let i=t;switch(s){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}},f$1=(t,s)=>!i$2(t,s),b$1={attribute:true,type:String,converter:u$1,reflect:false,useDefault:false,hasChanged:f$1};Symbol.metadata??=Symbol("metadata"),a$1.litPropertyMetadata??=new WeakMap;let y$1 = class y 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,s=b$1){if(s.state&&(s.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=true),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e$1(this.prototype,t,h);}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h$1(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i);},configurable:true,enumerable:true}}static getPropertyOptions(t){return this.elementProperties.get(t)??b$1}static _$Ei(){if(this.hasOwnProperty(d$1("elementProperties")))return;const t=n$2(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties);}static finalize(){if(this.hasOwnProperty(d$1("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(d$1("properties"))){const t=this.properties,s=[...r$2(t),...o$3(t)];for(const i of s)this.createProperty(i,t[i]);}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i);}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(c$2(s));}else void 0!==s&&i.push(c$2(s));return i}static _$Eu(t,s){const i=s.attribute;return false===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,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,s=this.constructor.elementProperties;for(const i of s.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 S$1(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(true),this._$EO?.forEach(t=>t.hostConnected?.());}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.());}attributeChangedCallback(t,s,i){this._$AK(t,i);}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&true===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u$1).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null;}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u$1;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null;}}requestUpdate(t,s,i,e=false,h){if(void 0!==t){const r=this.constructor;if(false===e&&(h=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??f$1)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,s,i);} false===this.isUpdatePending&&(this._$ES=this._$EP());}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),true!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),true===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t));}async _$EP(){this.isUpdatePending=true;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,s]of this._$Ep)this[t]=s;this._$Ep=void 0;}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];true!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e);}}let t=false;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(s)):this._$EM();}catch(s){throw t=false,this._$EM(),s}t&&this._$AE(s);}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(t)),this.updated(t);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return true}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM();}updated(t){}firstUpdated(t){}};y$1.elementStyles=[],y$1.shadowRootOptions={mode:"open"},y$1[d$1("elementProperties")]=new Map,y$1[d$1("finalized")]=new Map,p$1?.({ReactiveElement:y$1}),(a$1.reactiveElementVersions??=[]).push("2.1.2");
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const t$1=globalThis,i$1=t=>t,s$1=t$1.trustedTypes,e=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,h="$lit$",o$2=`lit$${Math.random().toFixed(9).slice(2)}$`,n$1="?"+o$2,r$1=`<${n$1}>`,l=document,c=()=>l.createComment(""),a=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,d=t=>u(t)||"function"==typeof t?.[Symbol.iterator],f="[ \t\n\f\r]",v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\s"'>=/]+)(${f}*=${f}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),E=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==e?e.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?"<svg>":3===i?"<math>":"",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?"!--"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp("</"+u[2],"g")),c=p):void 0!==u[3]&&(c=p):c===p?">"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith("/>")?" ":"";l+=c===v?s+r$1:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o$2+x):s+o$2+(-2===d?i:x);}return [V(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o$2),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:"."===e[1]?I:"?"===e[1]?L:"@"===e[1]?z:H}),r.removeAttribute(t);}else t.startsWith(o$2)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o$2),i=t.length-1;if(i>0){r.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c());}}}else if(8===r.nodeType)if(r.data===n$1)d.push({type:2,index:l});else {let t=-1;for(;-1!==(t=r.data.indexOf(o$2,t+1));)d.push({type:7,index:l}),t+=o$2.length-1;}l++;}}static createElement(t,i){const s=l.createElement("template");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,true);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n];}o!==r?.index&&(h=P.nextNode(),o++);}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||""===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(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!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(false,true,s);t!==this._$AB;){const s=i$1(t).nextSibling;i$1(t).remove(),t=s;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class I extends H{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===A?void 0:t;}}class L extends H{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A);}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t);}}const B=t$1.litHtmlPolyfillSupport;B?.(S,k),(t$1.litHtmlVersions??=[]).push("3.3.2");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{});}return h._$AI(t),h};
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const s=globalThis;class i extends y$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=D(r,this.renderRoot,this.renderOptions);}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(true);}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(false);}render(){return E}}i._$litElement$=true,i["finalized"]=true,s.litElementHydrateSupport?.({LitElement:i});const o$1=s.litElementPolyfillSupport;o$1?.({LitElement:i});(s.litElementVersions??=[]).push("4.2.2");
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/
const t=t=>(e,o)=>{ void 0!==o?o.addInitializer(()=>{customElements.define(t,e);}):customElements.define(t,e);};
/**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*/const o={attribute:true,type:String,converter:u$1,reflect:false,hasChanged:f$1},r=(t=o,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),"setter"===n&&((t=Object.create(t)).wrapped=true),s.set(r.name,t),"accessor"===n){const{name:o}=r;return {set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t,true,r);},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t,true,r);}}throw Error("Unsupported decorator location: "+n)};function n(t){return (e,o)=>"object"==typeof o?r(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}
// Climate Entity Feature Enum (matching Home Assistant)
const ClimateEntityFeature = {
TARGET_TEMPERATURE: 1,
TARGET_TEMPERATURE_RANGE: 2,
TARGET_HUMIDITY: 4,
FAN_MODE: 8,
PRESET_MODE: 16,
SWING_MODE: 32,
AUX_HEAT: 64,
TURN_OFF: 128,
TURN_ON: 256,
SWING_HORIZONTAL_MODE: 512,
};
// Helper function to check if a feature is supported
function supportsFeature(stateObj, feature) {
return (stateObj.attributes.supported_features & feature) !== 0;
}
let ClimateControlDialog = class ClimateControlDialog extends i {
constructor() {
super(...arguments);
this.stateObj = null;
}
// Helper to capitalize mode text
_capitalize(text) {
// Special case for heat_cool
if (text === 'heat_cool') {
return 'Heat/Cool';
}
return text.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
}
render() {
if (!this.stateObj) {
return b `<div>No climate entity data</div>`;
}
return b `
${this._renderModeRow()}
${this._renderNoTemperatureChangeToggle()}
${this._renderTargetTemperature()}
${this._renderTargetTemperatureRange()}
${this._renderTargetHumidity()}
${this._renderFanSwingRow()}
${this._renderAuxHeat()}
`;
}
_renderModeRow() {
const hasPresetMode = supportsFeature(this.stateObj, ClimateEntityFeature.PRESET_MODE);
if (!hasPresetMode) {
return this._renderHvacModes();
}
return b `
<div class="mode-row">
${this._renderHvacModes()}
${this._renderPresetModes()}
</div>
`;
}
_renderHvacModes() {
if (!this.stateObj)
return '';
return b `
<div class="section">
<div class="section-title">HVAC Mode</div>
<select
class="mode-select"
.value=${this.stateObj.state || ''}
@change=${this._handleHvacModeChange}
>
<option value="">-- No Change --</option>
${this.stateObj.attributes.hvac_modes.map(mode => b `
<option value="${mode}" ?selected=${this.stateObj.state === mode}>
${this._capitalize(mode)}
</option>
`)}
</select>
</div>
`;
}
_renderTargetTemperature() {
if (!this.stateObj || !supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE)) {
return '';
}
const isNoTempChange = this._isNoTemperatureChangeEnabled();
const temperatureStep = this._getTemperatureStep();
const { min_temp, max_temp, temperature } = this.stateObj.attributes;
const range = max_temp - min_temp;
const tempPercent = ((temperature - min_temp) / range) * 100;
// Use the currently selected HVAC mode to determine styling
const currentMode = this.stateObj.state;
// Determine class, track fill, and label based on current mode
let inputClass = '';
let trackFill = tempPercent;
let label = 'Set to';
if (currentMode === 'heat_cool') {
inputClass = 'heat-cool';
}
else if (currentMode === 'cool') {
inputClass = 'cooling';
trackFill = 100 - tempPercent;
label = 'Cool to';
}
else if (currentMode === 'heat') {
inputClass = 'heating';
label = 'Heat to';
}
return b `
<div class="section">
<div class="section-title">Target Temperature</div>
<div class="temp-range-control">
<div class="temp-range-labels" style="justify-content: center;">
<div class="temp-range-value">
<span class="temp-range-label">${label}</span>
<span class="temp-range-number">${temperature}°</span>
</div>
</div>
<div class="dual-range-container">
<input
type="range"
class="dual-range-input ${inputClass}"
min="${min_temp}"
max="${max_temp}"
step="${temperatureStep}"
?disabled=${isNoTempChange}
.value="${temperature}"
@input=${this._handleTempSlider}
@change=${this._handleTempSliderChange}
style="top: 0; --track-fill: ${trackFill}%;"
/>
</div>
</div>
</div>
`;
}
_renderTargetTemperatureRange() {
if (!this.stateObj || !supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE_RANGE)) {
return '';
}
const isNoTempChange = this._isNoTemperatureChangeEnabled();
const temperatureStep = this._getTemperatureStep();
const { min_temp, max_temp, target_temp_low, target_temp_high } = this.stateObj.attributes;
const range = max_temp - min_temp;
const lowPercent = ((target_temp_low - min_temp) / range) * 100;
const highPercent = ((target_temp_high - min_temp) / range) * 100;
// Use the currently selected HVAC mode to determine layout
const currentMode = this.stateObj.state;
// Determine if we need dual range or single based on current mode
const heatOnly = currentMode === 'heat';
const coolOnly = currentMode === 'cool';
const isOffOrAuto = currentMode === 'off' || currentMode === 'auto';
// Render heat only (single input with red track)
if (heatOnly) {
return b `
<div class="section">
<div class="section-title">Target Temperature</div>
<div class="temp-range-control">
<div class="temp-range-labels" style="justify-content: center;">
<div class="temp-range-value">
<span class="temp-range-label">Heat to</span>
<span class="temp-range-number">${target_temp_low}°</span>
</div>
</div>
<div class="dual-range-container">
<input
type="range"
class="dual-range-input heating"
min="${min_temp}"
max="${max_temp}"
step="${temperatureStep}"
?disabled=${isNoTempChange}
.value="${target_temp_low}"
@input=${this._handleTempLowSlider}
@change=${this._handleTempLowSliderChange}
style="top: 0; --track-fill: ${lowPercent}%;"
/>
</div>
</div>
</div>
`;
}
// Render cool only (single input with blue track)
if (coolOnly) {
return b `
<div class="section">
<div class="section-title">Target Temperature</div>
<div class="temp-range-control">
<div class="temp-range-labels" style="justify-content: center;">
<div class="temp-range-value">
<span class="temp-range-label">Cool to</span>
<span class="temp-range-number">${target_temp_high}°</span>
</div>
</div>
<div class="dual-range-container">
<input
type="range"
class="dual-range-input cooling"
min="${min_temp}"
max="${max_temp}"
step="${temperatureStep}"
?disabled=${isNoTempChange}
.value="${target_temp_high}"
@input=${this._handleTempHighSlider}
@change=${this._handleTempHighSliderChange}
style="top: 0; --track-fill: ${100 - highPercent}%;"
/>
</div>
</div>
</div>
`;
}
// Render dual range (both heat and cool, heat_cool, auto, or off)
return b `
<div class="section">
<div class="section-title">Temperature Range</div>
<div class="temp-range-control">
<div class="temp-range-labels">
<div class="temp-range-value">
<span class="temp-range-label">Heat to</span>
<span class="temp-range-number">${target_temp_low}°</span>
</div>
<div class="temp-range-value">
<span class="temp-range-label">Cool to</span>
<span class="temp-range-number">${target_temp_high}°</span>
</div>
</div>
<div class="dual-range-container">
${!isOffOrAuto ? b `
<div class="dual-range-fill"
style="left: ${lowPercent}%; width: ${highPercent - lowPercent}%">
</div>
` : ''}
<input
type="range"
class="dual-range-input ${!isOffOrAuto ? 'heating' : ''}"
min="${min_temp}"
max="${max_temp}"
step="${temperatureStep}"
?disabled=${isNoTempChange}
.value="${target_temp_low}"
@input=${this._handleTempLowSlider}
@change=${this._handleTempLowSliderChange}
style="top: 0; --track-fill: ${lowPercent}%;"
/>
<input
type="range"
class="dual-range-input ${!isOffOrAuto ? 'cooling' : ''}"
min="${min_temp}"
max="${max_temp}"
step="${temperatureStep}"
?disabled=${isNoTempChange}
.value="${target_temp_high}"
@input=${this._handleTempHighSlider}
@change=${this._handleTempHighSliderChange}
style="top: 0; --track-fill: ${100 - highPercent}%;"
/>
</div>
</div>
</div>
`;
}
_renderTargetHumidity() {
if (!this.stateObj || !supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_HUMIDITY)) {
return '';
}
const humidityStep = this._getHumidityStep();
const { min_humidity, max_humidity, target_humidity } = this.stateObj.attributes;
const range = max_humidity - min_humidity;
const humidityPercent = ((target_humidity - min_humidity) / range) * 100;
return b `
<div class="section">
<div class="section-title">Target Humidity</div>
<div class="temp-range-control">
<div class="temp-range-labels" style="justify-content: center;">
<div class="temp-range-value">
<span class="temp-range-label">Set to</span>
<span class="temp-range-number">${target_humidity}%</span>
</div>
</div>
<div class="dual-range-container">
<input
type="range"
class="dual-range-input"
min="${min_humidity}"
max="${max_humidity}"
step="${humidityStep}"
.value="${target_humidity}"
@input=${this._handleHumiditySlider}
@change=${this._handleHumiditySliderChange}
style="top: 0; --track-fill: ${humidityPercent}%;"
/>
</div>
</div>
</div>
`;
}
_renderFanSwingRow() {
const hasFanMode = supportsFeature(this.stateObj, ClimateEntityFeature.FAN_MODE);
const hasSwingMode = supportsFeature(this.stateObj, ClimateEntityFeature.SWING_MODE);
const hasSwingHorizontal = supportsFeature(this.stateObj, ClimateEntityFeature.SWING_HORIZONTAL_MODE);
// If none are present, return nothing
if (!hasFanMode && !hasSwingMode && !hasSwingHorizontal) {
return '';
}
// If only one is present, show it full width
if (hasFanMode && !hasSwingMode && !hasSwingHorizontal) {
return this._renderFanModes();
}
if (!hasFanMode && hasSwingMode && !hasSwingHorizontal) {
return this._renderSwingModes();
}
if (!hasFanMode && !hasSwingMode && hasSwingHorizontal) {
return this._renderSwingHorizontalModes();
}
// Show all present modes in a row
return b `
<div class="mode-row">
${hasFanMode ? this._renderFanModes() : ''}
${hasSwingMode ? this._renderSwingModes() : ''}
${hasSwingHorizontal ? this._renderSwingHorizontalModes() : ''}
</div>
`;
}
_renderFanModes() {
if (!this.stateObj)
return '';
return b `
<div class="section">
<div class="section-title">Fan Mode</div>
<select
class="mode-select"
.value=${this.stateObj.attributes.fan_mode || ''}
@change=${this._handleFanModeChange}
>
<option value="">-- No Change --</option>
${this.stateObj.attributes.fan_modes.map(mode => b `
<option value="${mode}" ?selected=${this.stateObj.attributes.fan_mode === mode}>
${this._capitalize(mode)}
</option>
`)}
</select>
</div>
`;
}
_renderPresetModes() {
if (!this.stateObj)
return '';
return b `
<div class="section">
<div class="section-title">Thermostat Preset</div>
<select
class="mode-select"
.value=${this.stateObj.attributes.preset_mode || ''}
@change=${this._handlePresetModeChange}
>
<option value="">-- No Change --</option>
${this.stateObj.attributes.preset_modes.map(mode => b `
<option value="${mode}" ?selected=${this.stateObj.attributes.preset_mode === mode}>
${this._capitalize(mode)}
</option>
`)}
</select>
</div>
`;
}
_renderSwingModes() {
if (!this.stateObj)
return '';
return b `
<div class="section">
<div class="section-title">Swing (Vertical)</div>
<select
class="mode-select"
.value=${this.stateObj.attributes.swing_mode || ''}
@change=${this._handleSwingModeChange}
>
<option value="">-- No Change --</option>
${this.stateObj.attributes.swing_modes.map(mode => b `
<option value="${mode}" ?selected=${this.stateObj.attributes.swing_mode === mode}>
${this._capitalize(mode)}
</option>
`)}
</select>
</div>
`;
}
_renderSwingHorizontalModes() {
if (!this.stateObj)
return '';
return b `
<div class="section">
<div class="section-title">Swing (Horizontal)</div>
<select
class="mode-select"
.value=${this.stateObj.attributes.swing_horizontal_mode || ''}
@change=${this._handleSwingHorizontalModeChange}
>
<option value="">-- No Change --</option>
${this.stateObj.attributes.swing_horizontal_modes.map(mode => b `
<option value="${mode}" ?selected=${this.stateObj.attributes.swing_horizontal_mode === mode}>
${this._capitalize(mode)}
</option>
`)}
</select>
</div>
`;
}
_renderAuxHeat() {
if (!this.stateObj || !supportsFeature(this.stateObj, ClimateEntityFeature.AUX_HEAT)) {
return '';
}
return b `
<div class="section">
<div class="section-title">Auxiliary Heat</div>
<div class="toggle-row">
<span class="toggle-label">Aux Heat</span>
<label class="toggle-switch">
<input
type="checkbox"
.checked=${this.stateObj.attributes.aux_heat === 'on'}
@change=${this._handleAuxHeatToggle}
/>
<span class="toggle-slider"></span>
</label>
</div>
</div>
`;
}
_isNoTemperatureChangeEnabled() {
return Boolean(this.stateObj?.attributes.noChange);
}
_getTemperatureStep() {
const configuredStep = this.stateObj?.attributes.temperature_step;
if (typeof configuredStep === 'number' && Number.isFinite(configuredStep) && configuredStep > 0) {
return configuredStep;
}
return 0.5;
}
_getHumidityStep() {
const configuredStep = this.stateObj?.attributes.humidity_step;
if (typeof configuredStep === 'number' && Number.isFinite(configuredStep) && configuredStep > 0) {
return configuredStep;
}
return 1;
}
_normalizeToStep(value, step) {
const snapped = step > 0 ? Math.round(value / step) * step : value;
const precision = this._getStepPrecision(step);
const factor = 10 ** precision;
return Math.round((snapped + Number.EPSILON) * factor) / factor;
}
_getStepPrecision(step) {
if (!Number.isFinite(step) || step <= 0) {
return 3;
}
const stepString = step.toString().toLowerCase();
if (stepString.includes('e-')) {
const exponent = Number(stepString.split('e-')[1]);
return Number.isFinite(exponent) ? exponent : 3;
}
const decimalPart = stepString.split('.')[1];
return decimalPart ? decimalPart.length : 0;
}
_renderNoTemperatureChangeToggle() {
if (!this.stateObj)
return '';
const supportsTemperature = supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE) ||
supportsFeature(this.stateObj, ClimateEntityFeature.TARGET_TEMPERATURE_RANGE);
if (!supportsTemperature) {
return '';
}
return b `
<div class="section">
<div class="toggle-row">
<span class="toggle-label">No Temperature Change</span>
<label class="toggle-switch">
<input
type="checkbox"
.checked=${this._isNoTemperatureChangeEnabled()}
@change=${this._handleNoTemperatureChangeToggle}
/>
<span class="toggle-slider"></span>
</label>
</div>
</div>
`;
}
// Event handlers that dispatch custom events for parent to handle
_handleHvacModeChange(e) {
const value = e.target.value;
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
state: value
};
}
this.dispatchEvent(new CustomEvent('hvac-mode-changed', {
detail: { mode: value },
bubbles: true,
composed: true
}));
}
_handleTempSlider(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
// Update stateObj to trigger re-render with new track fill
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
attributes: {
...this.stateObj.attributes,
temperature: value
}
};
}
this.dispatchEvent(new CustomEvent('temperature-changed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleTempSliderChange(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
this.dispatchEvent(new CustomEvent('temperature-change-committed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleTempLowSlider(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
// Update stateObj to trigger re-render with new track fill
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
attributes: {
...this.stateObj.attributes,
target_temp_low: value
}
};
}
this.dispatchEvent(new CustomEvent('target-temp-low-changed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleTempLowSliderChange(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
this.dispatchEvent(new CustomEvent('target-temp-low-committed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleTempHighSlider(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
// Update stateObj to trigger re-render with new track fill
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
attributes: {
...this.stateObj.attributes,
target_temp_high: value
}
};
}
this.dispatchEvent(new CustomEvent('target-temp-high-changed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleTempHighSliderChange(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getTemperatureStep());
this.dispatchEvent(new CustomEvent('target-temp-high-committed', {
detail: { temperature: value },
bubbles: true,
composed: true
}));
}
_handleHumiditySlider(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getHumidityStep());
// Update stateObj to trigger re-render with new track fill
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
attributes: {
...this.stateObj.attributes,
target_humidity: value
}
};
}
this.dispatchEvent(new CustomEvent('humidity-changed', {
detail: { humidity: value },
bubbles: true,
composed: true
}));
}
_handleHumiditySliderChange(e) {
const rawValue = parseFloat(e.target.value);
const value = this._normalizeToStep(rawValue, this._getHumidityStep());
this.dispatchEvent(new CustomEvent('humidity-committed', {
detail: { humidity: value },
bubbles: true,
composed: true
}));
}
_handleFanModeChange(e) {
const value = e.target.value;
this.dispatchEvent(new CustomEvent('fan-mode-changed', {
detail: { mode: value },
bubbles: true,
composed: true
}));
}
_handlePresetModeChange(e) {
const value = e.target.value;
this.dispatchEvent(new CustomEvent('preset-mode-changed', {
detail: { mode: value },
bubbles: true,
composed: true
}));
}
_handleSwingModeChange(e) {
const value = e.target.value;
this.dispatchEvent(new CustomEvent('swing-mode-changed', {
detail: { mode: value },
bubbles: true,
composed: true
}));
}
_handleSwingHorizontalModeChange(e) {
const value = e.target.value;
this.dispatchEvent(new CustomEvent('swing-horizontal-mode-changed', {
detail: { mode: value },
bubbles: true,
composed: true
}));
}
_handleAuxHeatToggle(e) {
const checked = e.target.checked;
this.dispatchEvent(new CustomEvent('aux-heat-changed', {
detail: { enabled: checked },
bubbles: true,
composed: true
}));
}
_handleNoTemperatureChangeToggle(e) {
const checked = e.target.checked;
if (this.stateObj) {
this.stateObj = {
...this.stateObj,
attributes: {
...this.stateObj.attributes,
noChange: checked
}
};
}
this.dispatchEvent(new CustomEvent('no-temp-change-changed', {
detail: { enabled: checked },
bubbles: true,
composed: true
}));
}
};
ClimateControlDialog.styles = i$3 `
:host {
display: block;
background: transparent;
border-radius: var(--ha-card-border-radius, 8px);
padding: 0;
}
.dialog-header {
font-size: 20px;
font-weight: 500;
color: var(--primary-text-color, #333);
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 12px;
}
.entity-icon {
font-size: 28px;
}
.section {
margin-bottom: 20px;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: var(--secondary-text-color, #666);
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.mode-row {
display: flex;
gap: 12px;
}
.mode-row .section {
flex: 1;
}
.mode-select {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--divider-color, #ddd);
border-radius: 4px;
background: var(--card-background-color, white);
font-size: 14px;
color: var(--primary-text-color, #333);
cursor: pointer;
outline: none;
transition: border-color 0.2s;
}
.mode-select:hover {
border-color: #999;
}
.mode-select:focus {
border-color: var(--primary-color, #03a9f4);
box-shadow: 0 0 0 2px rgba(3, 169, 244, 0.1);
}
.temp-range-control {
position: relative;
}
.dual-range-container {
position: relative;
margin: 0 0;
padding: 0;
}
.dual-range-input {
position: absolute;
width: 100%;
left: 0;
pointer-events: none;
-webkit-appearance: none;
background: transparent;
margin: 0;
height: 20px;
}
.dual-range-input::-webkit-slider-runnable-track {
background: transparent;
height: 8px;
border-radius: 4px;
}
.dual-range-input::-webkit-slider-thumb {
-webkit-appearance: none;
pointer-events: all;
width: 20px !important;
height: 20px !important;
border-radius: 10px;
background: linear-gradient(to bottom, white, #f8f8f8);
cursor: grab;
border: 2px solid var(--primary-color, #03a9f4);
box-shadow:
0 2px 8px rgba(0,0,0,0.15),
inset 0 1px 0 rgba(255,255,255,0.8);
margin-top: -6px !important;
transition: transform 0.15s, box-shadow 0.15s;
}
.dual-range-input::-webkit-slider-thumb:hover {
transform: scale(1.1);
box-shadow:
0 4px 12px rgba(0,0,0,0.2),
inset 0 1px 0 rgba(255,255,255,0.8);
}
.dual-range-input::-moz-range-track {
background: transparent;
height: 8px;
border-radius: 4px;
}
.dual-range-input::-moz-range-thumb {
pointer-events: all;
border: none;
width: 20px !important;
height: 20px !important;
border-radius: 10px;
background: linear-gradient(to bottom, white, #f8f8f8);
cursor: grab;
border: 2px solid var(--primary-color, #03a9f4);
box-shadow:
0 2px 8px rgba(0,0,0,0.15),
inset 0 1px 0 rgba(255,255,255,0.8);
margin-top: -6px !important;
transition: transform 0.15s, box-shadow 0.15s;
}
.dual-range-input::-moz-range-thumb:hover {
transform: scale(1.1);
box-shadow:
0 4px 12px rgba(0,0,0,0.2),
inset 0 1px 0 rgba(255,255,255,0.8);
}
.dual-range-input:focus::-webkit-slider-thumb {
box-shadow:
0 0 0 4px rgba(3, 169, 244, 0.2),
0 2px 8px rgba(0,0,0,0.15),
inset 0 1px 0 rgba(255,255,255,0.8);
}
.dual-range-input:focus::-moz-range-thumb {
box-shadow:
0 0 0 4px rgba(3, 169, 244, 0.2),
0 2px 8px rgba(0,0,0,0.15),
inset 0 1px 0 rgba(255,255,255,0.8);
}
/* Heating input - red from left to thumb */
.dual-range-input.heating::-webkit-slider-runnable-track {
background: linear-gradient(to right,
#f44336 0%,
#f44336 var(--track-fill, 50%),
transparent var(--track-fill, 50%));
height: 8px;
border-radius: 4px;
position: relative;
z-index: 5;
}
.dual-range-input.heating::-moz-range-track {
background: transparent;
height: 8px;
border-radius: 4px;
}
.dual-range-input.heating::-moz-range-progress {
background: #f44336;
height: 8px;
border-radius: 4px 0 0 4px;
}
/* Cooling input - blue from right to thumb */
.dual-range-input.cooling::-webkit-slider-runnable-track {
background: linear-gradient(to left,
#2196f3 0%,
#2196f3 var(--track-fill, 50%),
transparent var(--track-fill, 50%));
height: 8px;
border-radius: 4px;
position: relative;
z-index: 5;
}
.dual-range-input.cooling::-moz-range-track {
background: transparent;
height: 8px;
border-radius: 4px;
}
.dual-range-input.cooling::-moz-range-progress {
background: #2196f3;
height: 8px;
border-radius: 0 4px 4px 0;
transform: scaleX(-1);
transform-origin: center;
}
/* Heat/Cool input - orange full track */
.dual-range-input.heat-cool::-webkit-slider-runnable-track {
background: #ff9800;
height: 8px;
border-radius: 4px;
position: relative;
z-index: 5;
}
.dual-range-input.heat-cool::-moz-range-track {
background: #ff9800;
height: 8px;
border-radius: 4px;
}
.temp-range-labels {
display: flex;
justify-content: space-between;
margin-top: 12px;
padding: 0 10px;
}
.temp-range-value {
display: flex;
flex-direction: column;
align-items: center;
}
.temp-range-label {
font-size: 11px;
color: var(--secondary-text-color, #666);
margin-bottom: 4px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.temp-range-number {
font-size: 24px;
font-weight: 600;
color: var(--primary-text-color, #333);
}
.dual-range-fill {
position: absolute;
height: 8px;
background: linear-gradient(90deg, rgba(244, 67, 54, 0.3), rgba(33, 150, 243, 0.3));
border-radius: 4px;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
z-index: 1;
}
.toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 0;
}
.toggle-label {
font-size: 14px;
color: var(--primary-text-color, #333);
}
.toggle-switch {
position: relative;
display: inline-block;
width: 48px;
height: 26px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 26px;
}
.toggle-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 4px;
bottom: 4px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
input:checked + .toggle-slider {
background-color: var(--primary-color, #03a9f4);
}
input:checked + .toggle-slider:before {
transform: translateX(22px);
}
`;
__decorate([
n({ type: Object })
], ClimateControlDialog.prototype, "stateObj", void 0);
ClimateControlDialog = __decorate([
t('climate-control-dialog')
], ClimateControlDialog);
export { ClimateControlDialog, ClimateEntityFeature, supportsFeature };
//# sourceMappingURL=climate-dialog.js.map