Ryan Malloy e6308c5624
Some checks are pending
Validate / HACS validation (push) Waiting to run
Validate / Hassfest (push) Waiting to run
program editor — Cut 2: TIMED program edit UI
Three new pieces compose into an inline edit mode for the side panel:

E1 — omni_pca/programs/write websocket command:
  Accepts a Program dict (mirrors the dataclass field by field) plus
  a slot. Validates with a voluptuous schema (range checks on each
  byte field, prog_type 0..10), constructs the typed Program, calls
  client.download_program over the wire. Updates coordinator.data
  .programs on success so the next list call reflects the edit
  before the next poll catches up. Returns {slot, written: true} on
  success; structured errors on validation / not_supported / write_failed.

E2 — omni_pca/objects/list:
  Returns sorted {index, name} entries for zones / units / areas /
  thermostats / buttons sourced from the coordinator's discovered
  topology. Frontend caches the response client-side; the topology
  doesn't change unless the user reloads the integration.

E3 — Frontend TIMED editor:
  Detail panel grows an "Edit" button for TIMED+compact programs
  (other types stay read-only with no button). Click reveals an
  inline form with:
    * Time row — hour / minute number inputs
    * Days row — 7 toggle buttons (Mon..Sun) matching the bitmask
    * Action row — Command dropdown (friendly verbs from the
      COMMAND_OPTIONS table), object picker that auto-filters to
      the right kind for the selected command (zone / unit / area /
      button / none), and a Level % input for UNIT_LEVEL specifically
    * Read-only inline-conditions notice for programs that carry
      cond / cond2 (editing condition fields is a future cut)
  Save sends the draft via programs/write; Cancel discards.
  The poll timer pauses while editing so the form values don't
  flicker mid-edit.

Scope honesty: this pass edits TIMED programs only. Other types
(EVENT / YEARLY / WHEN / AT / EVERY / REMARK) remain read-only
with Fire / Clone / Clear available. Inline AND-IF condition editing
is deferred — the conditions render as a banner. Creating new programs
uses Clone (already shipped) → edit the clone.

The _fetchProgramFields function currently seeds from defaults (6:00
weekdays, UNIT_ON to first unit) rather than pulling raw fields from
the panel because the get-detail websocket response carries rendered
tokens but not raw bytes. That's a TODO marked inline; for the
clone-then-edit workflow the defaults are fine, but editing existing
programs in place will need a tiny backend addition.

4 new HA-integration tests covering write happy path, overwrite,
invalid payload validation, and objects/list returns named buckets.

Full suite: 647 passed, 1 skipped (up from 643, 4 new tests).
Frontend bundle: 47 KB minified (up from 38 KB with editor + form code).
2026-05-16 01:33:55 -06:00

