Ryan Malloy 14d16a5a4c
Some checks are pending
Validate / HACS validation (push) Waiting to run
Validate / Hassfest (push) Waiting to run
program editor: real edit-existing seed + EVENT/YEARLY editors
Three pieces close out the editor's main gaps:

F1 — backend includes raw fields in programs/get response:

  _program_to_fields() serialises a Program record into the same
  field dict the editor form consumes. Round-trips through
  programs/write are now lossless (fetch → edit → write produces
  byte-identical wire output if no fields changed). The old TODO
  in _fetchProgramFields was about exactly this — the frontend
  was seeding from sensible defaults rather than real values
  because the wire didn't carry raw fields. Now it does.

  Verified by a new round-trip test: read slot 42, write the same
  fields back, assert the encoded wire bytes are identical.

F2 — EVENT program editor:

  EVENT records pack a 16-bit event_id into (month<<8 | day).
  Editing requires decoding that ID into one of four categories:

    * "button"  — USER_MACRO_BUTTON, low byte = button index
    * "zone"    — ZONE_STATE_CHANGE, packed zone + state-change kind
    * "unit"    — UNIT_STATE_CHANGE, packed unit + on/off
    * "fixed"   — hand-rolled IDs (phone events, AC power) from
                  EVENT_AC_POWER_OFF / EVENT_PHONE_RINGING / etc.

  TS helpers decodeEventId / encodeEventId / packEventIdIntoFields
  mirror the Python helpers in program_engine.py.

  UI: category dropdown switches the sub-fields (button picker,
  zone+state pair, unit+on/off, fixed-event picker). Each change
  re-encodes back to month/day. Existing programs with unrecognised
  IDs fall into a "raw" category that shows the literal hex —
  user can switch category to redefine.

F3 — YEARLY program editor:

  YEARLY records have month + day + hour + minute, no days-bitmask.
  The editor now switches on prog_type to pick the right trigger
  section: month dropdown (named months), day number input,
  hour/minute number inputs.

Editor render path refactored: _renderTriggerSection(draft)
dispatches to _renderTimedTrigger / _renderEventTrigger /
_renderYearlyTrigger by prog_type. _renderActionSection is
shared across all three (command picker + object picker + level%).
Action editing works identically regardless of trigger.

Edit button visibility extended from "TIMED only" to any
program_type in EDITABLE_PROG_TYPES (TIMED / EVENT / YEARLY).
REMARK and clausal chains remain read-only.

Full suite: 648 passed, 1 skipped (up from 647, F1 round-trip test).
Frontend bundle: 56 KB minified (up from 47 KB with EVENT + YEARLY
forms and event-id helpers).
2026-05-16 12:20:21 -06:00

