forked from Rishi8078/TimeFlow-Card
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimeflow-card.js
More file actions
294 lines (270 loc) · 68.8 KB
/
timeflow-card.js
File metadata and controls
294 lines (270 loc) · 68.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
function t(t,e,i,s){var r,a=arguments.length,n=a<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 o=t.length-1;o>=0;o--)(r=t[o])&&(n=(a<3?r(n):a>3?r(e,i,n):r(e,i))||n);return a>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(),r=new WeakMap;let a=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=r.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&r.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 a(i,t,s)},o=i?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new a("string"==typeof t?t:t+"",void 0,s))(e)})(t):t,{is:l,defineProperty:c,getOwnPropertyDescriptor:h,getOwnPropertyNames:d,getOwnPropertySymbols:u,getPrototypeOf:m}=Object,p=globalThis,f=p.trustedTypes,g=f?f.emptyScript:"",_=p.reactiveElementPolyfillSupport,y=(t,e)=>t,v={toAttribute(t,e){switch(e){case Boolean:t=t?g: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}},x=(t,e)=>!l(t,e),b={attribute:!0,type:String,converter:v,reflect:!1,useDefault:!1,hasChanged:x};Symbol.metadata??=Symbol("metadata"),p.litPropertyMetadata??=new WeakMap;let $=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=b){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&&c(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:r}=h(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:s,set(e){const a=s?.call(this);r?.call(this,e),this.requestUpdate(t,a,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(y("elementProperties")))return;const t=m(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(y("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(y("properties"))){const t=this.properties,e=[...d(t),...u(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[e,i]of this.elementProperties){const t=this._$Eu(e,i);void 0!==t&&this._$Eh.set(t,e)}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(o(t))}else void 0!==t&&e.push(o(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"),r=e.litNonce;void 0!==r&&s.setAttribute("nonce",r),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 r=(void 0!==i.converter?.toAttribute?i.converter:v).toAttribute(e,i.type);this._$Em=t,null==r?this.removeAttribute(s):this.setAttribute(s,r),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),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:v;this._$Em=s;const a=r.fromAttribute(e,t.type);this[s]=a??this._$Ej?.get(s)??a,this._$Em=null}}requestUpdate(t,e,i){if(void 0!==t){const s=this.constructor,r=this[t];if(i??=s.getPropertyOptions(t),!((i.hasChanged??x)(r,e)||i.useDefault&&i.reflect&&r===this._$Ej?.get(t)&&!this.hasAttribute(s._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:s,wrapped:r},a){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,a??e??this[t]),!0!==r||void 0!==a)||(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){}};$.elementStyles=[],$.shadowRootOptions={mode:"open"},$[y("elementProperties")]=new Map,$[y("finalized")]=new Map,_?.({ReactiveElement:$}),(p.reactiveElementVersions??=[]).push("2.1.1");const w=globalThis,S=w.trustedTypes,A=S?S.createPolicy("lit-html",{createHTML:t=>t}):void 0,T="$lit$",C=`lit$${Math.random().toFixed(9).slice(2)}$`,D="?"+C,E=`<${D}>`,M=document,N=()=>M.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,k=Array.isArray,R="[ \t\n\f\r]",P=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,O=/-->/g,U=/>/g,z=RegExp(`>|${R}(?:([^\\s"'>=/]+)(${R}*=${R}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),H=/'/g,F=/"/g,L=/^(?:script|style|textarea|title)$/i,V=(t=>(e,...i)=>({_$litType$:t,strings:e,values:i}))(1),W=Symbol.for("lit-noChange"),j=Symbol.for("lit-nothing"),q=new WeakMap,B=M.createTreeWalker(M,129);function J(t,e){if(!k(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==A?A.createHTML(e):e}const K=(t,e)=>{const i=t.length-1,s=[];let r,a=2===e?"<svg>":3===e?"<math>":"",n=P;for(let o=0;o<i;o++){const e=t[o];let i,l,c=-1,h=0;for(;h<e.length&&(n.lastIndex=h,l=n.exec(e),null!==l);)h=n.lastIndex,n===P?"!--"===l[1]?n=O:void 0!==l[1]?n=U:void 0!==l[2]?(L.test(l[2])&&(r=RegExp("</"+l[2],"g")),n=z):void 0!==l[3]&&(n=z):n===z?">"===l[0]?(n=r??P,c=-1):void 0===l[1]?c=-2:(c=n.lastIndex-l[2].length,i=l[1],n=void 0===l[3]?z:'"'===l[3]?F:H):n===F||n===H?n=z:n===O||n===U?n=P:(n=z,r=void 0);const d=n===z&&t[o+1].startsWith("/>")?" ":"";a+=n===P?e+E:c>=0?(s.push(i),e.slice(0,c)+T+e.slice(c)+C+d):e+C+(-2===c?o:d)}return[J(t,a+(t[i]||"<?>")+(2===e?"</svg>":3===e?"</math>":"")),s]};class Z{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let r=0,a=0;const n=t.length-1,o=this.parts,[l,c]=K(t,e);if(this.el=Z.createElement(l,i),B.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=B.nextNode())&&o.length<n;){if(1===s.nodeType){if(s.hasAttributes())for(const t of s.getAttributeNames())if(t.endsWith(T)){const e=c[a++],i=s.getAttribute(t).split(C),n=/([.?@])?(.*)/.exec(e);o.push({type:1,index:r,name:n[2],strings:i,ctor:"."===n[1]?tt:"?"===n[1]?et:"@"===n[1]?it:Q}),s.removeAttribute(t)}else t.startsWith(C)&&(o.push({type:6,index:r}),s.removeAttribute(t));if(L.test(s.tagName)){const t=s.textContent.split(C),e=t.length-1;if(e>0){s.textContent=S?S.emptyScript:"";for(let i=0;i<e;i++)s.append(t[i],N()),B.nextNode(),o.push({type:2,index:++r});s.append(t[e],N())}}}else if(8===s.nodeType)if(s.data===D)o.push({type:2,index:r});else{let t=-1;for(;-1!==(t=s.data.indexOf(C,t+1));)o.push({type:7,index:r}),t+=C.length-1}r++}}static createElement(t,e){const i=M.createElement("template");return i.innerHTML=t,i}}function X(t,e,i=t,s){if(e===W)return e;let r=void 0!==s?i._$Co?.[s]:i._$Cl;const a=I(e)?void 0:e._$litDirective$;return r?.constructor!==a&&(r?._$AO?.(!1),void 0===a?r=void 0:(r=new a(t),r._$AT(t,i,s)),void 0!==s?(i._$Co??=[])[s]=r:i._$Cl=r),void 0!==r&&(e=X(t,r._$AS(t,e.values),r,s)),e}class Y{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:i}=this._$AD,s=(t?.creationScope??M).importNode(e,!0);B.currentNode=s;let r=B.nextNode(),a=0,n=0,o=i[0];for(;void 0!==o;){if(a===o.index){let e;2===o.type?e=new G(r,r.nextSibling,this,t):1===o.type?e=new o.ctor(r,o.name,o.strings,this,t):6===o.type&&(e=new st(r,this,t)),this._$AV.push(e),o=i[++n]}a!==o?.index&&(r=B.nextNode(),a++)}return B.currentNode=M,s}p(t){let e=0;for(const i of this._$AV)void 0!==i&&(void 0!==i.strings?(i._$AI(t,i,e),e+=i.strings.length-2):i._$AI(t[e])),e++}}class G{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,i,s){this.type=2,this._$AH=j,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=i,this.options=s,this._$Cv=s?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return void 0!==e&&11===t?.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=X(this,t,e),I(t)?t===j||null==t||""===t?(this._$AH!==j&&this._$AR(),this._$AH=j):t!==this._$AH&&t!==W&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):(t=>k(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!==j&&I(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=Z.createElement(J(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===s)this._$AH.p(e);else{const t=new Y(s,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=q.get(t.strings);return void 0===e&&q.set(t.strings,e=new Z(t)),e}k(t){k(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,s=0;for(const r of t)s===e.length?e.push(i=new G(this.O(N()),this.O(N()),this,this.options)):i=e[s],i._$AI(r),s++;s<e.length&&(this._$AR(i&&i._$AB.nextSibling,s),e.length=s)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){const e=t.nextSibling;t.remove(),t=e}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}class Q{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,i,s,r){this.type=1,this._$AH=j,this._$AN=void 0,this.element=t,this.name=e,this._$AM=s,this.options=r,i.length>2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=j}_$AI(t,e=this,i,s){const r=this.strings;let a=!1;if(void 0===r)t=X(this,t,e,0),a=!I(t)||t!==this._$AH&&t!==W,a&&(this._$AH=t);else{const s=t;let n,o;for(t=r[0],n=0;n<r.length-1;n++)o=X(this,s[i+n],e,n),o===W&&(o=this._$AH[n]),a||=!I(o)||o!==this._$AH[n],o===j?t=j:t!==j&&(t+=(o??"")+r[n+1]),this._$AH[n]=o}a&&!s&&this.j(t)}j(t){t===j?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class tt extends Q{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===j?void 0:t}}class et extends Q{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==j)}}class it extends Q{constructor(t,e,i,s,r){super(t,e,i,s,r),this.type=5}_$AI(t,e=this){if((t=X(this,t,e,0)??j)===W)return;const i=this._$AH,s=t===j&&i!==j||t.capture!==i.capture||t.once!==i.once||t.passive!==i.passive,r=t!==j&&(i===j||s);s&&this.element.removeEventListener(this.name,this,i),r&&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 st{constructor(t,e,i){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=i}get _$AU(){return this._$AM._$AU}_$AI(t){X(this,t)}}const rt=w.litHtmlPolyfillSupport;rt?.(Z,G),(w.litHtmlVersions??=[]).push("3.3.1");const at=globalThis;let nt=class extends ${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 e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{const s=i?.renderBefore??e;let r=s._$litPart$;if(void 0===r){const t=i?.renderBefore??null;s._$litPart$=r=new G(e.insertBefore(N(),t),t,void 0,i??{})}return r._$AI(t),r})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return W}};nt._$litElement$=!0,nt.finalized=!0,at.litElementHydrateSupport?.({LitElement:nt});const ot=at.litElementPolyfillSupport;ot?.({LitElement:nt}),(at.litElementVersions??=[]).push("4.2.1");const lt={attribute:!0,type:String,converter:v,reflect:!1,hasChanged:x},ct=(t=lt,e,i)=>{const{kind:s,metadata:r}=i;let a=globalThis.litPropertyMetadata.get(r);if(void 0===a&&globalThis.litPropertyMetadata.set(r,a=new Map),"setter"===s&&((t=Object.create(t)).wrapped=!0),a.set(i.name,t),"accessor"===s){const{name:s}=i;return{set(i){const r=e.get.call(this);e.set.call(this,i),this.requestUpdate(s,r,t)},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 r=this[s];e.call(this,i),this.requestUpdate(s,r,t)}}throw Error("Unsupported decorator location: "+s)};function ht(t){return(e,i)=>"object"==typeof i?ct(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 dt(t){return ht({...t,state:!0,attribute:!1})}class ut{static isTimerEntity(t){return!!t&&(!!t.startsWith("timer.")||!!(t.includes("_next_timer")||t.includes("alexa_timer")||t.startsWith("sensor.")&&t.includes("timer")))}static isAlexaTimer(t){return t.includes("_next_timer")||t.includes("alexa_timer")||t.startsWith("sensor.")&&t.includes("alexa")&&t.includes("timer")}static getTimerData(t,e){if(!e||!t||!this.isTimerEntity(t))return null;const i=e.states[t];return i?this.isAlexaTimer(t)?this.getAlexaTimerData(t,i,e):this.getStandardTimerData(t,i):null}static getAlexaTimerData(t,e,i){var s,r,a,n,o,l,c,h,d,u,m,p,f,g;const{state:_,attributes:y}=e,v=null!==(s=this.parseJson(y.sorted_active))&&void 0!==s?s:[],x=null!==(r=this.parseJson(y.sorted_all))&&void 0!==r?r:[],b=null!==(n=null!==(a=y.total_active)&&void 0!==a?a:v.length)&&void 0!==n?n:0,$=null!==(l=null!==(o=y.total_all)&&void 0!==o?o:x.length)&&void 0!==l?l:0,w=new Map;for(const z of v)Array.isArray(z)&&z.length>=2&&z[0]&&z[1]&&w.set(String(z[0]),z[1]);const S=new Map;for(const z of x)Array.isArray(z)&&z.length>=2&&z[0]&&z[1]&&S.set(String(z[0]),z[1]);const A=Date.now();let T=this.alexaIdCache.get(t);T||(T={},this.alexaIdCache.set(t,T));const C=[];for(const[z,H]of w.entries()){const t="number"==typeof(null==H?void 0:H.triggerTime)?H.triggerTime:0;t&&t<=A&&C.push({id:z,trig:t})}C.length>0?(C.sort((t,e)=>t.trig-e.trig),T.finishedWhileActiveId=C[0].id):T.finishedWhileActiveId&&!w.has(T.finishedWhileActiveId)&&delete T.finishedWhileActiveId;let D,E=!1,M=!1,N=!1,I=null;if(b>0&&v.length>0)if(T.finishedWhileActiveId&&w.has(T.finishedWhileActiveId))D=T.finishedWhileActiveId,I=null!==(c=w.get(D))&&void 0!==c?c:null,E=!!I,N=!0;else{if(1===v.length)D=String(null===(h=v[0])||void 0===h?void 0:h[0]),I=null!==(u=null===(d=v[0])||void 0===d?void 0:d[1])&&void 0!==u?u:null;else{let t,e=null,i=Number.POSITIVE_INFINITY;for(const s of v){const r=String(null==s?void 0:s[0]),a=null==s?void 0:s[1];a&&"number"==typeof a.remainingTime&&a.remainingTime<i&&(i=a.remainingTime,e=a,t=r)}D=t,I=e}E=!!I,E&&I&&"number"==typeof I.triggerTime&&I.triggerTime<=A&&(N=!0,T.finishedWhileActiveId=D)}else if($>0&&x.length>0){let t=null,e=-1/0;for(const[i,s]of S.entries())if("PAUSED"===(null==s?void 0:s.status)){const r="number"==typeof s.lastUpdatedDate?s.lastUpdatedDate:-1/0;r>e&&(e=r,t=s,D=i)}t&&(I=t,M=!0)}let k=0,R=0,P=null,O=0;if(I){const t=Date.now(),e="number"==typeof I.remainingTime?I.remainingTime:0,i="number"==typeof I.originalDurationInMillis?I.originalDurationInMillis:0,s="number"==typeof I.triggerTime?I.triggerTime:0;if(R=Math.max(0,Math.floor(i/1e3)),E?(s&&s>t?(k=Math.max(0,Math.floor((s-t)/1e3)),P=new Date(s)):(k=Math.max(0,Math.floor(e/1e3)),k>0&&(P=new Date(t+1e3*k))),(s&&s<=t||k<=0||"OFF"===I.status&&0===e)&&(k=0,P=null,N=!0)):(k=Math.max(0,Math.floor(e/1e3)),P=null),R>0){const t=Math.max(0,R-k);O=Math.min(100,Math.max(0,t/R*100)),E&&O>=100&&(k=0,N=!0)}}else{if(_&&"unavailable"!==_&&"unknown"!==_&&(this.isISOTimestamp(_)?(P=new Date(_),isNaN(P.getTime())||(k=Math.max(0,Math.floor((P.getTime()-Date.now())/1e3)))):isNaN(parseFloat(_))?"string"==typeof _&&_.includes(":")&&(k=this.parseDuration(_)):k=Math.max(0,parseFloat(_))),y.original_duration)R=this.parseDuration(y.original_duration);else if(y.duration)R=this.parseDuration(y.duration);else if(P&&e.last_changed){const t=new Date(e.last_changed).getTime(),i=P.getTime();!isNaN(t)&&i>t&&(R=Math.floor((i-t)/1e3))}if(R>0){const t=R-k;O=Math.min(100,Math.max(0,t/R*100))}}let U=null==I?void 0:I.timerLabel;return!U&&v.length>0&&(U=null===(p=null===(m=v[0])||void 0===m?void 0:m[1])||void 0===p?void 0:p.timerLabel),!U&&x.length>0&&(U=null===(g=null===(f=x[0])||void 0===f?void 0:f[1])||void 0===g?void 0:g.timerLabel),{isActive:E,isPaused:M,duration:R,remaining:k,finishesAt:P,progress:O,finished:N,isAlexaTimer:!0,alexaDevice:this.extractAlexaDevice(t,y),timerLabel:null!=U?U:this.extractAlexaDevice(t,y),timerStatus:M?"PAUSED":E?"ON":"OFF",userDefinedLabel:U}}static parseJson(t){if(Array.isArray(t))return t;if("string"==typeof t)try{return JSON.parse(t)}catch{}return null}static parseJsonArray(t){if(!t)return null;if(Array.isArray(t))return t;if("string"==typeof t)try{return JSON.parse(t)}catch(e){return null}return null}static extractAlexaDeviceFromEntity(t){return t.friendly_name?t.friendly_name.replace(/\s*next\s*timer$/i,"").replace(/\s*timer$/i,"").trim():"Alexa Device"}static parseLegacyAlexaTimer(t,e,i,s){let r=0,a=0,n=null,o=!1;if(i&&"unavailable"!==i&&"unknown"!==i)if(this.isISOTimestamp(i)){if(n=new Date(i),!isNaN(n.getTime())){const t=Date.now();r=Math.max(0,Math.floor((n.getTime()-t)/1e3)),o=r>0}}else isNaN(parseFloat(i))?"string"==typeof i&&i.includes(":")&&(r=this.parseDuration(i),o=r>0):(r=Math.max(0,parseFloat(i)),o=r>0);let l=!1;if(s.original_duration)a=this.parseDuration(s.original_duration),l=!0;else if(s.duration)a=this.parseDuration(s.duration),l=!0;else if(n&&e.last_changed){const t=new Date(e.last_changed).getTime(),i=n.getTime();!isNaN(t)&&i>t&&(a=Math.floor((i-t)/1e3),l=!0)}l||(a=r>0?r:0,l=!1);let c=0;if(l&&a>0)if(o&&r>=0){const t=a-r;c=Math.min(100,Math.max(0,t/a*100))}else 0===r&&a>0&&(c=100);else if(o&&r>0){const t=e.last_changed?new Date(e.last_changed).getTime():Date.now(),i=(Date.now()-t)/1e3;if(i<r){const t=r+i,e=i;c=Math.min(100,Math.max(0,e/t*100))}else c=0}else c=0;return{isActive:o,isPaused:!1,duration:a,remaining:r,finishesAt:n,progress:c,isAlexaTimer:!0,alexaDevice:this.extractAlexaDevice(t,s),timerLabel:s.friendly_name||s.timer_label||this.formatAlexaTimerName(t),timerStatus:o?"ON":"OFF",userDefinedLabel:void 0}}static getStandardTimerData(t,e){const i=e.state,s=e.attributes,r="active"===i,a="paused"===i,n="idle"===i;let o=0;s.duration&&(o=this.parseDuration(s.duration));let l=0,c=null;(r||a)&&(s.finishes_at?(c=new Date(s.finishes_at),isNaN(c.getTime())||(l=Math.max(0,Math.floor((c.getTime()-Date.now())/1e3)))):s.remaining&&(l=this.parseDuration(s.remaining)));let h=0;if(o>0)if(n)h=0;else{const t=o-l;h=Math.min(100,Math.max(0,t/o*100))}return{isActive:r,isPaused:a,duration:o,remaining:l,finishesAt:c,progress:h,isAlexaTimer:!1}}static isISOTimestamp(t){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?([+-]\d{2}:\d{2}|Z)?$/.test(t)}static extractAlexaDevice(t,e){if(e.friendly_name){let t=e.friendly_name;if(t=t.replace(/\s*next\s*timer$/i,"").replace(/\s*timer$/i,"").replace(/\s*echo\s*timer$/i,"").replace(/\s*alexa\s*timer$/i,"").trim(),t)return t}if(t.includes("_next_timer")){const e=t.replace(/^sensor\./,"").replace(/_next_timer$/,"").replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());if(e)return e}return e.device_name?e.device_name:e.device?e.device:"Alexa Device"}static formatAlexaTimerName(t){return t.replace(/^sensor\./,"").replace(/_next_timer$/,"").replace(/_timer$/,"").replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase())}static parseDuration(t){if("number"==typeof t)return t;if("string"!=typeof t)return 0;if(t.includes(":")){const e=t.split(":").map(Number);if(3===e.length)return 3600*e[0]+60*e[1]+e[2];if(2===e.length)return 60*e[0]+e[1]}const e=parseFloat(t);return isNaN(e)?0:e}static formatRemainingTime(t,e=!0){if(t<=0)return"0:00";const i=Math.floor(t/3600),s=Math.floor(t%3600/60),r=Math.floor(t%60);return i>0?e?`${i}:${s.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}`:`${i}:${s.toString().padStart(2,"0")}`:e?`${s}:${r.toString().padStart(2,"0")}`:`${s}m`}static getTimerTitle(t,e,i){if(i)return i;if(!e||!t)return"Timer";const s=e.states[t];if(!s)return"Timer";if(this.isAlexaTimer(t)){const i=this.getAlexaTimerData(t,s,e);return(null==i?void 0:i.timerLabel)?i.timerLabel:this.formatAlexaTimerName(t)}return s.attributes.friendly_name||t.replace("timer.","").replace(/_/g," ")}static getTimerSubtitle(t,e=!0){if(!t)return"Timer not found";if(t.isAlexaTimer){if(t.finished)return t.userDefinedLabel?`${t.userDefinedLabel} timer complete`:"Timer complete";if(t.isActive&&t.remaining>0){const i=this.formatRemainingTime(t.remaining,e);return t.userDefinedLabel?`${i} remaining on ${t.userDefinedLabel} timer`:t.alexaDevice?`${i} remaining on ${t.alexaDevice}`:`${i} remaining`}if(t.isPaused&&t.remaining>0){const i=this.formatRemainingTime(t.remaining,e);return t.userDefinedLabel?`${t.userDefinedLabel} timer paused - ${i} left`:t.alexaDevice?`Timer paused on ${t.alexaDevice} - ${i} left`:`Timer paused - ${i} left`}return t.finished||0===t.remaining&&t.progress>=100?t.userDefinedLabel?`${t.userDefinedLabel} timer complete`:"Timer complete":t.alexaDevice?`No timers on ${t.alexaDevice}`:"No timers"}if(t.isActive){return`${this.formatRemainingTime(t.remaining,e)} remaining`}if(t.isPaused){return`Paused - ${this.formatRemainingTime(t.remaining,e)} left`}if(t.duration>0){return`Ready - ${this.formatRemainingTime(t.duration,e)}`}return"Timer ready"}static isTimerExpired(t){return!!t&&(t.isAlexaTimer?!!t.finished||0===t.remaining&&t.progress>=100:!t.isActive&&!t.isPaused&&t.progress>=100)}static getTimerStateColor(t,e="#4caf50"){return t?t.isAlexaTimer?t.isActive&&t.remaining>0?"#00d4ff":this.isTimerExpired(t)?"#ff4444":"#888888":t.isActive?"#4caf50":t.isPaused?"#ff9800":this.isTimerExpired(t)?"#f44336":"#9e9e9e":e}static discoverAlexaTimers(t){var e,i;if(!t||!t.states)return[];const s=[];for(const r in t.states)if(this.isAlexaTimer(r)){const a=t.states[r].attributes||{},n=null!==(e=this.parseJson(a.sorted_active))&&void 0!==e?e:[],o=null!==(i=this.parseJson(a.sorted_all))&&void 0!==i?i:[],l=Array.isArray(n)&&n.length>0;let c=!1;if(!l&&Array.isArray(o)&&o.length>0)for(const t of o){const e=null==t?void 0:t[1];if(e&&"PAUSED"===e.status&&"number"==typeof e.remainingTime&&e.remainingTime>0){c=!0;break}}if(l||c){s.push(r);continue}const h=this.getTimerData(r,t);h&&(h.isActive||h.isPaused)&&s.push(r)}return s}static hasAnyTimers(t,e){try{const t=e.attributes,i=this.parseJsonArray(t.sorted_active)||[],s=this.parseJsonArray(t.sorted_all)||[];return i.length>0||s.length>0}catch(i){return!1}}}ut.alexaIdCache=new Map;class mt{static parseISODate(t){try{const e=this.parseISODateManual(t);if(!isNaN(e))return e}catch(i){}const e=new Date(t);return!isNaN(e.getTime())&&this.isValidDateResult(e,t)?e.getTime():this.parseISODateFallback(t)}static isValidDateResult(t,e){const i=t.getTime(),s=new Date("1970-01-01").getTime(),r=new Date("2100-12-31").getTime();if(i<s||i>r)return!1;if("string"==typeof e&&e.includes("02-29")){const e=t.getFullYear();if(!this.isLeapYear(e))return!1}return!0}static isLeapYear(t){return t%4==0&&t%100!=0||t%400==0}static parseISODateManual(t){if("string"==typeof t&&t.includes("T")){if(/[+-]\d{2}:\d{2}$|Z$/.test(t))return new Date(t).getTime();{const[e,i]=t.split("T"),[s,r,a]=e.split("-").map(Number);if(!this.isValidDateComponents(s,r,a))throw new Error("Invalid date components");if(i&&i.includes(":")){const[t,e,n]=i.split(":").map(parseFloat);if(!this.isValidTimeComponents(t,e,n))throw new Error("Invalid time components");return new Date(s,r-1,a,t,e,n||0).getTime()}return new Date(s,r-1,a).getTime()}}return new Date(t).getTime()}static isValidDateComponents(t,e,i){if(isNaN(t)||isNaN(e)||isNaN(i))return!1;if(t<1970||t>2100)return!1;if(e<1||e>12)return!1;if(i<1||i>31)return!1;return!(i>[31,this.isLeapYear(t)?29:28,31,30,31,30,31,31,30,31,30,31][e-1])}static isValidTimeComponents(t,e,i){const s=parseInt(t),r=parseInt(e),a=parseInt(i);return!(isNaN(s)||isNaN(r)||isNaN(a))&&(!(s<0||s>23)&&(!(r<0||r>59)&&!(a<0||a>59)))}static parseISODateFallback(t){try{const e=Date.parse(t);return isNaN(e)?Date.now():e}catch(e){return Date.now()}}}class pt{static validateConfig(t){const e=[];if(!t)return e.push({field:"config",message:"Configuration object is missing or empty",severity:"critical",suggestion:"Provide a valid configuration object with at least a target_date field.",value:t}),{isValid:!1,errors:e,hasCriticalErrors:!0,hasWarnings:!1};t.target_date?this.isValidDateInput(t.target_date)||e.push({field:"target_date",message:"Invalid target_date format",severity:"critical",suggestion:'Use ISO date string (2025-12-31T23:59:59), entity ID (sensor.my_date), or template ({{ states("sensor.date") }}).',value:t.target_date}):t.timer_entity||t.auto_discover_alexa||e.push({field:"target_date",message:'Either "target_date", "timer_entity", or "auto_discover_alexa" must be provided',severity:"critical",suggestion:'Add target_date field with a valid date value like "2025-12-31T23:59:59" OR specify a timer_entity like "timer.my_timer" OR enable auto_discover_alexa.',value:void 0}),t.timer_entity&&!this.isValidEntityId(t.timer_entity)&&e.push({field:"timer_entity",message:"Invalid timer_entity format",severity:"warning",suggestion:'Use a valid entity ID like "timer.my_timer" or "sensor.alexa_timer".',value:t.timer_entity}),t.creation_date&&!this.isValidDateInput(t.creation_date)&&e.push({field:"creation_date",message:"Invalid creation_date format",severity:"warning",suggestion:"Use ISO date string, entity ID, or template. This field is optional.",value:t.creation_date});["text_color","background_color","progress_color"].forEach(i=>{t[i]&&!this.isValidColorInput(t[i])&&e.push({field:i,message:`Invalid ${i} format`,severity:"warning",suggestion:"Use hex (#ff0000), rgb/rgba, hsl/hsla, CSS color name, entity ID, or template.",value:t[i]})});["width","height","icon_size"].forEach(i=>{t[i]&&!this.isValidDimensionInput(t[i])&&e.push({field:i,message:`Invalid ${i} format`,severity:"warning",suggestion:"Use pixel values (100px), percentages (50%), or CSS units (2rem).",value:t[i]})}),t.aspect_ratio&&!this.isValidAspectRatioInput(t.aspect_ratio)&&e.push({field:"aspect_ratio",message:"Invalid aspect_ratio format",severity:"warning",suggestion:'Use format like "16/9", "4/3", or "1/1".',value:t.aspect_ratio}),void 0===t.stroke_width||this.isValidNumberInput(t.stroke_width,1,50)||e.push({field:"stroke_width",message:"Invalid stroke_width value",severity:"warning",suggestion:"Must be a number between 1 and 50.",value:t.stroke_width});["show_months","show_days","show_hours","show_minutes","show_seconds","expired_animation","show_progress_text"].forEach(i=>{void 0===t[i]||this.isValidBooleanInput(t[i])||e.push({field:i,message:`Invalid ${i} value`,severity:"warning",suggestion:"Must be true or false (boolean value).",value:t[i]})});["title","subtitle","expired_text"].forEach(i=>{t[i]&&!this.isValidTextInput(t[i])&&e.push({field:i,message:`Invalid ${i} - contains potentially unsafe content`,severity:"critical",suggestion:"Remove script tags, javascript: URLs, and event handlers for security.",value:t[i]})}),t.styles&&!this.isValidStylesInput(t.styles)&&e.push({field:"styles",message:"Invalid styles object structure",severity:"warning",suggestion:"Must contain valid style arrays for card, title, subtitle, or progress_circle.",value:t.styles}),this._addHelpfulValidations(t,e);const i=this._generateSafeConfig(t,e),s=e.filter(t=>"critical"===t.severity),r=e.filter(t=>"warning"===t.severity);return{isValid:0===s.length&&0===r.length,errors:e,hasCriticalErrors:s.length>0,hasWarnings:r.length>0,safeConfig:i}}static _addHelpfulValidations(t,e){}static _generateSafeConfig(t,e){const i={...t};return e.forEach(t=>{if("critical"===t.severity||"warning"===t.severity)switch(t.field){case"target_date":if(!i.target_date&&!i.timer_entity){const t=new Date;t.setDate(t.getDate()+1),i.target_date=t.toISOString()}break;case"background_color":this.isValidColorInput(i.background_color)||(i.background_color="#1a1a1a");break;case"progress_color":this.isValidColorInput(i.progress_color)||(i.progress_color="#4caf50");break;case"stroke_width":this.isValidNumberInput(i.stroke_width,1,50)||(i.stroke_width=15);break;case"icon_size":this.isValidDimensionInput(i.icon_size)||(i.icon_size=100)}}),i}static validateConfigLegacy(t){const e=this.validateConfig(t);if(e.hasCriticalErrors){const t=e.errors.filter(t=>"critical"===t.severity);throw new Error(`Configuration validation failed:\n• ${t.map(t=>t.message).join("\n• ")}`)}}static isValidDateInput(t){if(!t)return!1;if(this.isTemplate(t))return!0;if("string"==typeof t&&t.includes("."))return!0;if("string"==typeof t)try{const e=new Date(t);return!isNaN(e.getTime())}catch(e){return!1}return!1}static isValidColorInput(t){if(!t)return!1;if(this.isTemplate(t)||"string"==typeof t&&t.includes("."))return!0;if("string"!=typeof t)return!1;if(/^#([0-9A-F]{3}){1,2}$/i.test(t))return!0;if(/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+\s*)?\)$/i.test(t))return!0;if(/^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(,\s*[\d.]+\s*)?\)$/i.test(t))return!0;return["red","blue","green","yellow","orange","purple","pink","brown","black","white","gray","grey","cyan","magenta","lime","maroon","navy","olive","teal","silver","gold","indigo","violet","transparent","currentColor","inherit","initial","unset"].includes(t.toLowerCase())}static isValidDimensionInput(t){if(!t)return!1;if(this.isTemplate(t)||"string"==typeof t&&t.includes("."))return!0;if("number"==typeof t)return!0;if("string"!=typeof t)return!1;const e=t.match(/^(\d+(?:\.\d+)?)px$/i);if(e){const t=parseFloat(e[1]);return t>=0&&t<=1e4}const i=t.match(/^(\d+(?:\.\d+)?)%$/i);if(i){const t=parseFloat(i[1]);return t>=0&&t<=1e3}const s=["em","rem","vh","vw","vmin","vmax","ch","ex"];for(const r of s){const e=new RegExp(`^(\\d+(?:\\.\\d+)?)${r}$`,"i"),i=t.match(e);if(i){const t=parseFloat(i[1]);return t>=0&&t<=1e3}}return["auto","fit-content","min-content","max-content"].includes(t.toLowerCase())}static isValidAspectRatioInput(t){if(!t)return!1;if(this.isTemplate(t)||"string"==typeof t&&t.includes("."))return!0;if("string"!=typeof t)return!1;const e=t.match(/^(\d+(?:\.\d+)?)\/(\d+(?:\.\d+)?)$/);if(e){const t=parseFloat(e[1]),i=parseFloat(e[2]);return t>0&&i>0&&t<=20&&i<=20}return!1}static isValidNumberInput(t,e=-1/0,i=1/0){if(null==t)return!1;if("string"==typeof t){if(this.isTemplate(t)||t.includes("."))return!0;const s=parseFloat(t);return!isNaN(s)&&s>=e&&s<=i}return"number"==typeof t&&!isNaN(t)&&t>=e&&t<=i}static isValidBooleanInput(t){return"boolean"==typeof t}static isValidTextInput(t){if(!t)return!0;if(this.isTemplate(t)||"string"==typeof t&&t.includes("."))return!0;if("string"!=typeof t)return!1;return![/<script/i,/javascript:/i,/vbscript:/i,/on\w+\s*=/i,/<iframe/i,/<object/i,/<embed/i,/<form/i].some(e=>e.test(t))}static isValidStylesInput(t){if(!t||"object"!=typeof t)return!1;const e=["card","title","subtitle","progress_circle"],i=Object.keys(t);return!!i.every(t=>e.includes(t))&&i.every(e=>Array.isArray(t[e]))}static isTemplate(t){return"string"==typeof t&&t.includes("{{")&&t.includes("}}")}static isValidEntityId(t){if(!t||"string"!=typeof t)return!1;if(this.isTemplate(t))return!0;return/^[a-z_]+\.[a-z0-9_]+$/.test(t)}}class ft{constructor(){this.templateResults=new Map,this.templateCacheLimit=100}async evaluateTemplate(t,e){if(!e||!t)return t;const i=t;if(this.templateResults.has(i)){const t=this.templateResults.get(i);if(t&&Date.now()-t.timestamp<5e3)return t.result}try{if(!this.isValidTemplate(t))throw new Error("Invalid template format");const s=await e.callApi("POST","template",{template:t});if("unknown"===s||"unavailable"===s||""===s||null===s){const e=this.extractFallbackFromTemplate(t);if(e&&e!==t)return this.templateResults.set(i,{result:e,timestamp:Date.now()}),this.enforceTemplateCacheLimit(),e}return this.templateResults.set(i,{result:s,timestamp:Date.now()}),this.enforceTemplateCacheLimit(),s}catch(s){const e=this.extractFallbackFromTemplate(t);return this.templateResults.set(i,{result:e,timestamp:Date.now()}),this.enforceTemplateCacheLimit(),e}}extractFallbackFromTemplate(t){if(!t||"string"!=typeof t)return t;try{const e=t.replace(/^\{\{\s*/,"").replace(/\s*\}\}$/,"").trim(),i=/^(.+?)\s+or\s+['"`]([^'"`]+)['"`]$/,s=e.match(i);if(s&&s[2])return s[2];const r=/^(.+?)\s+or\s+(.+?)\s+or\s+['"`]([^'"`]+)['"`]$/,a=e.match(r);if(a&&a[3])return a[3];const n=/^['"`]([^'"`]+)['"`]\s+if\s+(.+?)\s+else\s+['"`]([^'"`]+)['"`]$/,o=e.match(n);if(o&&o[3])return o[3];const l=/^(.+?)\s+if\s+(.+?)\s+else\s+['"`]([^'"`]+)['"`]$/,c=e.match(l);return c&&c[3]?c[3]:"Unavailable"}catch(e){return"Template Error"}}isTemplate(t){return"string"==typeof t&&t.includes("{{")&&t.includes("}}")}isValidTemplate(t){if(!t||"string"!=typeof t)return!1;if(!t.includes("{{")||!t.includes("}}"))return!1;if((t.match(/\{\{/g)||[]).length!==(t.match(/\}\}/g)||[]).length)return!1;return!!t.replace(/\{\{\s*/,"").replace(/\s*\}\}/,"").trim()}async resolveValue(t){var e,i;if(!t)return;if(this.isTemplate(t)){const i=(null===(e=this.card)||void 0===e?void 0:e.hass)||null;return await this.evaluateTemplate(t,i)||void 0}const s=null===(i=this.card)||void 0===i?void 0:i.hass;if("string"==typeof t&&t.includes(".")&&s&&s.states[t]){const e=s.states[t];if(!e)return;return e.state}return t}clearTemplateCache(){this.templateResults.clear()}enforceTemplateCacheLimit(){if(this.templateResults.size<=this.templateCacheLimit)return;const t=Array.from(this.templateResults.entries()).sort((t,e)=>t[1].timestamp-e[1].timestamp),e=t.length-this.templateCacheLimit;for(let i=0;i<e;i++)this.templateResults.delete(t[i][0])}hasTemplatesInConfig(t){if(!t)return!1;return["target_date","creation_date","title","subtitle","text_color","background_color","progress_color","primary_color","secondary_color"].some(e=>t[e]&&this.isTemplate(t[e]))}escapeHtml(t){return null==t||void 0===t?"":String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}}class gt{constructor(t,e){this.templateService=t,this.dateParser=e,this.timeRemaining={months:0,days:0,hours:0,minutes:0,seconds:0,total:0},this.expired=!1,this.lastAlexaTimerData=null}async updateCountdown(t,e){try{if(t.timer_entity&&e){const i=ut.getTimerData(t.timer_entity,e);if(i)return this.timeRemaining=this._timerDataToCountdownState(i),this.expired=ut.isTimerExpired(i),this.timeRemaining}if(!t.timer_entity&&t.auto_discover_alexa&&e){const t=ut.discoverAlexaTimers(e);if(t.length>0){let i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isActive});if(i||(i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isPaused})),i){const t=ut.getTimerData(i,e);if(t)return this.lastAlexaTimerData=t,this.timeRemaining=this._timerDataToCountdownState(t),this.expired=ut.isTimerExpired(t),this.timeRemaining}return this.lastAlexaTimerData=null,this.timeRemaining={months:0,days:0,hours:0,minutes:0,seconds:0,total:0},this.expired=!1,this.timeRemaining}return this.lastAlexaTimerData=null,this.timeRemaining={months:0,days:0,hours:0,minutes:0,seconds:0,total:0},this.expired=!1,this.timeRemaining}if(!t.target_date)return this.timeRemaining;const i=(new Date).getTime(),s=await this.templateService.resolveValue(t.target_date);if(!s)return this.timeRemaining;const r=this.dateParser.parseISODate(s);if(isNaN(r))return this.timeRemaining;const a=r-i;if(a>0){const{show_months:e,show_days:i,show_hours:s,show_minutes:r,show_seconds:n}=t;let o=a,l=0,c=0,h=0,d=0,u=0;if(e&&(l=Math.floor(o/2630016e3),o%=2630016e3),i)c=Math.floor(o/864e5),o%=864e5;else if(e&&!i){const t=Math.floor(o/864e5);l+=Math.floor(t/30.44),o%=864e5}if(s)h=Math.floor(o/36e5),o%=36e5;else if((e||i)&&!s){const t=Math.floor(o/36e5);i?c+=Math.floor(t/24):e&&(l+=Math.floor(t/(24*30.44))),o%=36e5}if(r)d=Math.floor(o/6e4),o%=6e4;else if((e||i||s)&&!r){const t=Math.floor(o/6e4);s?h+=Math.floor(t/60):i?c+=Math.floor(t/1440):e&&(l+=Math.floor(t/43833.6)),o%=6e4}if(n)u=Math.floor(o/1e3);else if((e||i||s||r)&&!n){const t=Math.floor(o/1e3);r?d+=Math.floor(t/60):s?h+=Math.floor(t/3600):i?c+=Math.floor(t/86400):e&&(l+=Math.floor(t/2630016))}this.timeRemaining={months:l,days:c,hours:h,minutes:d,seconds:u,total:a},this.expired=!1}else this.timeRemaining={months:0,days:0,hours:0,minutes:0,seconds:0,total:0},this.expired=!0;return this.timeRemaining}catch(i){return this.timeRemaining}}async calculateProgress(t,e){if(t.timer_entity&&e){const i=ut.getTimerData(t.timer_entity,e);return i?i.progress:0}if(!t.timer_entity&&t.auto_discover_alexa&&e){const t=ut.discoverAlexaTimers(e);if(t.length>0){let i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isActive});if(i||(i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isPaused})),i){const t=ut.getTimerData(i,e);if(t)return t.progress}}}const i=await this.templateService.resolveValue(t.target_date);if(!i)return 0;const s=this.dateParser.parseISODate(i),r=Date.now();let a;if(t.creation_date){const e=await this.templateService.resolveValue(t.creation_date);a=e?this.dateParser.parseISODate(e):r}else a=r;const n=s-a;if(n<=0)return 100;const o=r-a,l=Math.min(100,Math.max(0,o/n*100));return this.expired?100:l}getMainDisplay(t,e){if(t.timer_entity&&e){const i=ut.getTimerData(t.timer_entity,e);if(i){const{hours:t,minutes:e,seconds:s}=this.timeRemaining;return i.isAlexaTimer?ut.isTimerExpired(i)?{value:"🔔",label:ut.getTimerSubtitle(i,!1)}:t>0?{value:t.toString(),label:1===t?"hour left":"hours left"}:e>0?{value:e.toString(),label:1===e?"minute left":"minutes left"}:{value:s.toString(),label:1===s?"second left":"seconds left"}:t>0?{value:t.toString(),label:1===t?"hour":"hours"}:e>0?{value:e.toString(),label:1===e?"minute":"minutes"}:{value:s.toString(),label:1===s?"second":"seconds"}}}if(!t.timer_entity&&t.auto_discover_alexa&&e){const t=ut.discoverAlexaTimers(e);if(t.length>0){let i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isActive});if(i||(i=t.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isPaused})),i){const t=ut.getTimerData(i,e);if(t){this.lastAlexaTimerData=t;const{hours:e,minutes:i,seconds:s}=this.timeRemaining;return ut.isTimerExpired(t)?{value:"🔔",label:ut.getTimerSubtitle(t,!1)}:e>0?{value:e.toString(),label:1===e?"hour left":"hours left"}:i>0?{value:i.toString(),label:1===i?"minute left":"minutes left"}:{value:s.toString(),label:1===s?"second left":"seconds left"}}}if(this.lastAlexaTimerData&&ut.isTimerExpired(this.lastAlexaTimerData))return{value:"🔔",label:ut.getTimerSubtitle(this.lastAlexaTimerData,!1)}}}const{show_months:i,show_days:s,show_hours:r,show_minutes:a,show_seconds:n}=t,{months:o,days:l,hours:c,minutes:h,seconds:d}=this.timeRemaining;return this.expired?t.auto_discover_alexa?this.lastAlexaTimerData?{value:"🔔",label:ut.getTimerSubtitle(this.lastAlexaTimerData,!1)}:{value:"🔔",label:"Timer complete"}:{value:"🎉",label:"Completed!"}:i&&o>0?{value:o.toString(),label:1===o?"month left":"months left"}:s&&l>0?{value:l.toString(),label:1===l?"day left":"days left"}:r&&c>0?{value:c.toString(),label:1===c?"hour left":"hours left"}:a&&h>0?{value:h.toString(),label:1===h?"minute left":"minutes left"}:n&&d>=0?{value:d.toString(),label:1===d?"second left":"seconds left"}:{value:"0",label:"seconds left"}}getSubtitle(t,e){if(t.timer_entity&&e){const i=ut.getTimerData(t.timer_entity,e);return i?ut.getTimerSubtitle(i,!1!==t.show_seconds):"Timer not found"}if(!t.timer_entity&&t.auto_discover_alexa&&e){const i=ut.discoverAlexaTimers(e);if(i.length>0){let s=i.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isActive});if(s||(s=i.find(t=>{const i=ut.getTimerData(t,e);return i&&i.isPaused})),s){const i=ut.getTimerData(s,e);if(i)return this.lastAlexaTimerData=i,ut.getTimerSubtitle(i,!1!==t.show_seconds)}if(this.lastAlexaTimerData&&ut.isTimerExpired(this.lastAlexaTimerData))return ut.getTimerSubtitle(this.lastAlexaTimerData,!1!==t.show_seconds)}return"No timers"}if(this.expired){if(t.auto_discover_alexa)return this.lastAlexaTimerData?ut.getTimerSubtitle(this.lastAlexaTimerData,!1!==t.show_seconds):"Timer complete";const{expired_text:e="Completed! 🎉"}=t;return e}const{months:i,days:s,hours:r,minutes:a,seconds:n}=this.timeRemaining||{months:0,days:0,hours:0,minutes:0,seconds:0},{show_months:o,show_days:l,show_hours:c,show_minutes:h,show_seconds:d}=t,u=[];o&&i>0&&u.push({value:i,unit:1===i?"month":"months"}),l&&s>0&&u.push({value:s,unit:1===s?"day":"days"}),c&&r>0&&u.push({value:r,unit:1===r?"hour":"hours"}),h&&a>0&&u.push({value:a,unit:1===a?"minute":"minutes"}),d&&n>0&&u.push({value:n,unit:1===n?"second":"seconds"}),0===u.length&&(o?u.push({value:i,unit:1===i?"month":"months"}):l?u.push({value:s,unit:1===s?"day":"days"}):c?u.push({value:r,unit:1===r?"hour":"hours"}):h?u.push({value:a,unit:1===a?"minute":"minutes"}):d&&u.push({value:n,unit:1===n?"second":"seconds"}));if([o,l,c,h,d].filter(Boolean).length<=2&&u.length>0){if(1===u.length)return`${u[0].value} ${u[0].unit}`;if(2===u.length)return`${u[0].value} ${u[0].unit} and ${u[1].value} ${u[1].unit}`}return u.map(t=>{const e=t.unit.charAt(0);return`${t.value}${e}`}).join(" ")||"0s"}_timerDataToCountdownState(t){return{months:0,days:0,hours:Math.floor(t.remaining/3600),minutes:Math.floor(t.remaining%3600/60),seconds:Math.floor(t.remaining%60),total:1e3*t.remaining}}getTimeRemaining(){return this.timeRemaining}isExpired(){return this.expired}getAvailableAlexaTimers(t){return t?ut.discoverAlexaTimers(t):[]}getCurrentTimerEntity(t,e){if(t.timer_entity)return t.timer_entity;if(t.auto_discover_alexa&&e){const t=ut.discoverAlexaTimers(e);if(t.length>0){for(const i of t){const t=ut.getTimerData(i,e);if(t&&t.isActive)return i}return t[0]}}return null}}class _t{constructor(){this.cache={dynamicIconSize:null,dynamicStrokeWidth:null,customStyles:null,lastConfigHash:null}}processStyles(t){return t&&Array.isArray(t)?t.map(t=>{try{return"string"==typeof t?t:"object"==typeof t&&null!==t?Object.entries(t).map(([t,e])=>`${t}: ${e}`).join("; "):""}catch(e){return""}}).join("; "):""}buildStylesObject(t){const e=JSON.stringify(t.styles||{});if(null!==this.cache.customStyles&&this.cache.lastConfigHash===e)return this.cache.customStyles;const{styles:i={}}=t;try{const t={card:this.processStyles(i.card),title:this.processStyles(i.title),subtitle:this.processStyles(i.subtitle),progress_circle:this.processStyles(i.progress_circle)};return this.cache.customStyles=t,this.cache.lastConfigHash=e,t}catch(s){return this.cache.customStyles={card:"",title:"",subtitle:"",progress_circle:""},this.cache.customStyles}}_getCardDimensions(t,e,i){const s=300,r=150;let a=s,n=r;if(t&&e){a=this.parseDimension(t)||s,n=this.parseDimension(e)||r}else if(t&&i){a=this.parseDimension(t)||s;const[e,r]=i.split("/").map(parseFloat);!isNaN(e)&&!isNaN(r)&&e>0&&(n=a*(r/e))}else if(e&&i){n=this.parseDimension(e)||r;const[t,s]=i.split("/").map(parseFloat);!isNaN(t)&&!isNaN(s)&&s>0&&(a=n*(t/s))}else if(i){const[t,e]=i.split("/").map(parseFloat);!isNaN(t)&&!isNaN(e)&&t>0&&(n=s*(e/t)),a=s}return(!a||isNaN(a)||a<=0)&&(a=s),(!n||isNaN(n)||n<=0)&&(n=r),{cardWidth:a,cardHeight:n}}calculateDynamicIconSize(t,e,i,s){const r=JSON.stringify({width:t,height:e,aspect_ratio:i,icon_size:s});if(null!==this.cache.dynamicIconSize&&this.cache.lastIconConfigHash===r)return this.cache.dynamicIconSize;try{const{cardWidth:a,cardHeight:n}=this._getCardDimensions(t,e,i),o=.4*Math.min(a,n);let l=o;if(s&&"100px"!==s){const t="string"==typeof s?parseInt(s.replace("px","")):"number"==typeof s?s:o;l=isNaN(t)?o:t}return this.cache.dynamicIconSize=Math.max(_t.MIN_ICON_SIZE,Math.min(l,_t.MAX_ICON_SIZE)),this.cache.lastIconConfigHash=r,this.cache.dynamicIconSize}catch(a){return this.cache.dynamicIconSize=_t.MIN_ICON_SIZE,this.cache.dynamicIconSize}}calculateDynamicStrokeWidth(t,e){const i=JSON.stringify({iconSize:t,stroke_width:e});if(null!==this.cache.dynamicStrokeWidth&&this.cache.lastStrokeConfigHash===i)return this.cache.dynamicStrokeWidth;try{if(e&&"number"==typeof e)this.cache.dynamicStrokeWidth=Math.max(_t.MIN_STROKE,Math.min(e,_t.MAX_STROKE));else{const e=.15,i=Math.round(t*e);this.cache.dynamicStrokeWidth=Math.max(_t.MIN_STROKE,Math.min(i,_t.MAX_STROKE))}return this.cache.lastStrokeConfigHash=i,this.cache.dynamicStrokeWidth}catch(s){return this.cache.dynamicStrokeWidth=_t.MIN_STROKE,this.cache.dynamicStrokeWidth}}calculateProportionalSizes(t,e,i){try{const{cardWidth:s,cardHeight:r}=this._getCardDimensions(t,e,i),a=45e3,n=Math.sqrt(s*r/a);return{titleSize:Math.max(1.2,Math.min(2.2,1.6*n)),subtitleSize:Math.max(.9,Math.min(1.4,1.1*n)),cardWidth:s,cardHeight:r}}catch(s){return{titleSize:1.6,subtitleSize:1.1,cardWidth:300,cardHeight:150}}}parseDimension(t){try{if("number"==typeof t)return t;if("string"!=typeof t)return null;const e=t.toLowerCase();if(e.includes("%")){const t=parseFloat(e.replace("%",""));return isNaN(t)?null:t/100*300}if(e.includes("px")){const t=parseFloat(e.replace("px",""));return isNaN(t)?null:t}const i=parseFloat(e);return isNaN(i)?null:i}catch(e){return null}}generateCardDimensionStyles(t,e,i){const s=[];if(t){const e=this._formatDimensionValue(t);e&&s.push(`width: ${e}`)}if(e){const t=this._formatDimensionValue(e);t&&s.push(`height: ${t}`)}else i&&!e&&s.push(`aspect-ratio: ${i}`);return e||i||s.push("min-height: 120px"),s}_formatDimensionValue(t){if(!t)return null;const e=String(t).trim();if(/^[\d.]+\s*(px|%|em|rem|vh|vw|vmin|vmax|ch|ex)$/i.test(e))return e;const i=parseFloat(e);return isNaN(i)?null:`${i}px`}clearCache(){this.cache={dynamicIconSize:null,dynamicStrokeWidth:null,customStyles:null,lastConfigHash:null}}getCardDimensions(t,e,i){return this._getCardDimensions(t,e,i)}}_t.MIN_ICON_SIZE=40,_t.MAX_ICON_SIZE=300,_t.MIN_STROKE=4,_t.MAX_STROKE=50;class yt{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 vt=(t,e,i,s)=>{!function(t,e,i){const s=new CustomEvent(e,{bubbles:!0,cancelable:!0,composed:!0,detail:i});t.dispatchEvent(s)}(t,"hass-action",{config:i,action:s})},xt=(t,e)=>{const i=(()=>{const t=document.body;if(t.querySelector("action-handler"))return t.querySelector("action-handler");const e=document.createElement("action-handler");return t.appendChild(e),e})();i&&i.bind(t,e)},bt=(t=>(...e)=>({_$litDirective$:t,values:e}))(class extends yt{update(t,[e]){return xt(t.element,e),W}render(t){return W}});function $t(t){return void 0!==t&&"none"!==t.action}class wt extends nt{constructor(){super(...arguments),this.errors=[],this.title="Configuration Issues"}static get styles(){return n`
:host {
display: block;
font-family: var(--font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif);
}
.error-container {
background: #332022;
border: 1px solid #582533ff;
border-radius: 1px;
padding: 16px;
margin: 8px;
color: #ffffff;
}
.error-list {
list-style: none;
padding: 0;
margin: 0;
}
.error-item {
margin-bottom: 8px;
line-height: 1.4;
}
.error-field {
font-weight: 600;
color: #D74133;
}
`}render(){if(!this.errors||0===this.errors.length)return V``;const t=this.errors.filter(t=>"critical"===t.severity||"warning"===t.severity);return 0===t.length?V``:V`
<div class="error-container">
<ul class="error-list">
${t.map(t=>V`
<li class="error-item">
<span class="error-field">${t.field}:</span> ${t.message}
</li>
`)}
</ul>
</div>
`}}t([ht({type:Array})],wt.prototype,"errors",void 0),t([ht({type:String})],wt.prototype,"title",void 0),customElements.define("error-display",wt);class St extends nt{static async getConfigElement(){return document.createElement("timeflow-card-editor")}static get styles(){return n`
:host {
display: block;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
color: var(--primary-text-color, #222);
--progress-color: var(--progress-color, #4caf50);
}
/* FIXED: Set initial background immediately to prevent white flash */
ha-card {
display: flex;
flex-direction: column;
padding: 0;
border-radius: 22px;
position: relative;
overflow: hidden;
/* IMPORTANT: Set default background immediately */
background: var(--card-background, var(--primary-background-color, #1a1a1a));
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
border: none;
/* REMOVED: transition that causes flash - only animate specific properties if needed */
/* transition: background-color 0.3s ease; */
min-height: 120px; /* Prevent layout shift */
user-select: none; /* Prevent text selection during interactions */
}
/* Make card interactive when actions are configured */
ha-card[actionHandler] {
cursor: pointer;
}
ha-card[actionHandler]:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
ha-card[actionHandler]:active {
transform: translateY(0);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
/* Error message styling */
.error {
color: #721c24;
padding: 12px;
border-radius: 16px;
white-space: pre-wrap;
word-break: break-word;
}
/* FIXED: Only show card after initialization to prevent white flash */
ha-card:not(.initialized) {
opacity: 0;
}
ha-card.initialized {
opacity: 1;
transition: opacity 0.2s ease-in;
}
ha-card.expired {
animation: celebration 0.8s ease-in-out;
}
.card-content {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
height: 100%;
/* FIXED: Ensure content has proper background inheritance */
background: inherit;
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 0;
}
.title-section {
flex: 1;
display: flex;
flex-direction: column;
gap: 2px;
}
.title {
font-size: var(--timeflow-title-size, 1.5rem);
font-weight: 500;
margin: 0;
opacity: 0.9;
line-height: 1.3;
letter-spacing: -0.01em;
color: var(--timeflow-card-text-color, inherit);
}
.subtitle {
font-size: var(--timeflow-subtitle-size, 1rem);
opacity: 0.65;
margin: 0;
font-weight: 400;
line-height: 1.2;
color: var(--timeflow-card-text-color, inherit);
}
.progress-section {
flex-shrink: 0;
margin-left: auto;
}
.content {
display: flex;
align-items: flex-end;
justify-content: flex-end;
margin-top: auto;
padding-top: 12px;
}
.progress-circle {
opacity: 0.9;
}
@keyframes celebration {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
ha-card {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
}
`}constructor(){super(),this.hass=null,this.config=this.getStubConfig(),this._resolvedConfig=this.getStubConfig(),this._progress=0,this._countdown={months:0,days:0,hours:0,minutes:0,seconds:0,total:0},this._expired=!1,this._validationResult=null,this._initialized=!1,this._timerId=null,this.templateService=new ft,this.countdownService=new gt(this.templateService,mt),this.styleManager=new _t;const t=this.getStubConfig();this.config=t,this._resolvedConfig=t}static getStubConfig(){return{type:"custom:timeflow-card",target_date:"2025-12-31T23:59:59",creation_date:"2024-12-31T23:59:59",timer_entity:"",title:"New Year Countdown",show_days:!0,show_hours:!0,show_minutes:!0,show_seconds:!0,progress_color:"#C0F950",background_color:"#1a1a1a",stroke_width:15,icon_size:100,expired_animation:!0,expired_text:"Completed! 🎉",show_progress_text:!1}}getStubConfig(){return St.getStubConfig()}setConfig(t){try{const e=pt.validateConfig(t);if(this._validationResult=e,e.hasCriticalErrors)this.config=e.safeConfig||this.getStubConfig(),this._resolvedConfig={...this.config};else{if(e.hasWarnings)return this.config={...t},this._resolvedConfig={...t},this._initialized=!0,void this.requestUpdate();this.config={...t},this._resolvedConfig={...t}}this._initialized=!1,this.templateService.clearTemplateCache(),this.styleManager.clearCache(),this._updateCountdownAndRender().then(()=>{this._initialized=!0,this.requestUpdate()})}catch(e){this._validationResult={isValid:!1,errors:[{field:"config",message:e.message||"Unexpected configuration error",severity:"critical",suggestion:"Check console for details and verify your configuration syntax.",value:t}],hasCriticalErrors:!0,hasWarnings:!1,safeConfig:this.getStubConfig()},this.config=this.getStubConfig(),this._resolvedConfig={...this.config},this._initialized=!0,this.requestUpdate()}}firstUpdated(){this.templateService.card=this,this._updateCountdownAndRender().then(()=>{this._initialized=!0,this.requestUpdate(),this._startCountdownUpdates()})}disconnectedCallback(){super.disconnectedCallback(),this._stopCountdownUpdates()}updated(t){(t.has("hass")||t.has("config"))&&(this.templateService.clearTemplateCache(),this._updateCountdownAndRender())}_startCountdownUpdates(){this._stopCountdownUpdates(),this._timerId=setInterval(()=>{this._updateCountdownAndRender()},1e3)}_stopCountdownUpdates(){this._timerId&&(clearInterval(this._timerId),this._timerId=null)}async _updateCountdownAndRender(){var t;if(null===(t=this._validationResult)||void 0===t?void 0:t.hasCriticalErrors)return;const e={...this.config},i=["target_date","creation_date","timer_entity","title","subtitle","text_color","background_color","progress_color","primary_color","secondary_color","expired_text"];for(const s of i)if("string"==typeof e[s]&&this.templateService.isTemplate(e[s])){const t=await this.templateService.resolveValue(e[s]);e[s]=t||void 0}this._resolvedConfig=e,await this.countdownService.updateCountdown(e,this.hass),this._countdown={...this.countdownService.getTimeRemaining()},this._expired=this.countdownService.isExpired(),this._progress=await this.countdownService.calculateProgress(e,this.hass),this.requestUpdate()}render(){return this._validationResult&&!this._validationResult.isValid?V`
<error-display
.errors="${this._validationResult.errors}"
.title="${this._validationResult.hasCriticalErrors?"Configuration Error":"Configuration Issues"}"
></error-display>
`:this._renderCard()}_renderCard(){var t;const{title:e,subtitle:i,text_color:s,background_color:r,progress_color:a,stroke_width:n,icon_size:o,expired_animation:l=!0,expired_text:c="Completed! 🎉",width:h,height:d,aspect_ratio:u,show_progress_text:m=!1}=this._resolvedConfig,p=r||"var(--card-background, var(--primary-background-color, #1a1a1a))",f=s||"var(--primary-text-color, #fff)",g=a||s||"var(--progress-color, #4caf50)",_=this.styleManager.calculateDynamicIconSize(h,d,u,o),y=this.styleManager.calculateDynamicStrokeWidth(_,n),v=this.styleManager.calculateProportionalSizes(h,d,u),x=this.styleManager.generateCardDimensionStyles(h,d,u),b=[`background: ${p}`,`color: ${f}`,`--timeflow-card-background-color: ${p}`,`--timeflow-card-text-color: ${f}`,`--timeflow-card-progress-color: ${g}`,`--timeflow-card-icon-size: ${_}px`,`--timeflow-card-stroke-width: ${y}`,`--timeflow-title-size: ${v.titleSize}rem`,`--timeflow-subtitle-size: ${v.subtitleSize}rem`,`--progress-text-color: ${f}`,...x].join("; ");let $;if(this._resolvedConfig.timer_entity&&this.hass){const t=ut.getTimerData(this._resolvedConfig.timer_entity,this.hass);$=t?this._expired&&t.isAlexaTimer?ut.getTimerSubtitle(t,!1!==this._resolvedConfig.show_seconds):this._expired?c:i||ut.getTimerSubtitle(t,!1!==this._resolvedConfig.show_seconds):this._expired?c:i||this.countdownService.getSubtitle(this._resolvedConfig,this.hass)}else $=this._resolvedConfig.auto_discover_alexa?i||this.countdownService.getSubtitle(this._resolvedConfig,this.hass):this._expired?c:i||this.countdownService.getSubtitle(this._resolvedConfig,this.hass);let w=e;(null==w||"string"==typeof w&&""===w.trim())&&(w=this._resolvedConfig.timer_entity&&this.hass?ut.getTimerTitle(this._resolvedConfig.timer_entity,this.hass):this._resolvedConfig.auto_discover_alexa?"Countdown Timer":this._expired?c:"Countdown Timer");const S=[this._initialized?"initialized":"",this._expired&&l?"expired":""].filter(Boolean).join(" "),A={...this._resolvedConfig};A.timer_entity&&!A.entity&&(A.entity=A.timer_entity),A.entity&&!A.tap_action&&(A.tap_action={action:"more-info"}),null===(t=A.tap_action)||void 0===t||t.action;const T=A.tap_action||A.hold_action||A.double_tap_action;return V`
<ha-card
class="${S}"
style="${b}"
?actionHandler=${T}
.actionHandler=${T?(C=A,bt({hasHold:$t(C.hold_action),hasDoubleClick:$t(C.double_tap_action)})):void 0}
@action=${T&&this.hass?function(t,e){return t=>{vt(t.target,0,e,t.detail.action)}}(this.hass,A):void 0}
>
<div class="card-content">
<header class="header">
<div class="title-section">
<h2 class="title" aria-live="polite">${w}</h2>
<p class="subtitle" aria-live="polite">${$}</p>
</div>
</header>
<div class="content" role="group" aria-label="Countdown Progress">
<div class="progress-section">
<progress-circle
class="progress-circle"
.progress="${this._progress}"
.color="${g}"
.size="${_}"
.strokeWidth="${y}"
.showProgressText="${!0===m}"
aria-label="Countdown progress: ${Math.round(this._progress)}%"
></progress-circle>
</div>
</div>
</div>
</ha-card>
`;var C}getCardSize(){const{aspect_ratio:t="2/1",height:e}=this.config;if(e){const t=parseInt("string"==typeof e?e:e.toString());return t<=100?1:t<=150?2:t<=200?3:4}if(t){const[e,i]=t.split("/").map(Number);if(!e||!i)return 3;const s=i/e;return s>=1.5?4:s>=1?3:2}return 3}static get version(){return"3.0.3"}}t([ht({type:Object})],St.prototype,"hass",void 0),t([ht({type:Object})],St.prototype,"config",void 0),t([dt()],St.prototype,"_resolvedConfig",void 0),t([dt()],St.prototype,"_progress",void 0),t([dt()],St.prototype,"_countdown",void 0),t([dt()],St.prototype,"_expired",void 0),t([dt()],St.prototype,"_validationResult",void 0),t([dt()],St.prototype,"_initialized",void 0);class At extends nt{static get styles(){return n`
:host {
display: inline-block;
vertical-align: middle;
}
.progress-wrapper {
position: relative;
}
svg {
display: block;
margin: 0 auto;
}
.progress-text {
font-size: 16px;
font-weight: bold;
fill: var(--progress-text-color, #f4f5f4ff);
dominant-baseline: middle;
text-anchor: middle;
pointer-events: none;
user-select: none;
}
.updating {
transition: stroke-dashoffset 0.3s ease;
}
`}constructor(){super(),this.progress=0,this.color="#4CAF50",this.size=100,this.strokeWidth=15,this.showProgressText=!1,this.progress=0,this.color="#4CAF50",this.size=100,this.strokeWidth=15,this.showProgressText=!1}updated(t){var e;if(t.has("progress")){const t=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(".progress-bar");t&&(t.classList.add("updating"),setTimeout(()=>{t&&t.classList.remove("updating")},400))}}updateProgress(t,e=!0){var i;if(e)this.progress=t;else{const e=null===(i=this.renderRoot)||void 0===i?void 0:i.querySelector(".progress-bar");this.progress=t,e&&(e.style.transition="none"),setTimeout(()=>{e&&(e.style.transition="")},20)}}getProgress(){return this.progress}render(){const t=Math.max(0,Math.min(100,Number(this.progress)||0)),e=Number(this.size)||100,i=Number(this.strokeWidth)||15,s=(e-i)/2,r=2*Math.PI*s,a=r-t/100*r,n=Math.max(10,Math.min(24,.16*e));return V`
<div class="progress-wrapper" style="width:${e}px; height:${e}px;">
<svg
class="progress-circle"
height="${e}" width="${e}"
style="overflow:visible;"
>
<circle
class="progress-bg"
cx="${e/2}" cy="${e/2}"
r="${s}"
fill="none"
stroke="#FFFFFF1A"
stroke-width="${i}"
></circle>
<circle
class="progress-bar"
cx="${e/2}" cy="${e/2}"
r="${s}"
fill="none"
stroke="${this.color}"
stroke-width="${i}"
stroke-linecap="round"
style="
stroke-dasharray: ${r};
stroke-dashoffset: ${a};
transition: stroke-dashoffset 0.3s ease;
transform: rotate(-90deg);
transform-origin: ${e/2}px ${e/2}px;
"
></circle>
${this.showProgressText?V`
<text
x="50%" y="50%"
class="progress-text"
dy="2"
style="font-size: ${n}px;"
>
${Math.round(t)}%
</text>
`:V`<!-- showProgressText is false -->`}
</svg>
</div>
`}}t([ht({type:Number})],At.prototype,"progress",void 0),t([ht({type:String})],At.prototype,"color",void 0),t([ht({type:Number})],At.prototype,"size",void 0),t([ht({type:Number})],At.prototype,"strokeWidth",void 0),t([ht({type:Boolean})],At.prototype,"showProgressText",void 0);class Tt extends nt{constructor(){super(...arguments),this.hass=null,this._config={type:"custom:timeflow-card"}}setConfig(t){this._config={...t}}_fireConfigChanged(t){this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:t},bubbles:!0,composed:!0}))}_formChanged(t){var e,i;const s=(null===(e=t.detail)||void 0===e?void 0:e.value)||{},r={...this._config||{},...s,type:(null===(i=this._config)||void 0===i?void 0:i.type)||"custom:timeflow-card"};this._config=r,this._fireConfigChanged(r)}_computeHelper(t){return{creation_date:'Examples: "2024-01-01T00:00:00", "{{ now() }}", "{{ states(\'input_datetime.start\') }}"',target_date:'Examples: "2024-12-31T23:59:59", "{{ states(\'input_datetime.deadline\') }}"',progress_color:'Examples: "#FF0000", "red", "rgb(255,0,0)", "{{ states(\'input_text.color\') }}"',background_color:"Examples: \"#00FF00\", \"blue\", \"rgba(0,255,0,0.5)\", \"{{ 'red' if is_state('switch.alert', 'on') else 'green' }}\"",color:'Examples: "#333333", "white", "rgb(0,0,0)", "{{ states(\'input_text.color\') }}"',text_color:'Examples: "#333333", "white", "rgb(0,0,0)", "{{ states(\'input_text.color\') }}"',title:'Examples: "My Timer", "{{ states(\'sensor.event_name\') }}"',subtitle:'Shows time remaining by default; only change if you want custom text. Examples: "Countdown", "{{ relative_time(states(\'input_datetime.start\')) }}"',expired_text:'Examples: "Time\'s up!", "{{ states(\'input_text.message\') }}"',expired_animation:"A subtle animation when timer expires",width:'Card width in CSS units (e.g., "300px", "100%", "20em")',height:'Card height in CSS units (e.g., "200px", "auto", "15em")',aspect_ratio:'Width to height ratio (e.g., "16:9", "4:3", "1:1")'}[t.name]||""}_computeLabel(t){var e;if(t.label)return t.label;const i=(null!==(e=t.name)&&void 0!==e?e:"").toString();return i?i.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" "):""}render(){const t=this._config||{};return V`
<div style="padding: 8px;">
<ha-form
.hass=${this.hass}
.data=${t}
.schema=${[{name:"title",required:!1,selector:{text:{}}},{name:"subtitle",required:!1,selector:{text:{}}},{name:"expired_text",required:!1,selector:{text:{}}},{name:"creation_date",required:!1,selector:{text:{}}},{name:"target_date",required:!1,selector:{text:{}}},{name:"timer_entity",required:!1,selector:{entity:{domain:"timer"}}},{type:"expandable",title:"Appearance",schema:[{name:"progress_color",required:!1,selector:{text:{}}},{name:"background_color",required:!1,selector:{text:{}}},{name:"text_color",required:!1,selector:{text:{}}},{name:"expired_animation",required:!1,selector:{boolean:{}}}]},{type:"expandable",title:"Layout",schema:[{type:"grid",schema:[{name:"width",required:!1,selector:{text:{}}},{name:"height",required:!1,selector:{text:{}}}]},{name:"aspect_ratio",required:!1,selector:{text:{}}}]},{type:"expandable",title:"Time Units",schema:[{type:"grid",schema:[{name:"show_days",required:!1,selector:{boolean:{}}},{name:"show_hours",required:!1,selector:{boolean:{}}},{name:"show_minutes",required:!1,selector:{boolean:{}}},{name:"show_seconds",required:!1,selector:{boolean:{}}}]}]},{type:"expandable",title:"Progress Circle",schema:[{type:"grid",schema:[{name:"stroke_width",required:!1,selector:{number:{min:1,max:50}}},{name:"icon_size",required:!1,selector:{number:{min:10,max:1e3}}}]},{name:"show_progress_text",required:!1,selector:{boolean:{}}}]}]}
@value-changed=${t=>this._formChanged(t)}
.computeLabel=${this._computeLabel}
.computeHelper=${this._computeHelper}
></ha-form>
</div>
`}}t([ht({type:Object})],Tt.prototype,"hass",void 0),t([dt()],Tt.prototype,"_config",void 0),customElements.get("error-display")||customElements.define("error-display",wt),customElements.get("progress-circle")||customElements.define("progress-circle",At),customElements.get("timeflow-card")||customElements.define("timeflow-card",St),customElements.get("timeflow-card-editor")||customElements.define("timeflow-card-editor",Tt),window.customCards=window.customCards||[],window.customCards=window.customCards||[],window.customCards.push({type:"timeflow-card",name:"TimeFlow Card",description:"A beautiful countdown timer card with progress circle for Home Assistant, using Lit",preview:!0,documentationURL:"https://github.com/Rishi8078/TimeFlow-Card"});export{wt as ErrorDisplay,At as ProgressCircle,St as TimeFlowCard};
//# sourceMappingURL=timeflow-card.js.map