708 lines
47 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 Ee=Object.defineProperty;var Se=Object.getOwnPropertyDescriptor;var h=(s,e,t,r)=>{for(var i=r>1?void 0:r?Se(e,t):e,o=s.length-1,n;o>=0;o--)(n=s[o])&&(i=(r?n(e,t,i):n(i))||i);return r&&i&&Ee(e,t,i),i};var O=globalThis,z=O.ShadowRoot&&(O.ShadyCSS===void 0||O.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,B=Symbol(),ne=new WeakMap,T=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==B)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(z&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=ne.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&ne.set(t,e))}return e}toString(){return this.cssText}},ae=s=>new T(typeof s=="string"?s:s+"",void 0,B),V=(s,...e)=>{let t=s.length===1?s[0]:e.reduce((r,i,o)=>r+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+s[o+1],s[0]);return new T(t,s,B)},le=(s,e)=>{if(z)s.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(let t of e){let r=document.createElement("style"),i=O.litNonce;i!==void 0&&r.setAttribute("nonce",i),r.textContent=t.cssText,s.appendChild(r)}},Y=z?s=>s:s=>s instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return ae(t)})(s):s;var{is:Te,defineProperty:Ce,getOwnPropertyDescriptor:Re,getOwnPropertyNames:Pe,getOwnPropertySymbols:Me,getPrototypeOf:De}=Object,j=globalThis,ce=j.trustedTypes,Ie=ce?ce.emptyScript:"",Fe=j.reactiveElementPolyfillSupport,C=(s,e)=>s,R={toAttribute(s,e){switch(e){case Boolean:s=s?Ie:null;break;case Object:case Array:s=s==null?s:JSON.stringify(s)}return s},fromAttribute(s,e){let t=s;switch(e){case Boolean:t=s!==null;break;case Number:t=s===null?null:Number(s);break;case Object:case Array:try{t=JSON.parse(s)}catch{t=null}}return t}},H=(s,e)=>!Te(s,e),de={attribute:!0,type:String,converter:R,reflect:!1,useDefault:!1,hasChanged:H};Symbol.metadata??=Symbol("metadata"),j.litPropertyMetadata??=new WeakMap;var b=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??=[]).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=de){if(t.state&&(t.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(e)&&((t=Object.create(t)).wrapped=!0),this.elementProperties.set(e,t),!t.noAccessor){let r=Symbol(),i=this.getPropertyDescriptor(e,r,t);i!==void 0&&Ce(this.prototype,e,i)}}static getPropertyDescriptor(e,t,r){let{get:i,set:o}=Re(this.prototype,e)??{get(){return this[t]},set(n){this[t]=n}};return{get:i,set(n){let a=i?.call(this);o?.call(this,n),this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??de}static _$Ei(){if(this.hasOwnProperty(C("elementProperties")))return;let e=De(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(C("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(C("properties"))){let t=this.properties,r=[...Pe(t),...Me(t)];for(let i of r)this.createProperty(i,t[i])}let e=this[Symbol.metadata];if(e!==null){let t=litPropertyMetadata.get(e);if(t!==void 0)for(let[r,i]of t)this.elementProperties.set(r,i)}this._$Eh=new Map;for(let[t,r]of this.elementProperties){let i=this._$Eu(t,r);i!==void 0&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let i of r)t.unshift(Y(i))}else e!==void 0&&t.push(Y(e));return t}static _$Eu(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.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(e=>this.enableUpdating=e),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(e=>e(this))}addController(e){(this._$EO??=new Set).add(e),this.renderRoot!==void 0&&this.isConnected&&e.hostConnected?.()}removeController(e){this._$EO?.delete(e)}_$E_(){let e=new Map,t=this.constructor.elementProperties;for(let r of t.keys())this.hasOwnProperty(r)&&(e.set(r,this[r]),delete this[r]);e.size>0&&(this._$Ep=e)}createRenderRoot(){let e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return le(e,this.constructor.elementStyles),e}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(e=>e.hostConnected?.())}enableUpdating(e){}disconnectedCallback(){this._$EO?.forEach(e=>e.hostDisconnected?.())}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$ET(e,t){let r=this.constructor.elementProperties.get(e),i=this.constructor._$Eu(e,r);if(i!==void 0&&r.reflect===!0){let o=(r.converter?.toAttribute!==void 0?r.converter:R).toAttribute(t,r.type);this._$Em=e,o==null?this.removeAttribute(i):this.setAttribute(i,o),this._$Em=null}}_$AK(e,t){let r=this.constructor,i=r._$Eh.get(e);if(i!==void 0&&this._$Em!==i){let o=r.getPropertyOptions(i),n=typeof o.converter=="function"?{fromAttribute:o.converter}:o.converter?.fromAttribute!==void 0?o.converter:R;this._$Em=i;let a=n.fromAttribute(t,o.type);this[i]=a??this._$Ej?.get(i)??a,this._$Em=null}}requestUpdate(e,t,r,i=!1,o){if(e!==void 0){let n=this.constructor;if(i===!1&&(o=this[e]),r??=n.getPropertyOptions(e),!((r.hasChanged??H)(o,t)||r.useDefault&&r.reflect&&o===this._$Ej?.get(e)&&!this.hasAttribute(n._$Eu(e,r))))return;this.C(e,t,r)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(e,t,{useDefault:r,reflect:i,wrapped:o},n){r&&!(this._$Ej??=new Map).has(e)&&(this._$Ej.set(e,n??t??this[e]),o!==!0||n!==void 0)||(this._$AL.has(e)||(this.hasUpdated||r||(t=void 0),this._$AL.set(e,t)),i===!0&&this._$Em!==e&&(this._$Eq??=new Set).add(e))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[i,o]of this._$Ep)this[i]=o;this._$Ep=void 0}let r=this.constructor.elementProperties;if(r.size>0)for(let[i,o]of r){let{wrapped:n}=o,a=this[i];n!==!0||this._$AL.has(i)||a===void 0||this.C(i,void 0,o,a)}}let e=!1,t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),this._$EO?.forEach(r=>r.hostUpdate?.()),this.update(t)):this._$EM()}catch(r){throw e=!1,this._$EM(),r}e&&this._$AE(t)}willUpdate(e){}_$AE(e){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(e){}firstUpdated(e){}};b.elementStyles=[],b.shadowRootOptions={mode:"open"},b[C("elementProperties")]=new Map,b[C("finalized")]=new Map,Fe?.({ReactiveElement:b}),(j.reactiveElementVersions??=[]).push("2.1.2");var X=globalThis,pe=s=>s,U=X.trustedTypes,he=U?U.createPolicy("lit-html",{createHTML:s=>s}):void 0,be="$lit$",y=`lit$${Math.random().toFixed(9).slice(2)}$`,ve="?"+y,Ne=`<${ve}>`,w=document,M=()=>w.createComment(""),D=s=>s===null||typeof s!="object"&&typeof s!="function",ee=Array.isArray,Le=s=>ee(s)||typeof s?.[Symbol.iterator]=="function",W=`[
\f\r]`,P=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,ue=/-->/g,fe=/>/g,x=RegExp(`>|${W}(?:([^\\s"'>=/]+)(${W}*=${W}*(?:[^
\f\r"'\`<>=]|("|')|))|$)`,"g"),me=/'/g,ge=/"/g,ye=/^(?:script|style|textarea|title)$/i,te=s=>(e,...t)=>({_$litType$:s,strings:e,values:t}),l=te(1),Ze=te(2),Qe=te(3),A=Symbol.for("lit-noChange"),m=Symbol.for("lit-nothing"),_e=new WeakMap,k=w.createTreeWalker(w,129);function $e(s,e){if(!ee(s)||!s.hasOwnProperty("raw"))throw Error("invalid template strings array");return he!==void 0?he.createHTML(e):e}var Oe=(s,e)=>{let t=s.length-1,r=[],i,o=e===2?"<svg>":e===3?"<math>":"",n=P;for(let a=0;a<t;a++){let c=s[a],f,g,p=-1,_=0;for(;_<c.length&&(n.lastIndex=_,g=n.exec(c),g!==null);)_=n.lastIndex,n===P?g[1]==="!--"?n=ue:g[1]!==void 0?n=fe:g[2]!==void 0?(ye.test(g[2])&&(i=RegExp("</"+g[2],"g")),n=x):g[3]!==void 0&&(n=x):n===x?g[0]===">"?(n=i??P,p=-1):g[1]===void 0?p=-2:(p=n.lastIndex-g[2].length,f=g[1],n=g[3]===void 0?x:g[3]==='"'?ge:me):n===ge||n===me?n=x:n===ue||n===fe?n=P:(n=x,i=void 0);let v=n===x&&s[a+1].startsWith("/>")?" ":"";o+=n===P?c+Ne:p>=0?(r.push(f),c.slice(0,p)+be+c.slice(p)+y+v):c+y+(p===-2?a:v)}return[$e(s,o+(s[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),r]},I=class s{constructor({strings:e,_$litType$:t},r){let i;this.parts=[];let o=0,n=0,a=e.length-1,c=this.parts,[f,g]=Oe(e,t);if(this.el=s.createElement(f,r),k.currentNode=this.el.content,t===2||t===3){let p=this.el.content.firstChild;p.replaceWith(...p.childNodes)}for(;(i=k.nextNode())!==null&&c.length<a;){if(i.nodeType===1){if(i.hasAttributes())for(let p of i.getAttributeNames())if(p.endsWith(be)){let _=g[n++],v=i.getAttribute(p).split(y),L=/([.?@])?(.*)/.exec(_);c.push({type:1,index:o,name:L[2],strings:v,ctor:L[1]==="."?K:L[1]==="?"?J:L[1]==="@"?Z:S}),i.removeAttribute(p)}else p.startsWith(y)&&(c.push({type:6,index:o}),i.removeAttribute(p));if(ye.test(i.tagName)){let p=i.textContent.split(y),_=p.length-1;if(_>0){i.textContent=U?U.emptyScript:"";for(let v=0;v<_;v++)i.append(p[v],M()),k.nextNode(),c.push({type:2,index:++o});i.append(p[_],M())}}}else if(i.nodeType===8)if(i.data===ve)c.push({type:2,index:o});else{let p=-1;for(;(p=i.data.indexOf(y,p+1))!==-1;)c.push({type:7,index:o}),p+=y.length-1}o++}}static createElement(e,t){let r=w.createElement("template");return r.innerHTML=e,r}};function E(s,e,t=s,r){if(e===A)return e;let i=r!==void 0?t._$Co?.[r]:t._$Cl,o=D(e)?void 0:e._$litDirective$;return i?.constructor!==o&&(i?._$AO?.(!1),o===void 0?i=void 0:(i=new o(s),i._$AT(s,t,r)),r!==void 0?(t._$Co??=[])[r]=i:t._$Cl=i),i!==void 0&&(e=E(s,i._$AS(s,e.values),i,r)),e}var G=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:r}=this._$AD,i=(e?.creationScope??w).importNode(t,!0);k.currentNode=i;let o=k.nextNode(),n=0,a=0,c=r[0];for(;c!==void 0;){if(n===c.index){let f;c.type===2?f=new F(o,o.nextSibling,this,e):c.type===1?f=new c.ctor(o,c.name,c.strings,this,e):c.type===6&&(f=new Q(o,this,e)),this._$AV.push(f),c=r[++a]}n!==c?.index&&(o=k.nextNode(),n++)}return k.currentNode=w,i}p(e){let t=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(e,r,t),t+=r.strings.length-2):r._$AI(e[t])),t++}},F=class s{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,r,i){this.type=2,this._$AH=m,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=E(this,e,t),D(e)?e===m||e==null||e===""?(this._$AH!==m&&this._$AR(),this._$AH=m):e!==this._$AH&&e!==A&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):Le(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==m&&D(this._$AH)?this._$AA.nextSibling.data=e:this.T(w.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:r}=e,i=typeof r=="number"?this._$AC(e):(r.el===void 0&&(r.el=I.createElement($e(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(t);else{let o=new G(i,this),n=o.u(this.options);o.p(t),this.T(n),this._$AH=o}}_$AC(e){let t=_e.get(e.strings);return t===void 0&&_e.set(e.strings,t=new I(e)),t}k(e){ee(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,r,i=0;for(let o of e)i===t.length?t.push(r=new s(this.O(M()),this.O(M()),this,this.options)):r=t[i],r._$AI(o),i++;i<t.length&&(this._$AR(r&&r._$AB.nextSibling,i),t.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let r=pe(e).nextSibling;pe(e).remove(),e=r}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},S=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,r,i,o){this.type=1,this._$AH=m,this._$AN=void 0,this.element=e,this.name=t,this._$AM=i,this.options=o,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=m}_$AI(e,t=this,r,i){let o=this.strings,n=!1;if(o===void 0)e=E(this,e,t,0),n=!D(e)||e!==this._$AH&&e!==A,n&&(this._$AH=e);else{let a=e,c,f;for(e=o[0],c=0;c<o.length-1;c++)f=E(this,a[r+c],t,c),f===A&&(f=this._$AH[c]),n||=!D(f)||f!==this._$AH[c],f===m?e=m:e!==m&&(e+=(f??"")+o[c+1]),this._$AH[c]=f}n&&!i&&this.j(e)}j(e){e===m?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"")}},K=class extends S{constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===m?void 0:e}},J=class extends S{constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==m)}},Z=class extends S{constructor(e,t,r,i,o){super(e,t,r,i,o),this.type=5}_$AI(e,t=this){if((e=E(this,e,t,0)??m)===A)return;let r=this._$AH,i=e===m&&r!==m||e.capture!==r.capture||e.once!==r.once||e.passive!==r.passive,o=e!==m&&(r===m||i);i&&this.element.removeEventListener(this.name,this,r),o&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},Q=class{constructor(e,t,r){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(e){E(this,e)}};var ze=X.litHtmlPolyfillSupport;ze?.(I,F),(X.litHtmlVersions??=[]).push("3.3.3");var xe=(s,e,t)=>{let r=t?.renderBefore??e,i=r._$litPart$;if(i===void 0){let o=t?.renderBefore??null;r._$litPart$=i=new F(e.insertBefore(M(),o),o,void 0,t??{})}return i._$AI(s),i};var re=globalThis,$=class extends b{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let e=super.createRenderRoot();return this.renderOptions.renderBefore??=e.firstChild,e}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=xe(t,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return A}};$._$litElement$=!0,$.finalized=!0,re.litElementHydrateSupport?.({LitElement:$});var je=re.litElementPolyfillSupport;je?.({LitElement:$});(re.litElementVersions??=[]).push("4.2.2");var ke=s=>(e,t)=>{t!==void 0?t.addInitializer(()=>{customElements.define(s,e)}):customElements.define(s,e)};var He={attribute:!0,type:String,converter:R,reflect:!1,hasChanged:H},Ue=(s=He,e,t)=>{let{kind:r,metadata:i}=t,o=globalThis.litPropertyMetadata.get(i);if(o===void 0&&globalThis.litPropertyMetadata.set(i,o=new Map),r==="setter"&&((s=Object.create(s)).wrapped=!0),o.set(t.name,s),r==="accessor"){let{name:n}=t;return{set(a){let c=e.get.call(this);e.set.call(this,a),this.requestUpdate(n,c,s,!0,a)},init(a){return a!==void 0&&this.C(n,void 0,s,a),a}}}if(r==="setter"){let{name:n}=t;return function(a){let c=this[n];e.call(this,a),this.requestUpdate(n,c,s,!0,a)}}throw Error("Unsupported decorator location: "+r)};function N(s){return(e,t)=>typeof t=="object"?Ue(s,e,t):((r,i,o)=>{let n=i.hasOwnProperty(o);return i.constructor.createProperty(o,r),n?Object.getOwnPropertyDescriptor(i,o):void 0})(s,e,t)}function u(s){return N({...s,state:!0,attribute:!1})}function ie(s,e){return l`${s.map(t=>qe(t,e))}`}function qe(s,e){switch(s.k){case"newline":return l`<br />`;case"indent":return l`<span class="indent">${s.t}</span>`;case"keyword":return l`<span class="keyword">${s.t}</span>`;case"operator":return l`<span class="operator">${s.t}</span>`;case"value":return l`<span class="value">${s.t}</span>`;case"ref":{let t=e&&s.ek&&typeof s.ei=="number"?()=>e(s.ek,s.ei):void 0;return l`<button
type="button"
class="ref ref-${s.ek}"
title=${s.ek??""}
@click=${t}
>
<span class="ref-name">${s.t}</span>
${s.s?l`<span class="ref-state">${s.s}</span>`:""}
</button>`}default:return l`<span>${s.t}</span>`}}var se=[{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 oe(s){return se.find(e=>e.value===s)}var we=[{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"}],Ae=1;var Be=["TIMED","EVENT","YEARLY","WHEN","AT","EVERY","REMARK"],Ve=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(t){t.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(t){this._error=`Could not discover panels: ${t instanceof Error?t.message:String(t)}`}}async _loadList(){if(this._entryId){this._loading=!0,this._error=null;try{let t={type:"omni_pca/programs/list",entry_id:this._entryId};this._activeTriggerTypes.size>0&&(t.trigger_types=[...this._activeTriggerTypes]),this._referenceFilter&&(t.references_entity=this._referenceFilter),this._searchTerm&&(t.search=this._searchTerm);let r=await this.hass.connection.sendMessagePromise(t);this._rows=r.programs,this._total=r.total,this._filteredTotal=r.filtered_total}catch(t){this._error=t instanceof Error?t.message:String(t)}finally{this._loading=!1}}}async _loadDetail(t){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:t})}catch(r){this._error=r instanceof Error?r.message:String(r)}finally{this._detailLoading=!1}}}async _fireProgram(t){if(this._entryId){this._fireFeedback="firing\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/fire",entry_id:this._entryId,slot:t}),this._fireFeedback=`fired slot ${t}`}catch(r){this._fireFeedback=`error: ${r instanceof Error?r.message:r}`}setTimeout(()=>{this._fireFeedback=null},4e3)}}async _clearProgram(t){if(this._entryId){this._writeFeedback="clearing\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/clear",entry_id:this._entryId,slot:t}),this._writeFeedback=`cleared slot ${t}`,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(t){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===t){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:t,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(o){let n=o instanceof Error?o.message:String(o);this._writeFeedback=`error: ${n}`}setTimeout(()=>{this._writeFeedback=null},4e3)}_onCloneTargetInput(t){this._cloneTargetSlot=t.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(t){let r=t instanceof Error?t.message:String(t);console.warn("omni_pca: objects/list failed",r)}}async _beginEdit(){if(!this._detail||this._detail.kind!=="compact"||this._detail.trigger_type!=="TIMED"||(await this._ensureObjectsLoaded(),!this._entryId))return;let t=await this._fetchProgramFields(this._entryId,this._detail.slot);t!==null&&(this._editingDraft=t,this._stopRefreshTimer())}async _fetchProgramFields(t,r){let i=this._objects?.units?.[0]?.index??1;return{prog_type:Ae,cmd:1,par:0,pr2:i,hour:6,minute:0,days:62,cond:0,cond2:0,month:0,day:0}}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(t){let r=t instanceof Error?t.message:String(t);this._writeFeedback=`error: ${r}`}setTimeout(()=>{this._writeFeedback=null},4e3)}}_cancelEdit(){this._editingDraft=null,this._startRefreshTimer()}_patchDraft(t){this._editingDraft&&(this._editingDraft={...this._editingDraft,...t})}_toggleDayBit(t){if(!this._editingDraft)return;let i=(this._editingDraft.days??0)^t;this._patchDraft({days:i})}_onCommandChange(t){let r=parseInt(t.target.value,10);if(!Number.isFinite(r))return;let i=oe(r),o=this._editingDraft?.pr2??0;if(i?.ref_kind&&this._objects){let n=this._pickBucket(i.ref_kind);n&&n.length>0&&!n.some(a=>a.index===o)&&(o=n[0].index)}else i?.ref_kind||(o=0);this._patchDraft({cmd:r,pr2:o})}_pickBucket(t){if(!this._objects)return null;switch(t){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(t){let r=parseInt(t.target.value,10);Number.isFinite(r)&&this._patchDraft({pr2:r})}_onHourChange(t){let r=parseInt(t.target.value,10);Number.isFinite(r)&&r>=0&&r<=23&&this._patchDraft({hour:r})}_onMinuteChange(t){let r=parseInt(t.target.value,10);Number.isFinite(r)&&r>=0&&r<=59&&this._patchDraft({minute:r})}_onParChange(t){let r=parseInt(t.target.value,10);Number.isFinite(r)&&r>=0&&r<=255&&this._patchDraft({par:r})}_startRefreshTimer(){this._refreshTimer===null&&(this._refreshTimer=window.setInterval(()=>{this._loadList(),this._selectedSlot!==null&&this._loadDetail(this._selectedSlot)},Ve))}_stopRefreshTimer(){this._refreshTimer!==null&&(window.clearInterval(this._refreshTimer),this._refreshTimer=null)}_toggleTriggerFilter(t){let r=new Set(this._activeTriggerTypes);r.has(t)?r.delete(t):r.add(t),this._activeTriggerTypes=r,this._loadList()}_onSearchInput(t){this._searchTerm=t.target.value,this._loadList()}_clearReferenceFilter(){this._referenceFilter=null,this._loadList()}_onRowClick(t){this._selectedSlot=t,this._loadDetail(t)}_onRefClick(t,r){this._referenceFilter=`${t}:${r}`,this._selectedSlot=null,this._detail=null,this._loadList()}_closeDetail(){this._selectedSlot=null,this._detail=null}render(){return l`
<div class="header">
<div class="title">
<ha-icon icon="mdi:script-text-outline"></ha-icon>
<span>Omni Programs</span>
${this._total>0?l`
<span class="count">
${this._filteredTotal===this._total?`${this._total} programs`:`${this._filteredTotal} of ${this._total} shown`}
</span>`:""}
</div>
</div>
${this._error?l`
<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 l`
<div class="filters">
<input
type="search"
class="search"
placeholder="search programs..."
.value=${this._searchTerm}
@input=${this._onSearchInput}
/>
<div class="chips">
${Be.map(t=>l`
<button
type="button"
class="chip ${this._activeTriggerTypes.has(t)?"active":""}"
@click=${()=>this._toggleTriggerFilter(t)}
>${t}</button>
`)}
</div>
${this._referenceFilter?l`
<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?l`<div class="loading">loading…</div>`:this._rows.length===0?l`<div class="empty">No programs match the current filters.</div>`:l`
<div class="list">
${this._rows.map(t=>l`
<div
class="row ${this._selectedSlot===t.slot?"selected":""}"
@click=${()=>this._onRowClick(t.slot)}
>
<div class="row-slot">#${t.slot}</div>
<div class="row-summary">
${ie(t.summary,(r,i)=>this._onRefClick(r,i))}
</div>
<div class="row-meta">
<span class="trigger-badge trigger-${t.trigger_type.toLowerCase()}">
${t.trigger_type}
</span>
${t.condition_count>0?l`
<span class="meta-pill">${t.condition_count} cond</span>`:""}
${t.action_count>1?l`
<span class="meta-pill">${t.action_count} actions</span>`:""}
</div>
</div>
`)}
</div>
`}_renderDetail(){if(this._detailLoading)return l`<aside class="detail"><div class="loading">loading…</div></aside>`;if(this._detail===null)return l`<aside class="detail"></aside>`;let t=this._detail;return this._editingDraft!==null?this._renderEditor(t):l`
<aside class="detail">
<header>
<div>
<span class="trigger-badge trigger-${t.trigger_type.toLowerCase()}">
${t.trigger_type}
</span>
<span class="slot">slot #${t.slot}</span>
</div>
<button type="button" class="close" @click=${this._closeDetail}>×</button>
</header>
<pre class="detail-body">${ie(t.tokens,(r,i)=>this._onRefClick(r,i))}</pre>
<footer>
<button
type="button"
class="fire"
@click=${()=>this._fireProgram(t.slot)}
>▶ Fire now</button>
${t.trigger_type==="TIMED"&&t.kind==="compact"?l`
<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?l`
<span class="fire-feedback">${this._fireFeedback}</span>`:""}
${this._writeFeedback?l`
<span class="fire-feedback">${this._writeFeedback}</span>`:""}
</footer>
${this._showCloneInput?l`
<div class="action-row">
<label>Clone slot ${t.slot} → target slot:
<input
type="number"
min="1"
max="1500"
.value=${this._cloneTargetSlot}
@input=${this._onCloneTargetInput}
@keydown=${r=>{r.key==="Enter"&&this._cloneProgram(t.slot)}}
/>
</label>
<button
type="button"
class="primary"
@click=${()=>this._cloneProgram(t.slot)}
>Clone</button>
<button
type="button"
@click=${()=>{this._showCloneInput=!1}}
>Cancel</button>
</div>`:""}
${this._confirmingClear?l`
<div class="action-row danger-row">
<span>
<strong>Clear slot ${t.slot}?</strong>
This deletes the program from the panel.
</span>
<button
type="button"
class="danger"
@click=${()=>this._clearProgram(t.slot)}
>Yes, clear</button>
<button
type="button"
@click=${()=>{this._confirmingClear=!1}}
>Cancel</button>
</div>`:""}
${t.chain_slots&&t.chain_slots.length>1?l`
<div class="chain-info">
spans slots
${t.chain_slots.map((r,i)=>l`
${i>0?"\u2192":""}#${r}`)}
</div>`:""}
</aside>
`}_renderEditor(t){let r=this._editingDraft,i=oe(r.cmd??0),o=i?.ref_kind?this._pickBucket(i.ref_kind):null,n=r.cmd===9;return l`
<aside class="detail editor">
<header>
<div>
<span class="trigger-badge trigger-timed">EDIT • TIMED</span>
<span class="slot">slot #${t.slot}</span>
</div>
<button type="button" class="close" @click=${this._cancelEdit}>×</button>
</header>
<div class="editor-body">
<!-- Time of day -->
<fieldset>
<legend>Time</legend>
<div class="row">
<label>
Hour
<input
type="number" min="0" max="23"
.value=${String(r.hour??0)}
@input=${this._onHourChange}
/>
</label>
<span class="time-colon">:</span>
<label>
Minute
<input
type="number" min="0" max="59" step="1"
.value=${String(r.minute??0)}
@input=${this._onMinuteChange}
/>
</label>
</div>
</fieldset>
<!-- Days bitmask -->
<fieldset>
<legend>Days</legend>
<div class="days-row">
${we.map(a=>{let c=((r.days??0)&a.bit)!==0;return l`
<button
type="button"
class="day-toggle ${c?"active":""}"
@click=${()=>this._toggleDayBit(a.bit)}
>${a.label}</button>
`})}
</div>
</fieldset>
<!-- Action -->
<fieldset>
<legend>Action</legend>
<label class="block">
Command
<select @change=${this._onCommandChange}>
${se.map(a=>l`
<option .value=${String(a.value)}
?selected=${a.value===r.cmd}>
${a.label}
</option>
`)}
</select>
</label>
${i?.ref_kind?l`
<label class="block">
${i.ref_kind[0].toUpperCase()+i.ref_kind.slice(1)}
<select @change=${this._onObjectChange}>
${(o??[]).map(a=>l`
<option .value=${String(a.index)}
?selected=${a.index===r.pr2}>
#${a.index} ${a.name}
</option>
`)}
</select>
</label>`:""}
${n?l`
<label class="block">
Level (0..100)
<input
type="number" min="0" max="100"
.value=${String(r.par??0)}
@input=${this._onParChange}
/>
</label>`:""}
</fieldset>
${r.cond||r.cond2?l`
<div class="conditions-readonly">
<strong>Inline conditions:</strong>
this program has up to two inline AND-IF conditions on the
source record. They're preserved when saving 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?l`
<span class="fire-feedback">${this._writeFeedback}</span>`:""}
</footer>
</aside>
`}};d.styles=V`
: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([N({attribute:!1})],d.prototype,"hass",2),h([N({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([ke("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
*)
*/