850 lines
54 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// omni_pca side panel — generated by frontend/build.mjs. Edit src/, not this file.
var Ie=Object.defineProperty;var ze=Object.getOwnPropertyDescriptor;var h=(n,t,e,r)=>{for(var i=r>1?void 0:r?ze(t,e):t,s=n.length-1,o;s>=0;s--)(o=n[s])&&(i=(r?o(t,e,i):o(i))||i);return r&&i&&Ie(t,e,i),i};var H=globalThis,j=H.ShadowRoot&&(H.ShadyCSS===void 0||H.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,V=Symbol(),he=new WeakMap,F=class{constructor(t,e,r){if(this._$cssResult$=!0,r!==V)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o,e=this.t;if(j&&t===void 0){let r=e!==void 0&&e.length===1;r&&(t=he.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),r&&he.set(e,t))}return t}toString(){return this.cssText}},ue=n=>new F(typeof n=="string"?n:n+"",void 0,V),G=(n,...t)=>{let e=n.length===1?n[0]:t.reduce((r,i,s)=>r+(o=>{if(o._$cssResult$===!0)return o.cssText;if(typeof o=="number")return o;throw Error("Value passed to 'css' function must be a 'css' function result: "+o+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+n[s+1],n[0]);return new F(e,n,V)},ge=(n,t)=>{if(j)n.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of t){let r=document.createElement("style"),i=H.litNonce;i!==void 0&&r.setAttribute("nonce",i),r.textContent=e.cssText,n.appendChild(r)}},W=j?n=>n:n=>n instanceof CSSStyleSheet?(t=>{let e="";for(let r of t.cssRules)e+=r.cssText;return ue(e)})(n):n;var{is:Ne,defineProperty:Le,getOwnPropertyDescriptor:Oe,getOwnPropertyNames:He,getOwnPropertySymbols:je,getPrototypeOf:Ue}=Object,U=globalThis,fe=U.trustedTypes,Be=fe?fe.emptyScript:"",Ye=U.reactiveElementPolyfillSupport,R=(n,t)=>n,D={toAttribute(n,t){switch(t){case Boolean:n=n?Be:null;break;case Object:case Array:n=n==null?n:JSON.stringify(n)}return n},fromAttribute(n,t){let e=n;switch(t){case Boolean:e=n!==null;break;case Number:e=n===null?null:Number(n);break;case Object:case Array:try{e=JSON.parse(n)}catch{e=null}}return e}},B=(n,t)=>!Ne(n,t),me={attribute:!0,type:String,converter:D,reflect:!1,useDefault:!1,hasChanged:B};Symbol.metadata??=Symbol("metadata"),U.litPropertyMetadata??=new WeakMap;var v=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=me){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){let r=Symbol(),i=this.getPropertyDescriptor(t,r,e);i!==void 0&&Le(this.prototype,t,i)}}static getPropertyDescriptor(t,e,r){let{get:i,set:s}=Oe(this.prototype,t)??{get(){return this[e]},set(o){this[e]=o}};return{get:i,set(o){let c=i?.call(this);s?.call(this,o),this.requestUpdate(t,c,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??me}static _$Ei(){if(this.hasOwnProperty(R("elementProperties")))return;let t=Ue(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(R("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(R("properties"))){let e=this.properties,r=[...He(e),...je(e)];for(let i of r)this.createProperty(i,e[i])}let t=this[Symbol.metadata];if(t!==null){let e=litPropertyMetadata.get(t);if(e!==void 0)for(let[r,i]of e)this.elementProperties.set(r,i)}this._$Eh=new Map;for(let[e,r]of this.elementProperties){let i=this._$Eu(e,r);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){let e=[];if(Array.isArray(t)){let r=new Set(t.flat(1/0).reverse());for(let i of r)e.unshift(W(i))}else t!==void 0&&e.push(W(t));return e}static _$Eu(t,e){let r=e.attribute;return r===!1?void 0:typeof r=="string"?r:typeof t=="string"?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),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){let t=new Map,e=this.constructor.elementProperties;for(let r of e.keys())this.hasOwnProperty(r)&&(t.set(r,this[r]),delete this[r]);t.size>0&&(this._$Ep=t)}createRenderRoot(){let t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return ge(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,r){this._$AK(t,r)}_$ET(t,e){let r=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,r);if(i!==void 0&&r.reflect===!0){let s=(r.converter?.toAttribute!==void 0?r.converter:D).toAttribute(e,r.type);this._$Em=t,s==null?this.removeAttribute(i):this.setAttribute(i,s),this._$Em=null}}_$AK(t,e){let r=this.constructor,i=r._$Eh.get(t);if(i!==void 0&&this._$Em!==i){let s=r.getPropertyOptions(i),o=typeof s.converter=="function"?{fromAttribute:s.converter}:s.converter?.fromAttribute!==void 0?s.converter:D;this._$Em=i;let c=o.fromAttribute(e,s.type);this[i]=c??this._$Ej?.get(i)??c,this._$Em=null}}requestUpdate(t,e,r,i=!1,s){if(t!==void 0){let o=this.constructor;if(i===!1&&(s=this[t]),r??=o.getPropertyOptions(t),!((r.hasChanged??B)(s,e)||r.useDefault&&r.reflect&&s===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,r))))return;this.C(t,e,r)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:r,reflect:i,wrapped:s},o){r&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),s!==!0||o!==void 0)||(this._$AL.has(t)||(this.hasUpdated||r||(e=void 0),this._$AL.set(t,e)),i===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[i,s]of this._$Ep)this[i]=s;this._$Ep=void 0}let r=this.constructor.elementProperties;if(r.size>0)for(let[i,s]of r){let{wrapped:o}=s,c=this[i];o!==!0||this._$AL.has(i)||c===void 0||this.C(i,void 0,s,c)}}let t=!1,e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(r=>r.hostUpdate?.()),this.update(e)):this._$EM()}catch(r){throw t=!1,this._$EM(),r}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(e=>e.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(e=>this._$ET(e,this[e])),this._$EM()}updated(t){}firstUpdated(t){}};v.elementStyles=[],v.shadowRootOptions={mode:"open"},v[R("elementProperties")]=new Map,v[R("finalized")]=new Map,Ye?.({ReactiveElement:v}),(U.reactiveElementVersions??=[]).push("2.1.2");var te=globalThis,_e=n=>n,Y=te.trustedTypes,ve=Y?Y.createPolicy("lit-html",{createHTML:n=>n}):void 0,ke="$lit$",y=`lit$${Math.random().toFixed(9).slice(2)}$`,we="?"+y,qe=`<${we}>`,k=document,P=()=>k.createComment(""),I=n=>n===null||typeof n!="object"&&typeof n!="function",re=Array.isArray,Ve=n=>re(n)||typeof n?.[Symbol.iterator]=="function",Z=`[
\f\r]`,M=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,be=/-->/g,ye=/>/g,x=RegExp(`>|${Z}(?:([^\\s"'>=/]+)(${Z}*=${Z}*(?:[^
\f\r"'\`<>=]|("|')|))|$)`,"g"),$e=/'/g,xe=/"/g,Se=/^(?:script|style|textarea|title)$/i,ie=n=>(t,...e)=>({_$litType$:n,strings:t,values:e}),a=ie(1),ot=ie(2),at=ie(3),w=Symbol.for("lit-noChange"),f=Symbol.for("lit-nothing"),Ee=new WeakMap,E=k.createTreeWalker(k,129);function Ae(n,t){if(!re(n)||!n.hasOwnProperty("raw"))throw Error("invalid template strings array");return ve!==void 0?ve.createHTML(t):t}var Ge=(n,t)=>{let e=n.length-1,r=[],i,s=t===2?"<svg>":t===3?"<math>":"",o=M;for(let c=0;c<e;c++){let l=n[c],g,m,p=-1,_=0;for(;_<l.length&&(o.lastIndex=_,m=o.exec(l),m!==null);)_=o.lastIndex,o===M?m[1]==="!--"?o=be:m[1]!==void 0?o=ye:m[2]!==void 0?(Se.test(m[2])&&(i=RegExp("</"+m[2],"g")),o=x):m[3]!==void 0&&(o=x):o===x?m[0]===">"?(o=i??M,p=-1):m[1]===void 0?p=-2:(p=o.lastIndex-m[2].length,g=m[1],o=m[3]===void 0?x:m[3]==='"'?xe:$e):o===xe||o===$e?o=x:o===be||o===ye?o=M:(o=x,i=void 0);let b=o===x&&n[c+1].startsWith("/>")?" ":"";s+=o===M?l+qe:p>=0?(r.push(g),l.slice(0,p)+ke+l.slice(p)+y+b):l+y+(p===-2?c:b)}return[Ae(n,s+(n[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),r]},z=class n{constructor({strings:t,_$litType$:e},r){let i;this.parts=[];let s=0,o=0,c=t.length-1,l=this.parts,[g,m]=Ge(t,e);if(this.el=n.createElement(g,r),E.currentNode=this.el.content,e===2||e===3){let p=this.el.content.firstChild;p.replaceWith(...p.childNodes)}for(;(i=E.nextNode())!==null&&l.length<c;){if(i.nodeType===1){if(i.hasAttributes())for(let p of i.getAttributeNames())if(p.endsWith(ke)){let _=m[o++],b=i.getAttribute(p).split(y),O=/([.?@])?(.*)/.exec(_);l.push({type:1,index:s,name:O[2],strings:b,ctor:O[1]==="."?J:O[1]==="?"?X:O[1]==="@"?Q:A}),i.removeAttribute(p)}else p.startsWith(y)&&(l.push({type:6,index:s}),i.removeAttribute(p));if(Se.test(i.tagName)){let p=i.textContent.split(y),_=p.length-1;if(_>0){i.textContent=Y?Y.emptyScript:"";for(let b=0;b<_;b++)i.append(p[b],P()),E.nextNode(),l.push({type:2,index:++s});i.append(p[_],P())}}}else if(i.nodeType===8)if(i.data===we)l.push({type:2,index:s});else{let p=-1;for(;(p=i.data.indexOf(y,p+1))!==-1;)l.push({type:7,index:s}),p+=y.length-1}s++}}static createElement(t,e){let r=k.createElement("template");return r.innerHTML=t,r}};function S(n,t,e=n,r){if(t===w)return t;let i=r!==void 0?e._$Co?.[r]:e._$Cl,s=I(t)?void 0:t._$litDirective$;return i?.constructor!==s&&(i?._$AO?.(!1),s===void 0?i=void 0:(i=new s(n),i._$AT(n,e,r)),r!==void 0?(e._$Co??=[])[r]=i:e._$Cl=i),i!==void 0&&(t=S(n,i._$AS(n,t.values),i,r)),t}var K=class{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){let{el:{content:e},parts:r}=this._$AD,i=(t?.creationScope??k).importNode(e,!0);E.currentNode=i;let s=E.nextNode(),o=0,c=0,l=r[0];for(;l!==void 0;){if(o===l.index){let g;l.type===2?g=new N(s,s.nextSibling,this,t):l.type===1?g=new l.ctor(s,l.name,l.strings,this,t):l.type===6&&(g=new ee(s,this,t)),this._$AV.push(g),l=r[++c]}o!==l?.index&&(s=E.nextNode(),o++)}return E.currentNode=k,i}p(t){let e=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(t,r,e),e+=r.strings.length-2):r._$AI(t[e])),e++}},N=class n{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,r,i){this.type=2,this._$AH=f,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode,e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=S(this,t,e),I(t)?t===f||t==null||t===""?(this._$AH!==f&&this._$AR(),this._$AH=f):t!==this._$AH&&t!==w&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):Ve(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!==f&&I(this._$AH)?this._$AA.nextSibling.data=t:this.T(k.createTextNode(t)),this._$AH=t}$(t){let{values:e,_$litType$:r}=t,i=typeof r=="number"?this._$AC(t):(r.el===void 0&&(r.el=z.createElement(Ae(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(e);else{let s=new K(i,this),o=s.u(this.options);s.p(e),this.T(o),this._$AH=s}}_$AC(t){let e=Ee.get(t.strings);return e===void 0&&Ee.set(t.strings,e=new z(t)),e}k(t){re(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,r,i=0;for(let s of t)i===e.length?e.push(r=new n(this.O(P()),this.O(P()),this,this.options)):r=e[i],r._$AI(s),i++;i<e.length&&(this._$AR(r&&r._$AB.nextSibling,i),e.length=i)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){let r=_e(t).nextSibling;_e(t).remove(),t=r}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}},A=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,r,i,s){this.type=1,this._$AH=f,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=s,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=f}_$AI(t,e=this,r,i){let s=this.strings,o=!1;if(s===void 0)t=S(this,t,e,0),o=!I(t)||t!==this._$AH&&t!==w,o&&(this._$AH=t);else{let c=t,l,g;for(t=s[0],l=0;l<s.length-1;l++)g=S(this,c[r+l],e,l),g===w&&(g=this._$AH[l]),o||=!I(g)||g!==this._$AH[l],g===f?t=f:t!==f&&(t+=(g??"")+s[l+1]),this._$AH[l]=g}o&&!i&&this.j(t)}j(t){t===f?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},J=class extends A{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===f?void 0:t}},X=class extends A{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==f)}},Q=class extends A{constructor(t,e,r,i,s){super(t,e,r,i,s),this.type=5}_$AI(t,e=this){if((t=S(this,t,e,0)??f)===w)return;let r=this._$AH,i=t===f&&r!==f||t.capture!==r.capture||t.once!==r.once||t.passive!==r.passive,s=t!==f&&(r===f||i);i&&this.element.removeEventListener(this.name,this,r),s&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},ee=class{constructor(t,e,r){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(t){S(this,t)}};var We=te.litHtmlPolyfillSupport;We?.(z,N),(te.litHtmlVersions??=[]).push("3.3.3");var Te=(n,t,e)=>{let r=e?.renderBefore??t,i=r._$litPart$;if(i===void 0){let s=e?.renderBefore??null;r._$litPart$=i=new N(t.insertBefore(P(),s),s,void 0,e??{})}return i._$AI(n),i};var ne=globalThis,$=class extends v{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=Te(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return w}};$._$litElement$=!0,$.finalized=!0,ne.litElementHydrateSupport?.({LitElement:$});var Ze=ne.litElementPolyfillSupport;Ze?.({LitElement:$});(ne.litElementVersions??=[]).push("4.2.2");var Ce=n=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(n,t)}):customElements.define(n,t)};var Ke={attribute:!0,type:String,converter:D,reflect:!1,hasChanged:B},Je=(n=Ke,t,e)=>{let{kind:r,metadata:i}=e,s=globalThis.litPropertyMetadata.get(i);if(s===void 0&&globalThis.litPropertyMetadata.set(i,s=new Map),r==="setter"&&((n=Object.create(n)).wrapped=!0),s.set(e.name,n),r==="accessor"){let{name:o}=e;return{set(c){let l=t.get.call(this);t.set.call(this,c),this.requestUpdate(o,l,n,!0,c)},init(c){return c!==void 0&&this.C(o,void 0,n,c),c}}}if(r==="setter"){let{name:o}=e;return function(c){let l=this[o];t.call(this,c),this.requestUpdate(o,l,n,!0,c)}}throw Error("Unsupported decorator location: "+r)};function L(n){return(t,e)=>typeof e=="object"?Je(n,t,e):((r,i,s)=>{let o=i.hasOwnProperty(s);return i.constructor.createProperty(s,r),o?Object.getOwnPropertyDescriptor(i,s):void 0})(n,t,e)}function u(n){return L({...n,state:!0,attribute:!1})}function se(n,t){return a`${n.map(e=>Xe(e,t))}`}function Xe(n,t){switch(n.k){case"newline":return a`<br />`;case"indent":return a`<span class="indent">${n.t}</span>`;case"keyword":return a`<span class="keyword">${n.t}</span>`;case"operator":return a`<span class="operator">${n.t}</span>`;case"value":return a`<span class="value">${n.t}</span>`;case"ref":{let e=t&&n.ek&&typeof n.ei=="number"?()=>t(n.ek,n.ei):void 0;return a`<button
type="button"
class="ref ref-${n.ek}"
title=${n.ek??""}
@click=${e}
>
<span class="ref-name">${n.t}</span>
${n.s?a`<span class="ref-state">${n.s}</span>`:""}
</button>`}default:return a`<span>${n.t}</span>`}}var oe=[{value:0,label:"Turn OFF unit",ref_kind:"unit"},{value:1,label:"Turn ON unit",ref_kind:"unit"},{value:2,label:"All OFF",ref_kind:null},{value:3,label:"All ON",ref_kind:null},{value:4,label:"Bypass zone",ref_kind:"zone"},{value:5,label:"Restore zone",ref_kind:"zone"},{value:7,label:"Execute button",ref_kind:"button"},{value:9,label:"Set unit level %",ref_kind:"unit"},{value:48,label:"Disarm area",ref_kind:"area"},{value:49,label:"Arm area Day",ref_kind:"area"},{value:50,label:"Arm area Night",ref_kind:"area"},{value:51,label:"Arm area Away",ref_kind:"area"},{value:52,label:"Arm area Vacation",ref_kind:"area"}];function ae(n){return oe.find(t=>t.value===n)}var Fe=[{bit:2,label:"Mon"},{bit:4,label:"Tue"},{bit:8,label:"Wed"},{bit:16,label:"Thu"},{bit:32,label:"Fri"},{bit:64,label:"Sat"},{bit:128,label:"Sun"}],le=1,ce=2,de=3;var pe=[{id:768,label:"Phone line dead"},{id:769,label:"Phone ringing"},{id:770,label:"Phone off hook"},{id:771,label:"Phone on hook"},{id:772,label:"AC power lost"},{id:773,label:"AC power restored"}];function T(n){if(pe.some(t=>t.id===n))return{category:"fixed",fixedId:n};if(!(n&65280))return{category:"button",button:n&255};if((n&64512)===1024){let t=n&1023;return{category:"zone",zone:Math.floor(t/4)+1,zoneState:t%4}}if((n&64512)===2048){let t=n&1023;return{category:"unit",unit:Math.floor(t/2)+1,unitOn:(t&1)===1}}return{category:"raw",raw:n}}function Re(n){switch(n.category){case"button":return(n.button??1)&255;case"zone":{let t=(n.zone??1)-1,e=(n.zoneState??0)&3;return 1024|t*4+e&1023}case"unit":{let t=(n.unit??1)-1,e=n.unitOn?1:0;return 2048|t*2+e&1023}case"fixed":return n.fixedId??768;case"raw":default:return n.raw??0}}function C(n){return(n.month??0)<<8|(n.day??0)}function De(n,t){return{...n,month:t>>8&255,day:t&255}}var Me=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var Pe=new Set(["TIMED","EVENT","YEARLY"]),Qe=["TIMED","EVENT","YEARLY","WHEN","AT","EVERY","REMARK"],et=5e3,d=class extends ${constructor(){super(...arguments);this.narrow=!1;this._entryId=null;this._rows=[];this._total=0;this._filteredTotal=0;this._loading=!1;this._error=null;this._activeTriggerTypes=new Set;this._referenceFilter=null;this._searchTerm="";this._selectedSlot=null;this._detail=null;this._detailLoading=!1;this._fireFeedback=null;this._writeFeedback=null;this._cloneTargetSlot="";this._showCloneInput=!1;this._confirmingClear=!1;this._editingDraft=null;this._objects=null;this._refreshTimer=null}connectedCallback(){super.connectedCallback(),this._discoverEntry(),this._entryId&&(this._loadList(),this._startRefreshTimer())}disconnectedCallback(){super.disconnectedCallback(),this._stopRefreshTimer()}updated(e){e.has("hass")&&this._entryId===null&&(this._discoverEntry(),this._entryId&&(this._loadList(),this._startRefreshTimer()))}_discoverEntry(){this.hass?.connection&&this._discoverViaList()}async _discoverViaList(){try{let r=(await this.hass.connection.sendMessagePromise({type:"config_entries/get"})).filter(i=>i.domain==="omni_pca");if(r.length===0){this._error="No Omni panel configured. Add one via Settings \u2192 Devices & Services.";return}this._entryId=r[0].entry_id,this._error=null}catch(e){this._error=`Could not discover panels: ${e instanceof Error?e.message:String(e)}`}}async _loadList(){if(this._entryId){this._loading=!0,this._error=null;try{let e={type:"omni_pca/programs/list",entry_id:this._entryId};this._activeTriggerTypes.size>0&&(e.trigger_types=[...this._activeTriggerTypes]),this._referenceFilter&&(e.references_entity=this._referenceFilter),this._searchTerm&&(e.search=this._searchTerm);let r=await this.hass.connection.sendMessagePromise(e);this._rows=r.programs,this._total=r.total,this._filteredTotal=r.filtered_total}catch(e){this._error=e instanceof Error?e.message:String(e)}finally{this._loading=!1}}}async _loadDetail(e){if(this._entryId){this._detailLoading=!0,this._detail=null;try{this._detail=await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/get",entry_id:this._entryId,slot:e})}catch(r){this._error=r instanceof Error?r.message:String(r)}finally{this._detailLoading=!1}}}async _fireProgram(e){if(this._entryId){this._fireFeedback="firing\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/fire",entry_id:this._entryId,slot:e}),this._fireFeedback=`fired slot ${e}`}catch(r){this._fireFeedback=`error: ${r instanceof Error?r.message:r}`}setTimeout(()=>{this._fireFeedback=null},4e3)}}async _clearProgram(e){if(this._entryId){this._writeFeedback="clearing\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/clear",entry_id:this._entryId,slot:e}),this._writeFeedback=`cleared slot ${e}`,this._confirmingClear=!1,this._selectedSlot=null,this._detail=null,await this._loadList()}catch(r){let i=r instanceof Error?r.message:String(r);this._writeFeedback=`error: ${i}`}setTimeout(()=>{this._writeFeedback=null},4e3)}}async _cloneProgram(e){if(!this._entryId)return;let r=this._cloneTargetSlot.trim(),i=parseInt(r,10);if(!Number.isFinite(i)||i<1||i>1500){this._writeFeedback="target slot must be 1..1500",setTimeout(()=>{this._writeFeedback=null},4e3);return}if(i===e){this._writeFeedback="target must differ from source",setTimeout(()=>{this._writeFeedback=null},4e3);return}this._writeFeedback="cloning\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/clone",entry_id:this._entryId,source_slot:e,target_slot:i}),this._writeFeedback=`cloned to slot ${i}`,this._showCloneInput=!1,this._cloneTargetSlot="",this._selectedSlot=i,await this._loadList(),await this._loadDetail(i)}catch(s){let o=s instanceof Error?s.message:String(s);this._writeFeedback=`error: ${o}`}setTimeout(()=>{this._writeFeedback=null},4e3)}_onCloneTargetInput(e){this._cloneTargetSlot=e.target.value}async _ensureObjectsLoaded(){if(!(this._objects!==null||!this._entryId))try{this._objects=await this.hass.connection.sendMessagePromise({type:"omni_pca/objects/list",entry_id:this._entryId})}catch(e){let r=e instanceof Error?e.message:String(e);console.warn("omni_pca: objects/list failed",r)}}async _beginEdit(){if(!this._detail||this._detail.kind!=="compact"||!Pe.has(this._detail.trigger_type)||(await this._ensureObjectsLoaded(),!this._entryId))return;let e=this._detail.fields??this._defaultFieldsForType(this._detail.trigger_type);e!==null&&(this._editingDraft={...e},this._stopRefreshTimer())}_defaultFieldsForType(e){let r=this._objects?.units?.[0]?.index??1;if(e==="TIMED")return{prog_type:le,cmd:1,par:0,pr2:r,hour:6,minute:0,days:62,cond:0,cond2:0,month:0,day:0};if(e==="EVENT"){let i=this._objects?.buttons?.[0]?.index??1;return{prog_type:ce,cmd:1,par:0,pr2:r,month:0,day:i&255,hour:0,minute:0,days:0,cond:0,cond2:0}}return e==="YEARLY"?{prog_type:de,cmd:1,par:0,pr2:r,month:1,day:1,hour:0,minute:0,days:0,cond:0,cond2:0}:null}async _saveDraft(){if(!(!this._editingDraft||!this._detail||!this._entryId)){this._writeFeedback="saving\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/write",entry_id:this._entryId,slot:this._detail.slot,program:this._editingDraft}),this._writeFeedback=`saved slot ${this._detail.slot}`,this._editingDraft=null,this._startRefreshTimer(),await this._loadList(),await this._loadDetail(this._detail.slot)}catch(e){let r=e instanceof Error?e.message:String(e);this._writeFeedback=`error: ${r}`}setTimeout(()=>{this._writeFeedback=null},4e3)}}_cancelEdit(){this._editingDraft=null,this._startRefreshTimer()}_patchDraft(e){this._editingDraft&&(this._editingDraft={...this._editingDraft,...e})}_toggleDayBit(e){if(!this._editingDraft)return;let i=(this._editingDraft.days??0)^e;this._patchDraft({days:i})}_onCommandChange(e){let r=parseInt(e.target.value,10);if(!Number.isFinite(r))return;let i=ae(r),s=this._editingDraft?.pr2??0;if(i?.ref_kind&&this._objects){let o=this._pickBucket(i.ref_kind);o&&o.length>0&&!o.some(c=>c.index===s)&&(s=o[0].index)}else i?.ref_kind||(s=0);this._patchDraft({cmd:r,pr2:s})}_pickBucket(e){if(!this._objects)return null;switch(e){case"zone":return this._objects.zones;case"unit":return this._objects.units;case"area":return this._objects.areas;case"button":return this._objects.buttons;default:return null}}_onObjectChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&this._patchDraft({pr2:r})}_onHourChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&r>=0&&r<=23&&this._patchDraft({hour:r})}_onMinuteChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&r>=0&&r<=59&&this._patchDraft({minute:r})}_onParChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&r>=0&&r<=255&&this._patchDraft({par:r})}_onMonthChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&r>=1&&r<=12&&this._patchDraft({month:r})}_onDayChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&r>=1&&r<=31&&this._patchDraft({day:r})}_patchEvent(e){if(!this._editingDraft)return;let r=Re(e);this._editingDraft=De(this._editingDraft,r)}_onEventCategoryChange(e){let r=e.target.value;if(r==="button"){let i=this._objects?.buttons?.[0]?.index??1;this._patchEvent({category:"button",button:i})}else if(r==="zone"){let i=this._objects?.zones?.[0]?.index??1;this._patchEvent({category:"zone",zone:i,zoneState:1})}else if(r==="unit"){let i=this._objects?.units?.[0]?.index??1;this._patchEvent({category:"unit",unit:i,unitOn:!0})}else r==="fixed"&&this._patchEvent({category:"fixed",fixedId:772})}_onEventButtonChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&this._patchEvent({category:"button",button:r})}_onEventZoneChange(e){if(!this._editingDraft)return;let r=parseInt(e.target.value,10);if(!Number.isFinite(r))return;let i=T(C(this._editingDraft));this._patchEvent({category:"zone",zone:r,zoneState:i.zoneState??1})}_onEventZoneStateChange(e){if(!this._editingDraft)return;let r=parseInt(e.target.value,10);if(!Number.isFinite(r))return;let i=T(C(this._editingDraft));this._patchEvent({category:"zone",zone:i.zone??1,zoneState:r})}_onEventUnitChange(e){if(!this._editingDraft)return;let r=parseInt(e.target.value,10);if(!Number.isFinite(r))return;let i=T(C(this._editingDraft));this._patchEvent({category:"unit",unit:r,unitOn:i.unitOn??!0})}_onEventUnitOnChange(e){if(!this._editingDraft)return;let r=e.target.value==="1",i=T(C(this._editingDraft));this._patchEvent({category:"unit",unit:i.unit??1,unitOn:r})}_onEventFixedChange(e){let r=parseInt(e.target.value,10);Number.isFinite(r)&&this._patchEvent({category:"fixed",fixedId:r})}_startRefreshTimer(){this._refreshTimer===null&&(this._refreshTimer=window.setInterval(()=>{this._loadList(),this._selectedSlot!==null&&this._loadDetail(this._selectedSlot)},et))}_stopRefreshTimer(){this._refreshTimer!==null&&(window.clearInterval(this._refreshTimer),this._refreshTimer=null)}_toggleTriggerFilter(e){let r=new Set(this._activeTriggerTypes);r.has(e)?r.delete(e):r.add(e),this._activeTriggerTypes=r,this._loadList()}_onSearchInput(e){this._searchTerm=e.target.value,this._loadList()}_clearReferenceFilter(){this._referenceFilter=null,this._loadList()}_onRowClick(e){this._selectedSlot=e,this._loadDetail(e)}_onRefClick(e,r){this._referenceFilter=`${e}:${r}`,this._selectedSlot=null,this._detail=null,this._loadList()}_closeDetail(){this._selectedSlot=null,this._detail=null}render(){return a`
<div class="header">
<div class="title">
<ha-icon icon="mdi:script-text-outline"></ha-icon>
<span>Omni Programs</span>
${this._total>0?a`
<span class="count">
${this._filteredTotal===this._total?`${this._total} programs`:`${this._filteredTotal} of ${this._total} shown`}
</span>`:""}
</div>
</div>
${this._error?a`
<div class="error">${this._error}</div>`:""}
${this._renderFilters()}
<div class="body" data-narrow=${this.narrow}>
${this._renderList()}
${this._selectedSlot!==null?this._renderDetail():""}
</div>
`}_renderFilters(){return a`
<div class="filters">
<input
type="search"
class="search"
placeholder="search programs..."
.value=${this._searchTerm}
@input=${this._onSearchInput}
/>
<div class="chips">
${Qe.map(e=>a`
<button
type="button"
class="chip ${this._activeTriggerTypes.has(e)?"active":""}"
@click=${()=>this._toggleTriggerFilter(e)}
>${e}</button>
`)}
</div>
${this._referenceFilter?a`
<div class="ref-filter">
<span>filtering on <strong>${this._referenceFilter}</strong></span>
<button type="button" @click=${this._clearReferenceFilter}>clear</button>
</div>`:""}
</div>
`}_renderList(){return this._loading&&this._rows.length===0?a`<div class="loading">loading…</div>`:this._rows.length===0?a`<div class="empty">No programs match the current filters.</div>`:a`
<div class="list">
${this._rows.map(e=>a`
<div
class="row ${this._selectedSlot===e.slot?"selected":""}"
@click=${()=>this._onRowClick(e.slot)}
>
<div class="row-slot">#${e.slot}</div>
<div class="row-summary">
${se(e.summary,(r,i)=>this._onRefClick(r,i))}
</div>
<div class="row-meta">
<span class="trigger-badge trigger-${e.trigger_type.toLowerCase()}">
${e.trigger_type}
</span>
${e.condition_count>0?a`
<span class="meta-pill">${e.condition_count} cond</span>`:""}
${e.action_count>1?a`
<span class="meta-pill">${e.action_count} actions</span>`:""}
</div>
</div>
`)}
</div>
`}_renderDetail(){if(this._detailLoading)return a`<aside class="detail"><div class="loading">loading…</div></aside>`;if(this._detail===null)return a`<aside class="detail"></aside>`;let e=this._detail;return this._editingDraft!==null?this._renderEditor(e):a`
<aside class="detail">
<header>
<div>
<span class="trigger-badge trigger-${e.trigger_type.toLowerCase()}">
${e.trigger_type}
</span>
<span class="slot">slot #${e.slot}</span>
</div>
<button type="button" class="close" @click=${this._closeDetail}>×</button>
</header>
<pre class="detail-body">${se(e.tokens,(r,i)=>this._onRefClick(r,i))}</pre>
<footer>
<button
type="button"
class="fire"
@click=${()=>this._fireProgram(e.slot)}
>▶ Fire now</button>
${e.kind==="compact"&&Pe.has(e.trigger_type)?a`
<button
type="button"
class="secondary"
@click=${this._beginEdit}
>Edit</button>`:""}
<button
type="button"
class="secondary"
@click=${()=>{this._showCloneInput=!this._showCloneInput,this._confirmingClear=!1}}
>Clone…</button>
<button
type="button"
class="danger"
@click=${()=>{this._confirmingClear=!this._confirmingClear,this._showCloneInput=!1}}
>Clear</button>
${this._fireFeedback?a`
<span class="fire-feedback">${this._fireFeedback}</span>`:""}
${this._writeFeedback?a`
<span class="fire-feedback">${this._writeFeedback}</span>`:""}
</footer>
${this._showCloneInput?a`
<div class="action-row">
<label>Clone slot ${e.slot} → target slot:
<input
type="number"
min="1"
max="1500"
.value=${this._cloneTargetSlot}
@input=${this._onCloneTargetInput}
@keydown=${r=>{r.key==="Enter"&&this._cloneProgram(e.slot)}}
/>
</label>
<button
type="button"
class="primary"
@click=${()=>this._cloneProgram(e.slot)}
>Clone</button>
<button
type="button"
@click=${()=>{this._showCloneInput=!1}}
>Cancel</button>
</div>`:""}
${this._confirmingClear?a`
<div class="action-row danger-row">
<span>
<strong>Clear slot ${e.slot}?</strong>
This deletes the program from the panel.
</span>
<button
type="button"
class="danger"
@click=${()=>this._clearProgram(e.slot)}
>Yes, clear</button>
<button
type="button"
@click=${()=>{this._confirmingClear=!1}}
>Cancel</button>
</div>`:""}
${e.chain_slots&&e.chain_slots.length>1?a`
<div class="chain-info">
spans slots
${e.chain_slots.map((r,i)=>a`
${i>0?"\u2192":""}#${r}`)}
</div>`:""}
</aside>
`}_renderEditor(e){let r=this._editingDraft,i=e.trigger_type;return a`
<aside class="detail editor">
<header>
<div>
<span class="trigger-badge trigger-${i.toLowerCase()}">
EDIT • ${i}
</span>
<span class="slot">slot #${e.slot}</span>
</div>
<button type="button" class="close" @click=${this._cancelEdit}>×</button>
</header>
<div class="editor-body">
${this._renderTriggerSection(r)}
${this._renderActionSection(r)}
${r.cond||r.cond2?a`
<div class="conditions-readonly">
<strong>Inline conditions:</strong>
this program carries up to two inline AND-IF conditions on
the source record. They're preserved on save but editing
condition fields is not yet supported.
</div>`:""}
</div>
<footer>
<button type="button" class="primary" @click=${this._saveDraft}>
Save
</button>
<button type="button" class="secondary" @click=${this._cancelEdit}>
Cancel
</button>
${this._writeFeedback?a`
<span class="fire-feedback">${this._writeFeedback}</span>`:""}
</footer>
</aside>
`}_renderTriggerSection(e){switch(e.prog_type){case le:return this._renderTimedTrigger(e);case ce:return this._renderEventTrigger(e);case de:return this._renderYearlyTrigger(e);default:return a`<div class="conditions-readonly">
Editing program type ${e.prog_type} is not supported.
</div>`}}_renderTimedTrigger(e){return a`
<fieldset>
<legend>Time</legend>
<div class="row">
<label>
Hour
<input
type="number" min="0" max="23"
.value=${String(e.hour??0)}
@input=${this._onHourChange}
/>
</label>
<span class="time-colon">:</span>
<label>
Minute
<input
type="number" min="0" max="59" step="1"
.value=${String(e.minute??0)}
@input=${this._onMinuteChange}
/>
</label>
</div>
</fieldset>
<fieldset>
<legend>Days</legend>
<div class="days-row">
${Fe.map(r=>{let i=((e.days??0)&r.bit)!==0;return a`
<button
type="button"
class="day-toggle ${i?"active":""}"
@click=${()=>this._toggleDayBit(r.bit)}
>${r.label}</button>
`})}
</div>
</fieldset>
`}_renderEventTrigger(e){let r=C(e),i=T(r);return a`
<fieldset>
<legend>Trigger event</legend>
<label class="block">
Category
<select @change=${this._onEventCategoryChange}>
<option value="button"
?selected=${i.category==="button"}>
Button press
</option>
<option value="zone"
?selected=${i.category==="zone"}>
Zone state change
</option>
<option value="unit"
?selected=${i.category==="unit"}>
Unit state change
</option>
<option value="fixed"
?selected=${i.category==="fixed"}>
Fixed event (phone / AC)
</option>
${i.category==="raw"?a`
<option value="raw" selected>
Raw 0x${r.toString(16).padStart(4,"0")}
</option>`:""}
</select>
</label>
${this._renderEventCategoryFields(i)}
</fieldset>
`}_renderEventCategoryFields(e){return e.category==="button"?a`
<label class="block">
Button
<select @change=${this._onEventButtonChange}>
${(this._objects?.buttons??[]).map(r=>a`
<option .value=${String(r.index)}
?selected=${r.index===e.button}>
#${r.index} ${r.name}
</option>
`)}
</select>
</label>`:e.category==="zone"?a`
<label class="block">
Zone
<select @change=${this._onEventZoneChange}>
${(this._objects?.zones??[]).map(r=>a`
<option .value=${String(r.index)}
?selected=${r.index===e.zone}>
#${r.index} ${r.name}
</option>
`)}
</select>
</label>
<label class="block">
Becomes
<select @change=${this._onEventZoneStateChange}>
<option value="0" ?selected=${e.zoneState===0}>secure</option>
<option value="1" ?selected=${e.zoneState===1}>not ready</option>
<option value="2" ?selected=${e.zoneState===2}>trouble</option>
<option value="3" ?selected=${e.zoneState===3}>tamper</option>
</select>
</label>`:e.category==="unit"?a`
<label class="block">
Unit
<select @change=${this._onEventUnitChange}>
${(this._objects?.units??[]).map(r=>a`
<option .value=${String(r.index)}
?selected=${r.index===e.unit}>
#${r.index} ${r.name}
</option>
`)}
</select>
</label>
<label class="block">
Turns
<select @change=${this._onEventUnitOnChange}>
<option value="1" ?selected=${e.unitOn===!0}>ON</option>
<option value="0" ?selected=${e.unitOn===!1}>OFF</option>
</select>
</label>`:e.category==="fixed"?a`
<label class="block">
Event
<select @change=${this._onEventFixedChange}>
${pe.map(r=>a`
<option .value=${String(r.id)}
?selected=${r.id===e.fixedId}>
${r.label}
</option>
`)}
</select>
</label>`:a`
<div class="conditions-readonly">
Unrecognised event ID. Switch category above to redefine.
</div>`}_renderYearlyTrigger(e){return a`
<fieldset>
<legend>Date</legend>
<div class="row">
<label>
Month
<select @change=${this._onMonthChange}>
${Me.map((r,i)=>a`
<option .value=${String(i+1)}
?selected=${(e.month??1)===i+1}>
${r} (${i+1})
</option>
`)}
</select>
</label>
<label>
Day
<input
type="number" min="1" max="31"
.value=${String(e.day??1)}
@input=${this._onDayChange}
/>
</label>
</div>
</fieldset>
<fieldset>
<legend>Time of day</legend>
<div class="row">
<label>
Hour
<input
type="number" min="0" max="23"
.value=${String(e.hour??0)}
@input=${this._onHourChange}
/>
</label>
<span class="time-colon">:</span>
<label>
Minute
<input
type="number" min="0" max="59"
.value=${String(e.minute??0)}
@input=${this._onMinuteChange}
/>
</label>
</div>
</fieldset>
`}_renderActionSection(e){let r=ae(e.cmd??0),i=r?.ref_kind?this._pickBucket(r.ref_kind):null,s=e.cmd===9;return a`
<fieldset>
<legend>Action</legend>
<label class="block">
Command
<select @change=${this._onCommandChange}>
${oe.map(o=>a`
<option .value=${String(o.value)}
?selected=${o.value===e.cmd}>
${o.label}
</option>
`)}
</select>
</label>
${r?.ref_kind?a`
<label class="block">
${r.ref_kind[0].toUpperCase()+r.ref_kind.slice(1)}
<select @change=${this._onObjectChange}>
${(i??[]).map(o=>a`
<option .value=${String(o.index)}
?selected=${o.index===e.pr2}>
#${o.index} ${o.name}
</option>
`)}
</select>
</label>`:""}
${s?a`
<label class="block">
Level (0..100)
<input
type="number" min="0" max="100"
.value=${String(e.par??0)}
@input=${this._onParChange}
/>
</label>`:""}
</fieldset>
`}};d.styles=G`
:host {
display: block;
min-height: 100vh;
background: var(--primary-background-color, #fafafa);
color: var(--primary-text-color, #000);
font-family: var(--paper-font-body1_-_font-family, sans-serif);
}
.header {
display: flex; align-items: center;
padding: 16px 20px;
background: var(--primary-color, #03a9f4);
color: var(--text-primary-color, #fff);
}
.header .title { display: flex; align-items: center; gap: 10px; font-size: 1.2rem; }
.header .count {
margin-left: 12px;
font-size: 0.85rem; opacity: 0.85; font-weight: normal;
}
.error {
margin: 12px 16px;
padding: 10px 14px;
background: var(--error-color, #db4437);
color: white;
border-radius: 4px;
}
.filters {
padding: 12px 16px 8px;
border-bottom: 1px solid var(--divider-color, #ddd);
}
.search {
width: 100%;
padding: 8px 10px;
font-size: 0.95rem;
border: 1px solid var(--divider-color, #ccc);
border-radius: 4px;
background: var(--card-background-color, #fff);
color: inherit;
box-sizing: border-box;
}
.chips {
display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px;
}
.chip {
border: 1px solid var(--divider-color, #ccc);
background: var(--card-background-color, #fff);
color: var(--secondary-text-color, #555);
padding: 4px 10px;
border-radius: 12px;
font-size: 0.78rem;
cursor: pointer;
font-family: inherit;
}
.chip:hover { background: var(--secondary-background-color, #eee); }
.chip.active {
background: var(--primary-color, #03a9f4);
color: var(--text-primary-color, #fff);
border-color: transparent;
}
.ref-filter {
margin-top: 8px;
font-size: 0.85rem;
color: var(--secondary-text-color, #555);
display: flex; align-items: center; gap: 8px;
}
.ref-filter button {
border: 1px solid var(--divider-color, #ccc);
background: transparent; color: inherit;
padding: 2px 8px; border-radius: 8px;
font-size: 0.75rem; cursor: pointer;
}
.body {
display: grid;
grid-template-columns: 1fr;
gap: 0;
}
.body[data-narrow="false"] { grid-template-columns: 1fr 380px; }
.list {
max-height: calc(100vh - 200px);
overflow-y: auto;
}
.row {
display: grid;
grid-template-columns: 60px 1fr auto;
align-items: start;
gap: 12px;
padding: 10px 16px;
border-bottom: 1px solid var(--divider-color, #eee);
cursor: pointer;
}
.row:hover { background: var(--secondary-background-color, #f5f5f5); }
.row.selected { background: var(--state-active-color, #e3f2fd); }
.row-slot {
font-family: var(--code-font-family, monospace);
font-size: 0.78rem;
color: var(--secondary-text-color, #888);
padding-top: 2px;
}
.row-summary {
font-size: 0.92rem;
line-height: 1.45;
}
.row-meta {
display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
}
/* trigger-type badges */
.trigger-badge {
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.5px;
padding: 2px 6px;
border-radius: 3px;
text-transform: uppercase;
}
.trigger-timed { background: #e3f2fd; color: #1565c0; }
.trigger-event { background: #fff3e0; color: #e65100; }
.trigger-yearly { background: #f3e5f5; color: #6a1b9a; }
.trigger-when { background: #e8f5e9; color: #2e7d32; }
.trigger-at { background: #e3f2fd; color: #1565c0; }
.trigger-every { background: #fce4ec; color: #ad1457; }
.trigger-remark { background: #f5f5f5; color: #616161; }
.meta-pill {
font-size: 0.7rem;
color: var(--secondary-text-color, #888);
background: var(--secondary-background-color, #eee);
padding: 1px 6px;
border-radius: 8px;
}
/* token-renderer styles */
.row-summary, .detail-body {
font-family: var(--paper-font-body1_-_font-family, system-ui, sans-serif);
}
.keyword { font-weight: 600; color: var(--primary-color, #1565c0); }
.operator { color: var(--secondary-text-color, #666); font-style: italic; }
.value { font-family: var(--code-font-family, monospace); color: var(--accent-color, #ff6f00); }
.ref {
display: inline-flex; align-items: baseline; gap: 4px;
border: none; background: transparent; padding: 0 2px;
cursor: pointer; font: inherit; color: inherit;
border-bottom: 1px dotted var(--secondary-text-color, #999);
}
.ref:hover { background: var(--secondary-background-color, #eee); }
.ref-name { font-weight: 500; }
.ref-state {
font-size: 0.72rem;
padding: 1px 5px;
border-radius: 3px;
background: var(--secondary-background-color, #eee);
color: var(--secondary-text-color, #666);
vertical-align: 1px;
}
.ref-zone .ref-name { color: var(--info-color, #0288d1); }
.ref-unit .ref-name { color: var(--warning-color, #f57c00); }
.ref-area .ref-name { color: var(--success-color, #388e3c); }
.ref-thermostat .ref-name { color: var(--accent-color, #c2185b); }
.ref-button .ref-name { color: var(--state-light-color, #7e57c2); }
.indent { display: inline-block; width: 1.5em; }
/* detail panel */
.detail {
border-left: 1px solid var(--divider-color, #ddd);
padding: 16px;
max-height: calc(100vh - 200px);
overflow-y: auto;
box-sizing: border-box;
}
.body[data-narrow="true"] .detail {
border-left: none;
border-top: 1px solid var(--divider-color, #ddd);
}
.detail header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 12px;
}
.detail header .slot {
margin-left: 8px;
font-family: var(--code-font-family, monospace);
font-size: 0.85rem;
color: var(--secondary-text-color, #888);
}
.detail .close {
background: transparent; border: none;
font-size: 1.4rem; cursor: pointer;
color: var(--secondary-text-color, #888);
}
.detail-body {
font-size: 0.95rem;
line-height: 1.6;
white-space: pre-wrap;
word-wrap: break-word;
background: var(--card-background-color, #fff);
padding: 12px;
border-radius: 4px;
border: 1px solid var(--divider-color, #eee);
margin: 0;
}
.detail footer {
display: flex; align-items: center; gap: 12px; margin-top: 14px;
}
.fire, .primary, .secondary, .danger {
border: none;
padding: 8px 16px;
font-size: 0.92rem;
border-radius: 4px;
cursor: pointer;
font-family: inherit;
}
.fire, .primary {
background: var(--primary-color, #03a9f4);
color: var(--text-primary-color, #fff);
}
.secondary {
background: var(--secondary-background-color, #eee);
color: var(--primary-text-color, #000);
}
.danger {
background: transparent;
color: var(--error-color, #db4437);
border: 1px solid var(--error-color, #db4437);
}
.fire:hover, .primary:hover, .secondary:hover, .danger:hover {
filter: brightness(0.9);
}
.action-row {
display: flex;
align-items: center;
gap: 8px;
margin-top: 12px;
padding: 10px;
background: var(--secondary-background-color, #f5f5f5);
border-radius: 4px;
font-size: 0.88rem;
}
.action-row.danger-row {
background: var(--error-color, #db4437);
color: white;
}
.action-row input[type="number"] {
width: 70px;
padding: 4px 6px;
font-size: 0.9rem;
border: 1px solid var(--divider-color, #ccc);
border-radius: 3px;
margin-left: 6px;
}
.action-row button {
padding: 4px 12px;
font-size: 0.85rem;
}
.fire-feedback {
font-size: 0.85rem; color: var(--secondary-text-color, #666);
}
.chain-info {
margin-top: 12px;
font-size: 0.8rem;
color: var(--secondary-text-color, #888);
}
.loading, .empty {
padding: 40px 20px;
text-align: center;
color: var(--secondary-text-color, #888);
}
/* editor */
.editor-body { display: flex; flex-direction: column; gap: 12px; }
.editor fieldset {
border: 1px solid var(--divider-color, #ddd);
border-radius: 4px;
padding: 10px 12px;
margin: 0;
}
.editor legend {
padding: 0 6px;
font-size: 0.78rem;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--secondary-text-color, #777);
}
.editor .row {
display: flex; align-items: center; gap: 8px;
}
.editor label.block {
display: flex; flex-direction: column;
gap: 4px;
font-size: 0.85rem;
color: var(--secondary-text-color, #555);
margin-bottom: 8px;
}
.editor label.block:last-child { margin-bottom: 0; }
.editor input[type="number"], .editor select {
padding: 6px 8px;
font-size: 0.95rem;
border: 1px solid var(--divider-color, #ccc);
border-radius: 3px;
background: var(--card-background-color, #fff);
color: inherit;
}
.editor .time-colon {
font-weight: 600; font-size: 1.4rem;
margin: 0 2px;
}
.days-row { display: flex; flex-wrap: wrap; gap: 4px; }
.day-toggle {
padding: 6px 10px;
border: 1px solid var(--divider-color, #ccc);
background: var(--card-background-color, #fff);
color: var(--secondary-text-color, #555);
border-radius: 3px;
cursor: pointer;
font-family: inherit;
font-size: 0.82rem;
}
.day-toggle.active {
background: var(--primary-color, #03a9f4);
color: var(--text-primary-color, #fff);
border-color: transparent;
}
.conditions-readonly {
padding: 10px 12px;
background: var(--secondary-background-color, #f5f5f5);
border-radius: 4px;
font-size: 0.82rem;
color: var(--secondary-text-color, #666);
}
`,h([L({attribute:!1})],d.prototype,"hass",2),h([L({attribute:!1})],d.prototype,"narrow",2),h([u()],d.prototype,"_entryId",2),h([u()],d.prototype,"_rows",2),h([u()],d.prototype,"_total",2),h([u()],d.prototype,"_filteredTotal",2),h([u()],d.prototype,"_loading",2),h([u()],d.prototype,"_error",2),h([u()],d.prototype,"_activeTriggerTypes",2),h([u()],d.prototype,"_referenceFilter",2),h([u()],d.prototype,"_searchTerm",2),h([u()],d.prototype,"_selectedSlot",2),h([u()],d.prototype,"_detail",2),h([u()],d.prototype,"_detailLoading",2),h([u()],d.prototype,"_fireFeedback",2),h([u()],d.prototype,"_writeFeedback",2),h([u()],d.prototype,"_cloneTargetSlot",2),h([u()],d.prototype,"_showCloneInput",2),h([u()],d.prototype,"_confirmingClear",2),h([u()],d.prototype,"_editingDraft",2),h([u()],d.prototype,"_objects",2),d=h([Ce("omni-panel-programs")],d);export{d as OmniPanelPrograms};
/*! Bundled license information:
@lit/reactive-element/css-tag.js:
(**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/reactive-element.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-html/lit-html.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-element/lit-element.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
lit-html/is-server.js:
(**
* @license
* Copyright 2022 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/custom-element.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/property.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/state.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/event-options.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/base.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/query.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/query-all.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/query-async.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/query-assigned-elements.js:
(**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
@lit/reactive-element/decorators/query-assigned-nodes.js:
(**
* @license
* Copyright 2017 Google LLC
* SPDX-License-Identifier: BSD-3-Clause
*)
*/