Multi-record clausal programs are now editable end-to-end. A chain
spans N consecutive slots — head (WHEN/AT/EVERY) + zero-or-more
AND/OR condition records + one-or-more THEN action records — so
"editing" means rewriting the whole run, validating that any
expansion doesn't trample adjacent programs, and clearing any old
slots when the chain shrinks.
H1 — backend:
* programs/get for chains now returns chain_members[] with each
member's slot + role + raw fields. The editor uses this to seed
one editable form-row per slot.
* New programs/chain/write command: takes head_slot + head dict +
conditions[] + actions[], does N sequential download_program
calls, then clears any old chain slots that fell outside the new
range. Validates:
- head_slot + new_len doesn't extend past slot 1500
- any expansion-into slot not already part of THIS chain is FREE
(anti-trample: refuse rather than overwrite an adjacent program)
- at least one THEN action present (empty chain rejected)
Updates coordinator.data.programs immediately so subsequent list
calls reflect the edit before the next poll.
H2 — TS helpers:
* AND-record encoding mirrors compact-form cond family bytes
(0x04 ZONE / 0x08 CTRL / 0x0C TIME / 0x00 OTHER + 0x10+ SEC) but
with a slightly different bit layout: the family byte lives at
fields.cond & 0xFF (disk byte 1) and the instance at
(fields.cond2 >> 8) & 0xFF (disk byte 3). The selector bit is
family's bit 0x02 instead of cond's 0x0200. decodeAndCondition /
encodeAndCondition handle both directions; round-trip exact.
* isStructuredAnd helper detects records with OP > 0 (TEMP > N
comparisons etc.); those render read-only in the chain editor
with a warning banner.
* emptyAndRecord / emptyOrRecord / emptyThenRecord helpers for
the add-condition / add-action buttons.
H3 — chain editor UI:
* New _chainDraft state (parallel to _editingDraft for compact form)
with head + conditions[] + actions[] arrays. Mutation helpers
preserve immutability via array-copy-then-patch.
* "Edit" button on chain detail now opens the chain editor instead
of returning early (previous read-only behaviour).
* Three sub-renderers: trigger section dispatches on prog_type
(WHEN→event-id builder reusing the EVENT helpers, AT→time+days
reusing TIMED layout, EVERY→single seconds input that packs into
cond+cond2), conditions section with per-row add/remove (separate
+ AND IF and + OR IF buttons in the legend), actions section with
per-row add/remove (+ THEN button; at least one action enforced).
* Structured-OP AND records render with an explanatory read-only
banner and a × button to drop the row entirely — preserves the
data when the user doesn't touch it, lets them remove it cleanly
when they want to.
* Each row picks objects via _bucketWithPreserve so out-of-range
zone/unit/area indices stay safe.
5 new HA integration tests:
* get-chain returns chain_members with correct roles + raw fields
* chain/write in-place rewrite preserves footprint, updates bytes
* chain/write shrink clears the trailing old slots
* chain/write refuses to trample an adjacent program on expansion
* chain/write rejects zero-actions submission
Live screenshot 11-chain-editor.png: state injection into the side
panel (real panel has no chains) shows the editor rendering a sample
WHEN zone-state → AND IF unit ON → 2x THEN action chain with every
control populated and functional.
Full suite: 653 passed, 1 skipped (up from 648, 5 new chain tests).
Frontend bundle: 82 KB minified (up from 63 KB).
1309 lines
80 KiB
JavaScript
1309 lines
80 KiB
JavaScript
// omni_pca side panel — generated by frontend/build.mjs. Edit src/, not this file.
|
||
var Ze=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var m=(s,i,e,t)=>{for(var n=t>1?void 0:t?Ke(i,e):i,r=s.length-1,o;r>=0;r--)(o=s[r])&&(n=(t?o(i,e,n):o(n))||n);return t&&n&&Ze(i,e,n),n};var U=globalThis,Y=U.ShadowRoot&&(U.ShadyCSS===void 0||U.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,K=Symbol(),ye=new WeakMap,R=class{constructor(i,e,t){if(this._$cssResult$=!0,t!==K)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=i,this.t=e}get styleSheet(){let i=this.o,e=this.t;if(Y&&i===void 0){let t=e!==void 0&&e.length===1;t&&(i=ye.get(e)),i===void 0&&((this.o=i=new CSSStyleSheet).replaceSync(this.cssText),t&&ye.set(e,i))}return i}toString(){return this.cssText}},$e=s=>new R(typeof s=="string"?s:s+"",void 0,K),J=(s,...i)=>{let e=s.length===1?s[0]:i.reduce((t,n,r)=>t+(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.")})(n)+s[r+1],s[0]);return new R(e,s,K)},xe=(s,i)=>{if(Y)s.adoptedStyleSheets=i.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of i){let t=document.createElement("style"),n=U.litNonce;n!==void 0&&t.setAttribute("nonce",n),t.textContent=e.cssText,s.appendChild(t)}},X=Y?s=>s:s=>s instanceof CSSStyleSheet?(i=>{let e="";for(let t of i.cssRules)e+=t.cssText;return $e(e)})(s):s;var{is:Je,defineProperty:Xe,getOwnPropertyDescriptor:Qe,getOwnPropertyNames:et,getOwnPropertySymbols:tt,getPrototypeOf:it}=Object,B=globalThis,Ee=B.trustedTypes,nt=Ee?Ee.emptyScript:"",rt=B.reactiveElementPolyfillSupport,D=(s,i)=>s,P={toAttribute(s,i){switch(i){case Boolean:s=s?nt:null;break;case Object:case Array:s=s==null?s:JSON.stringify(s)}return s},fromAttribute(s,i){let e=s;switch(i){case Boolean:e=s!==null;break;case Number:e=s===null?null:Number(s);break;case Object:case Array:try{e=JSON.parse(s)}catch{e=null}}return e}},W=(s,i)=>!Je(s,i),ke={attribute:!0,type:String,converter:P,reflect:!1,useDefault:!1,hasChanged:W};Symbol.metadata??=Symbol("metadata"),B.litPropertyMetadata??=new WeakMap;var y=class extends HTMLElement{static addInitializer(i){this._$Ei(),(this.l??=[]).push(i)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(i,e=ke){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(i)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(i,e),!e.noAccessor){let t=Symbol(),n=this.getPropertyDescriptor(i,t,e);n!==void 0&&Xe(this.prototype,i,n)}}static getPropertyDescriptor(i,e,t){let{get:n,set:r}=Qe(this.prototype,i)??{get(){return this[e]},set(o){this[e]=o}};return{get:n,set(o){let c=n?.call(this);r?.call(this,o),this.requestUpdate(i,c,t)},configurable:!0,enumerable:!0}}static getPropertyOptions(i){return this.elementProperties.get(i)??ke}static _$Ei(){if(this.hasOwnProperty(D("elementProperties")))return;let i=it(this);i.finalize(),i.l!==void 0&&(this.l=[...i.l]),this.elementProperties=new Map(i.elementProperties)}static finalize(){if(this.hasOwnProperty(D("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(D("properties"))){let e=this.properties,t=[...et(e),...tt(e)];for(let n of t)this.createProperty(n,e[n])}let i=this[Symbol.metadata];if(i!==null){let e=litPropertyMetadata.get(i);if(e!==void 0)for(let[t,n]of e)this.elementProperties.set(t,n)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let n=this._$Eu(e,t);n!==void 0&&this._$Eh.set(n,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(i){let e=[];if(Array.isArray(i)){let t=new Set(i.flat(1/0).reverse());for(let n of t)e.unshift(X(n))}else i!==void 0&&e.push(X(i));return e}static _$Eu(i,e){let t=e.attribute;return t===!1?void 0:typeof t=="string"?t:typeof i=="string"?i.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(i=>this.enableUpdating=i),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(i=>i(this))}addController(i){(this._$EO??=new Set).add(i),this.renderRoot!==void 0&&this.isConnected&&i.hostConnected?.()}removeController(i){this._$EO?.delete(i)}_$E_(){let i=new Map,e=this.constructor.elementProperties;for(let t of e.keys())this.hasOwnProperty(t)&&(i.set(t,this[t]),delete this[t]);i.size>0&&(this._$Ep=i)}createRenderRoot(){let i=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return xe(i,this.constructor.elementStyles),i}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(i=>i.hostConnected?.())}enableUpdating(i){}disconnectedCallback(){this._$EO?.forEach(i=>i.hostDisconnected?.())}attributeChangedCallback(i,e,t){this._$AK(i,t)}_$ET(i,e){let t=this.constructor.elementProperties.get(i),n=this.constructor._$Eu(i,t);if(n!==void 0&&t.reflect===!0){let r=(t.converter?.toAttribute!==void 0?t.converter:P).toAttribute(e,t.type);this._$Em=i,r==null?this.removeAttribute(n):this.setAttribute(n,r),this._$Em=null}}_$AK(i,e){let t=this.constructor,n=t._$Eh.get(i);if(n!==void 0&&this._$Em!==n){let r=t.getPropertyOptions(n),o=typeof r.converter=="function"?{fromAttribute:r.converter}:r.converter?.fromAttribute!==void 0?r.converter:P;this._$Em=n;let c=o.fromAttribute(e,r.type);this[n]=c??this._$Ej?.get(n)??c,this._$Em=null}}requestUpdate(i,e,t,n=!1,r){if(i!==void 0){let o=this.constructor;if(n===!1&&(r=this[i]),t??=o.getPropertyOptions(i),!((t.hasChanged??W)(r,e)||t.useDefault&&t.reflect&&r===this._$Ej?.get(i)&&!this.hasAttribute(o._$Eu(i,t))))return;this.C(i,e,t)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(i,e,{useDefault:t,reflect:n,wrapped:r},o){t&&!(this._$Ej??=new Map).has(i)&&(this._$Ej.set(i,o??e??this[i]),r!==!0||o!==void 0)||(this._$AL.has(i)||(this.hasUpdated||t||(e=void 0),this._$AL.set(i,e)),n===!0&&this._$Em!==i&&(this._$Eq??=new Set).add(i))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let i=this.scheduleUpdate();return i!=null&&await i,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[n,r]of this._$Ep)this[n]=r;this._$Ep=void 0}let t=this.constructor.elementProperties;if(t.size>0)for(let[n,r]of t){let{wrapped:o}=r,c=this[n];o!==!0||this._$AL.has(n)||c===void 0||this.C(n,void 0,r,c)}}let i=!1,e=this._$AL;try{i=this.shouldUpdate(e),i?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(t){throw i=!1,this._$EM(),t}i&&this._$AE(e)}willUpdate(i){}_$AE(i){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(i)),this.updated(i)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(i){return!0}update(i){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(i){}firstUpdated(i){}};y.elementStyles=[],y.shadowRootOptions={mode:"open"},y[D("elementProperties")]=new Map,y[D("finalized")]=new Map,rt?.({ReactiveElement:y}),(B.reactiveElementVersions??=[]).push("2.1.2");var se=globalThis,Se=s=>s,V=se.trustedTypes,Ce=V?V.createPolicy("lit-html",{createHTML:s=>s}):void 0,De="$lit$",$=`lit$${Math.random().toFixed(9).slice(2)}$`,Pe="?"+$,st=`<${Pe}>`,S=document,I=()=>S.createComment(""),z=s=>s===null||typeof s!="object"&&typeof s!="function",oe=Array.isArray,ot=s=>oe(s)||typeof s?.[Symbol.iterator]=="function",Q=`[
|
||
\f\r]`,M=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Te=/-->/g,we=/>/g,E=RegExp(`>|${Q}(?:([^\\s"'>=/]+)(${Q}*=${Q}*(?:[^
|
||
\f\r"'\`<>=]|("|')|))|$)`,"g"),Ae=/'/g,Fe=/"/g,Me=/^(?:script|style|textarea|title)$/i,ae=s=>(i,...e)=>({_$litType$:s,strings:i,values:e}),a=ae(1),xt=ae(2),Et=ae(3),C=Symbol.for("lit-noChange"),g=Symbol.for("lit-nothing"),Re=new WeakMap,k=S.createTreeWalker(S,129);function Ie(s,i){if(!oe(s)||!s.hasOwnProperty("raw"))throw Error("invalid template strings array");return Ce!==void 0?Ce.createHTML(i):i}var at=(s,i)=>{let e=s.length-1,t=[],n,r=i===2?"<svg>":i===3?"<math>":"",o=M;for(let c=0;c<e;c++){let l=s[c],u,p,d=-1,b=0;for(;b<l.length&&(o.lastIndex=b,p=o.exec(l),p!==null);)b=o.lastIndex,o===M?p[1]==="!--"?o=Te:p[1]!==void 0?o=we:p[2]!==void 0?(Me.test(p[2])&&(n=RegExp("</"+p[2],"g")),o=E):p[3]!==void 0&&(o=E):o===E?p[0]===">"?(o=n??M,d=-1):p[1]===void 0?d=-2:(d=o.lastIndex-p[2].length,u=p[1],o=p[3]===void 0?E:p[3]==='"'?Fe:Ae):o===Fe||o===Ae?o=E:o===Te||o===we?o=M:(o=E,n=void 0);let _=o===E&&s[c+1].startsWith("/>")?" ":"";r+=o===M?l+st:d>=0?(t.push(u),l.slice(0,d)+De+l.slice(d)+$+_):l+$+(d===-2?c:_)}return[Ie(s,r+(s[e]||"<?>")+(i===2?"</svg>":i===3?"</math>":"")),t]},O=class s{constructor({strings:i,_$litType$:e},t){let n;this.parts=[];let r=0,o=0,c=i.length-1,l=this.parts,[u,p]=at(i,e);if(this.el=s.createElement(u,t),k.currentNode=this.el.content,e===2||e===3){let d=this.el.content.firstChild;d.replaceWith(...d.childNodes)}for(;(n=k.nextNode())!==null&&l.length<c;){if(n.nodeType===1){if(n.hasAttributes())for(let d of n.getAttributeNames())if(d.endsWith(De)){let b=p[o++],_=n.getAttribute(d).split($),j=/([.?@])?(.*)/.exec(b);l.push({type:1,index:r,name:j[2],strings:_,ctor:j[1]==="."?te:j[1]==="?"?ie:j[1]==="@"?ne:A}),n.removeAttribute(d)}else d.startsWith($)&&(l.push({type:6,index:r}),n.removeAttribute(d));if(Me.test(n.tagName)){let d=n.textContent.split($),b=d.length-1;if(b>0){n.textContent=V?V.emptyScript:"";for(let _=0;_<b;_++)n.append(d[_],I()),k.nextNode(),l.push({type:2,index:++r});n.append(d[b],I())}}}else if(n.nodeType===8)if(n.data===Pe)l.push({type:2,index:r});else{let d=-1;for(;(d=n.data.indexOf($,d+1))!==-1;)l.push({type:7,index:r}),d+=$.length-1}r++}}static createElement(i,e){let t=S.createElement("template");return t.innerHTML=i,t}};function w(s,i,e=s,t){if(i===C)return i;let n=t!==void 0?e._$Co?.[t]:e._$Cl,r=z(i)?void 0:i._$litDirective$;return n?.constructor!==r&&(n?._$AO?.(!1),r===void 0?n=void 0:(n=new r(s),n._$AT(s,e,t)),t!==void 0?(e._$Co??=[])[t]=n:e._$Cl=n),n!==void 0&&(i=w(s,n._$AS(s,i.values),n,t)),i}var ee=class{constructor(i,e){this._$AV=[],this._$AN=void 0,this._$AD=i,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(i){let{el:{content:e},parts:t}=this._$AD,n=(i?.creationScope??S).importNode(e,!0);k.currentNode=n;let r=k.nextNode(),o=0,c=0,l=t[0];for(;l!==void 0;){if(o===l.index){let u;l.type===2?u=new L(r,r.nextSibling,this,i):l.type===1?u=new l.ctor(r,l.name,l.strings,this,i):l.type===6&&(u=new re(r,this,i)),this._$AV.push(u),l=t[++c]}o!==l?.index&&(r=k.nextNode(),o++)}return k.currentNode=S,n}p(i){let e=0;for(let t of this._$AV)t!==void 0&&(t.strings!==void 0?(t._$AI(i,t,e),e+=t.strings.length-2):t._$AI(i[e])),e++}},L=class s{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(i,e,t,n){this.type=2,this._$AH=g,this._$AN=void 0,this._$AA=i,this._$AB=e,this._$AM=t,this.options=n,this._$Cv=n?.isConnected??!0}get parentNode(){let i=this._$AA.parentNode,e=this._$AM;return e!==void 0&&i?.nodeType===11&&(i=e.parentNode),i}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(i,e=this){i=w(this,i,e),z(i)?i===g||i==null||i===""?(this._$AH!==g&&this._$AR(),this._$AH=g):i!==this._$AH&&i!==C&&this._(i):i._$litType$!==void 0?this.$(i):i.nodeType!==void 0?this.T(i):ot(i)?this.k(i):this._(i)}O(i){return this._$AA.parentNode.insertBefore(i,this._$AB)}T(i){this._$AH!==i&&(this._$AR(),this._$AH=this.O(i))}_(i){this._$AH!==g&&z(this._$AH)?this._$AA.nextSibling.data=i:this.T(S.createTextNode(i)),this._$AH=i}$(i){let{values:e,_$litType$:t}=i,n=typeof t=="number"?this._$AC(i):(t.el===void 0&&(t.el=O.createElement(Ie(t.h,t.h[0]),this.options)),t);if(this._$AH?._$AD===n)this._$AH.p(e);else{let r=new ee(n,this),o=r.u(this.options);r.p(e),this.T(o),this._$AH=r}}_$AC(i){let e=Re.get(i.strings);return e===void 0&&Re.set(i.strings,e=new O(i)),e}k(i){oe(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,t,n=0;for(let r of i)n===e.length?e.push(t=new s(this.O(I()),this.O(I()),this,this.options)):t=e[n],t._$AI(r),n++;n<e.length&&(this._$AR(t&&t._$AB.nextSibling,n),e.length=n)}_$AR(i=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);i!==this._$AB;){let t=Se(i).nextSibling;Se(i).remove(),i=t}}setConnected(i){this._$AM===void 0&&(this._$Cv=i,this._$AP?.(i))}},A=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(i,e,t,n,r){this.type=1,this._$AH=g,this._$AN=void 0,this.element=i,this.name=e,this._$AM=n,this.options=r,t.length>2||t[0]!==""||t[1]!==""?(this._$AH=Array(t.length-1).fill(new String),this.strings=t):this._$AH=g}_$AI(i,e=this,t,n){let r=this.strings,o=!1;if(r===void 0)i=w(this,i,e,0),o=!z(i)||i!==this._$AH&&i!==C,o&&(this._$AH=i);else{let c=i,l,u;for(i=r[0],l=0;l<r.length-1;l++)u=w(this,c[t+l],e,l),u===C&&(u=this._$AH[l]),o||=!z(u)||u!==this._$AH[l],u===g?i=g:i!==g&&(i+=(u??"")+r[l+1]),this._$AH[l]=u}o&&!n&&this.j(i)}j(i){i===g?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,i??"")}},te=class extends A{constructor(){super(...arguments),this.type=3}j(i){this.element[this.name]=i===g?void 0:i}},ie=class extends A{constructor(){super(...arguments),this.type=4}j(i){this.element.toggleAttribute(this.name,!!i&&i!==g)}},ne=class extends A{constructor(i,e,t,n,r){super(i,e,t,n,r),this.type=5}_$AI(i,e=this){if((i=w(this,i,e,0)??g)===C)return;let t=this._$AH,n=i===g&&t!==g||i.capture!==t.capture||i.once!==t.once||i.passive!==t.passive,r=i!==g&&(t===g||n);n&&this.element.removeEventListener(this.name,this,t),r&&this.element.addEventListener(this.name,this,i),this._$AH=i}handleEvent(i){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,i):this._$AH.handleEvent(i)}},re=class{constructor(i,e,t){this.element=i,this.type=6,this._$AN=void 0,this._$AM=e,this.options=t}get _$AU(){return this._$AM._$AU}_$AI(i){w(this,i)}};var lt=se.litHtmlPolyfillSupport;lt?.(O,L),(se.litHtmlVersions??=[]).push("3.3.3");var ze=(s,i,e)=>{let t=e?.renderBefore??i,n=t._$litPart$;if(n===void 0){let r=e?.renderBefore??null;t._$litPart$=n=new L(i.insertBefore(I(),r),r,void 0,e??{})}return n._$AI(s),n};var le=globalThis,x=class extends y{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let i=super.createRenderRoot();return this.renderOptions.renderBefore??=i.firstChild,i}update(i){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(i),this._$Do=ze(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return C}};x._$litElement$=!0,x.finalized=!0,le.litElementHydrateSupport?.({LitElement:x});var ct=le.litElementPolyfillSupport;ct?.({LitElement:x});(le.litElementVersions??=[]).push("4.2.2");var Oe=s=>(i,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(s,i)}):customElements.define(s,i)};var dt={attribute:!0,type:String,converter:P,reflect:!1,hasChanged:W},ut=(s=dt,i,e)=>{let{kind:t,metadata:n}=e,r=globalThis.litPropertyMetadata.get(n);if(r===void 0&&globalThis.litPropertyMetadata.set(n,r=new Map),t==="setter"&&((s=Object.create(s)).wrapped=!0),r.set(e.name,s),t==="accessor"){let{name:o}=e;return{set(c){let l=i.get.call(this);i.set.call(this,c),this.requestUpdate(o,l,s,!0,c)},init(c){return c!==void 0&&this.C(o,void 0,s,c),c}}}if(t==="setter"){let{name:o}=e;return function(c){let l=this[o];i.call(this,c),this.requestUpdate(o,l,s,!0,c)}}throw Error("Unsupported decorator location: "+t)};function N(s){return(i,e)=>typeof e=="object"?ut(s,i,e):((t,n,r)=>{let o=n.hasOwnProperty(r);return n.constructor.createProperty(r,t),o?Object.getOwnPropertyDescriptor(n,r):void 0})(s,i,e)}function f(s){return N({...s,state:!0,attribute:!1})}function ce(s,i){return a`${s.map(e=>pt(e,i))}`}function pt(s,i){switch(s.k){case"newline":return a`<br />`;case"indent":return a`<span class="indent">${s.t}</span>`;case"keyword":return a`<span class="keyword">${s.t}</span>`;case"operator":return a`<span class="operator">${s.t}</span>`;case"value":return a`<span class="value">${s.t}</span>`;case"ref":{let e=i&&s.ek&&typeof s.ei=="number"?()=>i(s.ek,s.ei):void 0;return a`<button
|
||
type="button"
|
||
class="ref ref-${s.ek}"
|
||
title=${s.ek??""}
|
||
@click=${e}
|
||
>
|
||
<span class="ref-name">${s.t}</span>
|
||
${s.s?a`<span class="ref-state">${s.s}</span>`:""}
|
||
</button>`}default:return a`<span>${s.t}</span>`}}var G=[{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 H(s){return G.find(i=>i.value===s)}var de=[{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"}],ue=1,pe=2,he=3;var Z=[{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(s){if(Z.some(i=>i.id===s))return{category:"fixed",fixedId:s};if(!(s&65280))return{category:"button",button:s&255};if((s&64512)===1024){let i=s&1023;return{category:"zone",zone:Math.floor(i/4)+1,zoneState:i%4}}if((s&64512)===2048){let i=s&1023;return{category:"unit",unit:Math.floor(i/2)+1,unitOn:(i&1)===1}}return{category:"raw",raw:s}}function me(s){switch(s.category){case"button":return(s.button??1)&255;case"zone":{let i=(s.zone??1)-1,e=(s.zoneState??0)&3;return 1024|i*4+e&1023}case"unit":{let i=(s.unit??1)-1,e=s.unitOn?1:0;return 2048|i*2+e&1023}case"fixed":return s.fixedId??768;case"raw":default:return s.raw??0}}function F(s){return(s.month??0)<<8|(s.day??0)}function Le(s,i){return{...s,month:i>>8&255,day:i&255}}var Ne=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],fe=[{value:0,label:"always"},{value:1,label:"never"},{value:2,label:"it is light outside"},{value:3,label:"it is dark outside"},{value:4,label:"phone line is dead"},{value:5,label:"phone is ringing"},{value:6,label:"phone is off hook"},{value:7,label:"phone is on hook"},{value:8,label:"AC power is off"},{value:9,label:"AC power is on"},{value:10,label:"battery is low"},{value:11,label:"battery is OK"},{value:12,label:"energy cost is low"},{value:13,label:"energy cost is mid"},{value:14,label:"energy cost is high"},{value:15,label:"energy cost is critical"}],ge=[{value:0,label:"Off (disarmed)"},{value:1,label:"Day"},{value:2,label:"Night"},{value:3,label:"Away"},{value:4,label:"Vacation"},{value:5,label:"Day Instant"},{value:6,label:"Night Delayed"}];function He(s){if(s===0)return{family:"none"};let i=s>>8&252,e=(s&512)!==0;return i===0?{family:"misc",misc:s&15}:i===4?{family:"zone",index:s&255,active:e}:i===8?{family:"unit",index:s&511,active:e}:i===12?{family:"time",index:s&255,active:e}:{family:"sec",index:s>>8&15,mode:s>>12&7}}function v(s){switch(s.family){case"none":return 0;case"misc":return(s.misc??0)&15;case"zone":{let i=(s.index??0)&255;return 1024|(s.active?512:0)|i}case"unit":{let i=(s.index??0)&511;return 2048|(s.active?512:0)|i}case"time":{let i=(s.index??0)&255;return 3072|(s.active?512:0)|i}case"sec":{let i=(s.index??1)&15;return((s.mode??0)&7)<<12|i<<8}}}var je=5,Ue=6,Ye=7,ht=8,be=9,mt=10;function Be(s){let i=(s.cond??0)&255,e=(s.cond2??0)>>8&255,t=i&252,n=(i&2)!==0;return i===0&&e===0?{family:"none"}:t===0?{family:"misc",misc:i&15}:t===4?{family:"zone",index:e,active:n}:t===8?{family:"unit",index:e,active:n}:t===12?{family:"time",index:e,active:n}:{family:"sec",index:i&15,mode:i>>4&7}}function ve(s){switch(s.family){case"none":return{cond:0,cond2:0};case"misc":return{cond:(s.misc??0)&15,cond2:0};case"zone":return{cond:4|(s.active?2:0),cond2:((s.index??0)&255)<<8};case"unit":return{cond:8|(s.active?2:0),cond2:((s.index??0)&255)<<8};case"time":return{cond:12|(s.active?2:0),cond2:((s.index??0)&255)<<8};case"sec":{let i=(s.index??1)&15;return{cond:((s.mode??0)&7)<<4|i,cond2:0}}}}function We(s){return((s.cond??0)>>8&255)!==0}function _e(){return{prog_type:ht,cond:1,cond2:0,cmd:0,par:0,pr2:0,month:0,day:0,days:0,hour:0,minute:0}}function Ve(){return{..._e(),prog_type:be}}function qe(s=1){return{prog_type:mt,cmd:0,par:0,pr2:s,cond:0,cond2:0,month:0,day:0,days:0,hour:0,minute:0}}var Ge=new Set(["TIMED","EVENT","YEARLY"]),ft=["TIMED","EVENT","YEARLY","WHEN","AT","EVERY","REMARK"],gt=5e3,h=class extends x{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._chainDraft=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 t=(await this.hass.connection.sendMessagePromise({type:"config_entries/get"})).filter(r=>r.domain==="omni_pca");if(t.length===0){this._error="No Omni panel configured. Add one via Settings \u2192 Devices & Services.";return}let n=t.find(r=>r.state==="loaded");this._entryId=(n??t[0]).entry_id,this._error=null,this._loadList(),this._startRefreshTimer()}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 t=await this.hass.connection.sendMessagePromise(e);this._rows=t.programs,this._total=t.total,this._filteredTotal=t.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(t){this._error=t instanceof Error?t.message:String(t)}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(t){this._fireFeedback=`error: ${t instanceof Error?t.message:t}`}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(t){let n=t instanceof Error?t.message:String(t);this._writeFeedback=`error: ${n}`}setTimeout(()=>{this._writeFeedback=null},4e3)}}async _cloneProgram(e){if(!this._entryId)return;let t=this._cloneTargetSlot.trim(),n=parseInt(t,10);if(!Number.isFinite(n)||n<1||n>1500){this._writeFeedback="target slot must be 1..1500",setTimeout(()=>{this._writeFeedback=null},4e3);return}if(n===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:n}),this._writeFeedback=`cloned to slot ${n}`,this._showCloneInput=!1,this._cloneTargetSlot="",this._selectedSlot=n,await this._loadList(),await this._loadDetail(n)}catch(r){let o=r instanceof Error?r.message:String(r);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 t=e instanceof Error?e.message:String(e);console.warn("omni_pca: objects/list failed",t)}}async _beginEdit(){if(!this._detail||(await this._ensureObjectsLoaded(),!this._entryId))return;if(this._detail.kind==="chain"){this._beginChainEdit();return}if(!Ge.has(this._detail.trigger_type))return;let e=this._detail.fields??this._defaultFieldsForType(this._detail.trigger_type);e!==null&&(this._editingDraft={...e},this._stopRefreshTimer())}_beginChainEdit(){if(!this._detail||!this._detail.chain_members)return;let e=this._detail.chain_members,t=e.find(n=>n.role==="head");t&&(this._chainDraft={headSlot:t.slot,head:{...t.fields},conditions:e.filter(n=>n.role==="condition").map(n=>({...n.fields})),actions:e.filter(n=>n.role==="action").map(n=>({...n.fields}))},this._stopRefreshTimer())}_cancelChainEdit(){this._chainDraft=null,this._startRefreshTimer()}async _saveChainDraft(){if(!(!this._chainDraft||!this._entryId)){this._writeFeedback="saving chain\u2026";try{await this.hass.connection.sendMessagePromise({type:"omni_pca/programs/chain/write",entry_id:this._entryId,head_slot:this._chainDraft.headSlot,head:this._chainDraft.head,conditions:this._chainDraft.conditions,actions:this._chainDraft.actions}),this._writeFeedback=`saved chain @ slot ${this._chainDraft.headSlot}`;let e=this._chainDraft.headSlot;this._chainDraft=null,this._startRefreshTimer(),await this._loadList(),await this._loadDetail(e)}catch(e){let t=e instanceof Error?e.message:String(e);this._writeFeedback=`error: ${t}`}setTimeout(()=>{this._writeFeedback=null},4e3)}}_patchChainHead(e){this._chainDraft&&(this._chainDraft={...this._chainDraft,head:{...this._chainDraft.head,...e}})}_patchChainCondition(e,t){if(!this._chainDraft)return;let n=[...this._chainDraft.conditions];n[e]={...n[e],...t},this._chainDraft={...this._chainDraft,conditions:n}}_addChainCondition(e=!1){if(!this._chainDraft)return;let t=e?Ve():_e();this._chainDraft={...this._chainDraft,conditions:[...this._chainDraft.conditions,t]}}_removeChainCondition(e){if(!this._chainDraft)return;let t=this._chainDraft.conditions.filter((n,r)=>r!==e);this._chainDraft={...this._chainDraft,conditions:t}}_patchChainAction(e,t){if(!this._chainDraft)return;let n=[...this._chainDraft.actions];n[e]={...n[e],...t},this._chainDraft={...this._chainDraft,actions:n}}_addChainAction(){if(!this._chainDraft)return;let e=this._objects?.units?.[0]?.index??1;this._chainDraft={...this._chainDraft,actions:[...this._chainDraft.actions,qe(e)]}}_removeChainAction(e){if(!this._chainDraft||this._chainDraft.actions.length<=1)return;let t=this._chainDraft.actions.filter((n,r)=>r!==e);this._chainDraft={...this._chainDraft,actions:t}}_defaultFieldsForType(e){let t=this._objects?.units?.[0]?.index??1;if(e==="TIMED")return{prog_type:ue,cmd:1,par:0,pr2:t,hour:6,minute:0,days:62,cond:0,cond2:0,month:0,day:0};if(e==="EVENT"){let n=this._objects?.buttons?.[0]?.index??1;return{prog_type:pe,cmd:1,par:0,pr2:t,month:0,day:n&255,hour:0,minute:0,days:0,cond:0,cond2:0}}return e==="YEARLY"?{prog_type:he,cmd:1,par:0,pr2:t,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 t=e instanceof Error?e.message:String(e);this._writeFeedback=`error: ${t}`}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 n=(this._editingDraft.days??0)^e;this._patchDraft({days:n})}_onCommandChange(e){let t=parseInt(e.target.value,10);if(!Number.isFinite(t))return;let n=H(t),r=this._editingDraft?.pr2??0;if(n?.ref_kind&&this._objects){let o=this._pickBucket(n.ref_kind);o&&o.length>0&&!o.some(c=>c.index===r)&&(r=o[0].index)}else n?.ref_kind||(r=0);this._patchDraft({cmd:t,pr2:r})}_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}}_bucketWithPreserve(e,t,n){let r=e??[];return n===0||r.some(o=>o.index===n)?r:[{index:n,name:`(undiscovered ${t} ${n} \u2014 preserve original)`},...r]}_onObjectChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&this._patchDraft({pr2:t})}_onHourChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&t>=0&&t<=23&&this._patchDraft({hour:t})}_onMinuteChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&t>=0&&t<=59&&this._patchDraft({minute:t})}_onParChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&t>=0&&t<=255&&this._patchDraft({par:t})}_onMonthChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&t>=1&&t<=12&&this._patchDraft({month:t})}_onDayChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&t>=1&&t<=31&&this._patchDraft({day:t})}_patchEvent(e){if(!this._editingDraft)return;let t=me(e);this._editingDraft=Le(this._editingDraft,t)}_onEventCategoryChange(e){let t=e.target.value;if(t==="button"){let n=this._objects?.buttons?.[0]?.index??1;this._patchEvent({category:"button",button:n})}else if(t==="zone"){let n=this._objects?.zones?.[0]?.index??1;this._patchEvent({category:"zone",zone:n,zoneState:1})}else if(t==="unit"){let n=this._objects?.units?.[0]?.index??1;this._patchEvent({category:"unit",unit:n,unitOn:!0})}else t==="fixed"&&this._patchEvent({category:"fixed",fixedId:772})}_onEventButtonChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&this._patchEvent({category:"button",button:t})}_onEventZoneChange(e){if(!this._editingDraft)return;let t=parseInt(e.target.value,10);if(!Number.isFinite(t))return;let n=T(F(this._editingDraft));this._patchEvent({category:"zone",zone:t,zoneState:n.zoneState??1})}_onEventZoneStateChange(e){if(!this._editingDraft)return;let t=parseInt(e.target.value,10);if(!Number.isFinite(t))return;let n=T(F(this._editingDraft));this._patchEvent({category:"zone",zone:n.zone??1,zoneState:t})}_onEventUnitChange(e){if(!this._editingDraft)return;let t=parseInt(e.target.value,10);if(!Number.isFinite(t))return;let n=T(F(this._editingDraft));this._patchEvent({category:"unit",unit:t,unitOn:n.unitOn??!0})}_onEventUnitOnChange(e){if(!this._editingDraft)return;let t=e.target.value==="1",n=T(F(this._editingDraft));this._patchEvent({category:"unit",unit:n.unit??1,unitOn:t})}_onEventFixedChange(e){let t=parseInt(e.target.value,10);Number.isFinite(t)&&this._patchEvent({category:"fixed",fixedId:t})}_startRefreshTimer(){this._refreshTimer===null&&(this._refreshTimer=window.setInterval(()=>{this._loadList(),this._selectedSlot!==null&&this._loadDetail(this._selectedSlot)},gt))}_stopRefreshTimer(){this._refreshTimer!==null&&(window.clearInterval(this._refreshTimer),this._refreshTimer=null)}_toggleTriggerFilter(e){let t=new Set(this._activeTriggerTypes);t.has(e)?t.delete(e):t.add(e),this._activeTriggerTypes=t,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,t){this._referenceFilter=`${e}:${t}`,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">
|
||
${ft.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">
|
||
${ce(e.summary,(t,n)=>this._onRefClick(t,n))}
|
||
</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):this._chainDraft!==null?this._renderChainEditor(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">${ce(e.tokens,(t,n)=>this._onRefClick(t,n))}</pre>
|
||
<footer>
|
||
<button
|
||
type="button"
|
||
class="fire"
|
||
@click=${()=>this._fireProgram(e.slot)}
|
||
>▶ Fire now</button>
|
||
${e.kind==="compact"&&Ge.has(e.trigger_type)||e.kind==="chain"?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=${t=>{t.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((t,n)=>a`
|
||
${n>0?"\u2192":""}#${t}`)}
|
||
</div>`:""}
|
||
</aside>
|
||
`}_renderEditor(e){let t=this._editingDraft,n=e.trigger_type;return a`
|
||
<aside class="detail editor">
|
||
<header>
|
||
<div>
|
||
<span class="trigger-badge trigger-${n.toLowerCase()}">
|
||
EDIT • ${n}
|
||
</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(t)}
|
||
${this._renderActionSection(t)}
|
||
${this._renderConditionsSection(t)}
|
||
</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 ue:return this._renderTimedTrigger(e);case pe:return this._renderEventTrigger(e);case he: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">
|
||
${de.map(t=>{let n=((e.days??0)&t.bit)!==0;return a`
|
||
<button
|
||
type="button"
|
||
class="day-toggle ${n?"active":""}"
|
||
@click=${()=>this._toggleDayBit(t.bit)}
|
||
>${t.label}</button>
|
||
`})}
|
||
</div>
|
||
</fieldset>
|
||
`}_renderEventTrigger(e){let t=F(e),n=T(t);return a`
|
||
<fieldset>
|
||
<legend>Trigger event</legend>
|
||
<label class="block">
|
||
Category
|
||
<select @change=${this._onEventCategoryChange}>
|
||
<option value="button"
|
||
?selected=${n.category==="button"}>
|
||
Button press
|
||
</option>
|
||
<option value="zone"
|
||
?selected=${n.category==="zone"}>
|
||
Zone state change
|
||
</option>
|
||
<option value="unit"
|
||
?selected=${n.category==="unit"}>
|
||
Unit state change
|
||
</option>
|
||
<option value="fixed"
|
||
?selected=${n.category==="fixed"}>
|
||
Fixed event (phone / AC)
|
||
</option>
|
||
${n.category==="raw"?a`
|
||
<option value="raw" selected>
|
||
Raw 0x${t.toString(16).padStart(4,"0")}
|
||
</option>`:""}
|
||
</select>
|
||
</label>
|
||
${this._renderEventCategoryFields(n)}
|
||
</fieldset>
|
||
`}_renderEventCategoryFields(e){if(e.category==="button"){let t=this._bucketWithPreserve(this._objects?.buttons??null,"button",e.button??0);return a`
|
||
<label class="block">
|
||
Button
|
||
<select @change=${this._onEventButtonChange}>
|
||
${t.map(n=>a`
|
||
<option .value=${String(n.index)}
|
||
?selected=${n.index===e.button}>
|
||
#${n.index} ${n.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`}if(e.category==="zone"){let t=this._bucketWithPreserve(this._objects?.zones??null,"zone",e.zone??0);return a`
|
||
<label class="block">
|
||
Zone
|
||
<select @change=${this._onEventZoneChange}>
|
||
${t.map(n=>a`
|
||
<option .value=${String(n.index)}
|
||
?selected=${n.index===e.zone}>
|
||
#${n.index} ${n.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>`}if(e.category==="unit"){let t=this._bucketWithPreserve(this._objects?.units??null,"unit",e.unit??0);return a`
|
||
<label class="block">
|
||
Unit
|
||
<select @change=${this._onEventUnitChange}>
|
||
${t.map(n=>a`
|
||
<option .value=${String(n.index)}
|
||
?selected=${n.index===e.unit}>
|
||
#${n.index} ${n.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>`}return e.category==="fixed"?a`
|
||
<label class="block">
|
||
Event
|
||
<select @change=${this._onEventFixedChange}>
|
||
${Z.map(t=>a`
|
||
<option .value=${String(t.id)}
|
||
?selected=${t.id===e.fixedId}>
|
||
${t.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}>
|
||
${Ne.map((t,n)=>a`
|
||
<option .value=${String(n+1)}
|
||
?selected=${(e.month??1)===n+1}>
|
||
${t} (${n+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 t=H(e.cmd??0),n=t?.ref_kind?this._bucketWithPreserve(this._pickBucket(t.ref_kind),t.ref_kind,e.pr2??0):null,r=e.cmd===9;return a`
|
||
<fieldset>
|
||
<legend>Action</legend>
|
||
<label class="block">
|
||
Command
|
||
<select @change=${this._onCommandChange}>
|
||
${G.map(o=>a`
|
||
<option .value=${String(o.value)}
|
||
?selected=${o.value===e.cmd}>
|
||
${o.label}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>
|
||
${t?.ref_kind?a`
|
||
<label class="block">
|
||
${t.ref_kind[0].toUpperCase()+t.ref_kind.slice(1)}
|
||
<select @change=${this._onObjectChange}>
|
||
${(n??[]).map(o=>a`
|
||
<option .value=${String(o.index)}
|
||
?selected=${o.index===e.pr2}>
|
||
#${o.index} ${o.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`:""}
|
||
${r?a`
|
||
<label class="block">
|
||
Level (0..100)
|
||
<input
|
||
type="number" min="0" max="100"
|
||
.value=${String(e.par??0)}
|
||
@input=${this._onParChange}
|
||
/>
|
||
</label>`:""}
|
||
</fieldset>
|
||
`}_renderConditionsSection(e){return a`
|
||
<fieldset>
|
||
<legend>Inline AND-IF conditions</legend>
|
||
${this._renderConditionSlot("First condition",e.cond??0,t=>this._patchDraft({cond:t}))}
|
||
${this._renderConditionSlot("Second condition",e.cond2??0,t=>this._patchDraft({cond2:t}))}
|
||
</fieldset>
|
||
`}_renderConditionSlot(e,t,n){let r=He(t),o=c=>{let l=this._objects?.zones?.[0]?.index??1,u=this._objects?.units?.[0]?.index??1,p=this._objects?.areas?.[0]?.index??1,d;switch(c){case"none":d={family:"none"};break;case"misc":d={family:"misc",misc:1};break;case"zone":d={family:"zone",index:l,active:!1};break;case"unit":d={family:"unit",index:u,active:!0};break;case"time":d={family:"time",index:1,active:!0};break;case"sec":d={family:"sec",index:p,mode:0};break}n(v(d))};return a`
|
||
<div class="cond-slot">
|
||
<label class="block cond-family-label">
|
||
${e}
|
||
<select @change=${c=>o(c.target.value)}>
|
||
<option value="none" ?selected=${r.family==="none"}>(none)</option>
|
||
<option value="zone" ?selected=${r.family==="zone"}>Zone state</option>
|
||
<option value="unit" ?selected=${r.family==="unit"}>Unit state</option>
|
||
<option value="sec" ?selected=${r.family==="sec"}>Area in security mode</option>
|
||
<option value="time" ?selected=${r.family==="time"}>Time clock</option>
|
||
<option value="misc" ?selected=${r.family==="misc"}>Misc (light, AC power, …)</option>
|
||
</select>
|
||
</label>
|
||
${this._renderConditionSubfields(r,n)}
|
||
</div>
|
||
`}_renderConditionSubfields(e,t){if(e.family==="none")return a``;if(e.family==="zone"){let n=this._bucketWithPreserve(this._objects?.zones??null,"zone",e.index??0);return a`
|
||
<label class="block">
|
||
Zone
|
||
<select @change=${r=>{let o=parseInt(r.target.value,10);t(v({...e,index:o}))}}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)}
|
||
?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${r=>{let o=r.target.value==="1";t(v({...e,active:o}))}}>
|
||
<option value="0" ?selected=${!e.active}>secure</option>
|
||
<option value="1" ?selected=${e.active}>not ready</option>
|
||
</select>
|
||
</label>`}if(e.family==="unit"){let n=this._bucketWithPreserve(this._objects?.units??null,"unit",e.index??0);return a`
|
||
<label class="block">
|
||
Unit
|
||
<select @change=${r=>{let o=parseInt(r.target.value,10);t(v({...e,index:o}))}}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)}
|
||
?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${r=>{let o=r.target.value==="1";t(v({...e,active:o}))}}>
|
||
<option value="1" ?selected=${e.active}>ON</option>
|
||
<option value="0" ?selected=${!e.active}>OFF</option>
|
||
</select>
|
||
</label>`}if(e.family==="sec"){let n=this._bucketWithPreserve(this._objects?.areas??null,"area",e.index??0);return a`
|
||
<label class="block">
|
||
Area
|
||
<select @change=${r=>{let o=parseInt(r.target.value,10);t(v({...e,index:o}))}}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)}
|
||
?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Mode
|
||
<select @change=${r=>{let o=parseInt(r.target.value,10);t(v({...e,mode:o}))}}>
|
||
${ge.map(r=>a`
|
||
<option .value=${String(r.value)}
|
||
?selected=${r.value===e.mode}>
|
||
${r.label}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`}return e.family==="time"?a`
|
||
<label class="block">
|
||
Time clock # (1..3)
|
||
<input
|
||
type="number" min="1" max="3"
|
||
.value=${String(e.index??1)}
|
||
@input=${n=>{let r=parseInt(n.target.value,10);Number.isFinite(r)&&t(v({...e,index:r}))}}
|
||
/>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${n=>{let r=n.target.value==="1";t(v({...e,active:r}))}}>
|
||
<option value="1" ?selected=${e.active}>enabled</option>
|
||
<option value="0" ?selected=${!e.active}>disabled</option>
|
||
</select>
|
||
</label>`:a`
|
||
<label class="block">
|
||
Condition
|
||
<select @change=${n=>{let r=parseInt(n.target.value,10);t(v({family:"misc",misc:r}))}}>
|
||
${fe.map(n=>a`
|
||
<option .value=${String(n.value)}
|
||
?selected=${n.value===e.misc}>
|
||
${n.label}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`}_renderChainEditor(e){let t=this._chainDraft;return a`
|
||
<aside class="detail editor">
|
||
<header>
|
||
<div>
|
||
<span class="trigger-badge trigger-${e.trigger_type.toLowerCase()}">
|
||
EDIT • ${e.trigger_type}
|
||
</span>
|
||
<span class="slot">head @ slot #${t.headSlot}</span>
|
||
</div>
|
||
<button type="button" class="close" @click=${this._cancelChainEdit}>×</button>
|
||
</header>
|
||
|
||
<div class="editor-body">
|
||
${this._renderChainHeadSection(t.head)}
|
||
${this._renderChainConditionsSection(t.conditions)}
|
||
${this._renderChainActionsSection(t.actions)}
|
||
<div class="chain-meta">
|
||
Chain will occupy <strong>${1+t.conditions.length+t.actions.length}</strong>
|
||
consecutive slots starting at #${t.headSlot}.
|
||
</div>
|
||
</div>
|
||
|
||
<footer>
|
||
<button type="button" class="primary" @click=${this._saveChainDraft}>
|
||
Save chain
|
||
</button>
|
||
<button type="button" class="secondary" @click=${this._cancelChainEdit}>
|
||
Cancel
|
||
</button>
|
||
${this._writeFeedback?a`
|
||
<span class="fire-feedback">${this._writeFeedback}</span>`:""}
|
||
</footer>
|
||
</aside>
|
||
`}_renderChainHeadSection(e){return e.prog_type===je?this._renderEventTriggerChain(e):e.prog_type===Ue?this._renderTimedTriggerChain(e):e.prog_type===Ye?this._renderEveryTriggerChain(e):a`
|
||
<div class="conditions-readonly">
|
||
Editing trigger type ${e.prog_type} (chain head) is not supported.
|
||
</div>`}_renderTimedTriggerChain(e){return a`
|
||
<fieldset>
|
||
<legend>AT (trigger)</legend>
|
||
<div class="row">
|
||
<label>
|
||
Hour
|
||
<input type="number" min="0" max="23"
|
||
.value=${String(e.hour??0)}
|
||
@input=${t=>this._patchChainHead({hour:parseInt(t.target.value,10)||0})}
|
||
/>
|
||
</label>
|
||
<span class="time-colon">:</span>
|
||
<label>
|
||
Minute
|
||
<input type="number" min="0" max="59"
|
||
.value=${String(e.minute??0)}
|
||
@input=${t=>this._patchChainHead({minute:parseInt(t.target.value,10)||0})}
|
||
/>
|
||
</label>
|
||
</div>
|
||
<div class="days-row">
|
||
${de.map(t=>{let n=((e.days??0)&t.bit)!==0;return a`
|
||
<button type="button"
|
||
class="day-toggle ${n?"active":""}"
|
||
@click=${()=>this._patchChainHead({days:(e.days??0)^t.bit})}
|
||
>${t.label}</button>`})}
|
||
</div>
|
||
</fieldset>
|
||
`}_renderEventTriggerChain(e){let t=(e.month??0)<<8|(e.day??0),n=T(t),r=o=>{let c=me(o);this._patchChainHead({month:c>>8&255,day:c&255})};return a`
|
||
<fieldset>
|
||
<legend>WHEN (trigger event)</legend>
|
||
<label class="block">
|
||
Category
|
||
<select @change=${o=>{let c=o.target.value;if(c==="button"){let l=this._objects?.buttons?.[0]?.index??1;r({category:"button",button:l})}else if(c==="zone"){let l=this._objects?.zones?.[0]?.index??1;r({category:"zone",zone:l,zoneState:1})}else if(c==="unit"){let l=this._objects?.units?.[0]?.index??1;r({category:"unit",unit:l,unitOn:!0})}else c==="fixed"&&r({category:"fixed",fixedId:772})}}>
|
||
<option value="button" ?selected=${n.category==="button"}>Button press</option>
|
||
<option value="zone" ?selected=${n.category==="zone"}>Zone state change</option>
|
||
<option value="unit" ?selected=${n.category==="unit"}>Unit state change</option>
|
||
<option value="fixed" ?selected=${n.category==="fixed"}>Fixed (phone / AC)</option>
|
||
${n.category==="raw"?a`
|
||
<option value="raw" selected>Raw 0x${t.toString(16).padStart(4,"0")}</option>`:""}
|
||
</select>
|
||
</label>
|
||
${this._renderChainEventSubfields(n,r)}
|
||
</fieldset>
|
||
`}_renderChainEventSubfields(e,t){if(e.category==="button"){let n=this._bucketWithPreserve(this._objects?.buttons??null,"button",e.button??0);return a`
|
||
<label class="block">
|
||
Button
|
||
<select @change=${r=>t({category:"button",button:parseInt(r.target.value,10)})}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)}
|
||
?selected=${r.index===e.button}>
|
||
#${r.index} ${r.name}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`}if(e.category==="zone"){let n=this._bucketWithPreserve(this._objects?.zones??null,"zone",e.zone??0);return a`
|
||
<label class="block">
|
||
Zone
|
||
<select @change=${r=>t({...e,category:"zone",zone:parseInt(r.target.value,10),zoneState:e.zoneState??1})}>
|
||
${n.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=${r=>t({...e,category:"zone",zone:e.zone??1,zoneState:parseInt(r.target.value,10)})}>
|
||
<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>`}if(e.category==="unit"){let n=this._bucketWithPreserve(this._objects?.units??null,"unit",e.unit??0);return a`
|
||
<label class="block">
|
||
Unit
|
||
<select @change=${r=>t({...e,category:"unit",unit:parseInt(r.target.value,10),unitOn:e.unitOn??!0})}>
|
||
${n.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=${r=>t({...e,category:"unit",unit:e.unit??1,unitOn:r.target.value==="1"})}>
|
||
<option value="1" ?selected=${e.unitOn===!0}>ON</option>
|
||
<option value="0" ?selected=${e.unitOn===!1}>OFF</option>
|
||
</select>
|
||
</label>`}return e.category==="fixed"?a`
|
||
<label class="block">
|
||
Event
|
||
<select @change=${n=>t({category:"fixed",fixedId:parseInt(n.target.value,10)})}>
|
||
${Z.map(n=>a`
|
||
<option .value=${String(n.id)}
|
||
?selected=${n.id===e.fixedId}>
|
||
${n.label}
|
||
</option>
|
||
`)}
|
||
</select>
|
||
</label>`:a`<div class="conditions-readonly">Unrecognised event ID. Pick a category to redefine.</div>`}_renderEveryTriggerChain(e){let t=((e.cond??0)&255)<<8|(e.cond2??0)>>8&255;return a`
|
||
<fieldset>
|
||
<legend>EVERY (interval, seconds)</legend>
|
||
<label class="block">
|
||
Seconds between fires
|
||
<input type="number" min="1" max="65535"
|
||
.value=${String(t||1)}
|
||
@input=${n=>{let r=parseInt(n.target.value,10);!Number.isFinite(r)||r<1||this._patchChainHead({cond:r>>8&255,cond2:(r&255)<<8})}}
|
||
/>
|
||
</label>
|
||
</fieldset>
|
||
`}_renderChainConditionsSection(e){return a`
|
||
<fieldset>
|
||
<legend>
|
||
Conditions (${e.length})
|
||
<button type="button" class="mini-btn" @click=${()=>this._addChainCondition(!1)}>
|
||
+ AND IF
|
||
</button>
|
||
<button type="button" class="mini-btn" @click=${()=>this._addChainCondition(!0)}>
|
||
+ OR IF
|
||
</button>
|
||
</legend>
|
||
${e.length===0?a`
|
||
<div class="conditions-readonly">
|
||
No conditions — chain fires unconditionally when triggered.
|
||
</div>`:""}
|
||
${e.map((t,n)=>this._renderChainConditionRow(t,n))}
|
||
</fieldset>
|
||
`}_renderChainConditionRow(e,t){let n=e.prog_type===be;if(We(e))return a`
|
||
<div class="cond-slot structured-cond">
|
||
<div>
|
||
<strong>${n?"OR IF":"AND IF"}</strong> (structured comparison — read-only)
|
||
<button type="button" class="mini-btn danger"
|
||
@click=${()=>this._removeChainCondition(t)}>×</button>
|
||
</div>
|
||
<div class="conditions-readonly">
|
||
This condition uses a structured comparison (TEMP > N etc.).
|
||
Editing structured-OP records is not yet supported; it's
|
||
preserved on save.
|
||
</div>
|
||
</div>`;let r=Be(e);return a`
|
||
<div class="cond-slot">
|
||
<div class="cond-row-header">
|
||
<strong>${n?"OR IF":"AND IF"}</strong>
|
||
<button type="button" class="mini-btn danger"
|
||
@click=${()=>this._removeChainCondition(t)}>×</button>
|
||
</div>
|
||
${this._renderChainCondFamily(r,t)}
|
||
</div>`}_renderChainCondFamily(e,t){let n=o=>{let c=this._objects?.zones?.[0]?.index??1,l=this._objects?.units?.[0]?.index??1,u=this._objects?.areas?.[0]?.index??1,p;switch(o){case"none":p={family:"none"};break;case"misc":p={family:"misc",misc:1};break;case"zone":p={family:"zone",index:c,active:!1};break;case"unit":p={family:"unit",index:l,active:!0};break;case"time":p={family:"time",index:1,active:!0};break;case"sec":p={family:"sec",index:u,mode:0};break}let d=ve(p);this._patchChainCondition(t,d)},r=o=>{this._patchChainCondition(t,ve(o))};return a`
|
||
<label class="block">
|
||
Family
|
||
<select @change=${o=>n(o.target.value)}>
|
||
<option value="zone" ?selected=${e.family==="zone"}>Zone state</option>
|
||
<option value="unit" ?selected=${e.family==="unit"}>Unit state</option>
|
||
<option value="sec" ?selected=${e.family==="sec"}>Area in security mode</option>
|
||
<option value="time" ?selected=${e.family==="time"}>Time clock</option>
|
||
<option value="misc" ?selected=${e.family==="misc"}>Misc</option>
|
||
</select>
|
||
</label>
|
||
${this._renderChainCondSubfields(e,r)}
|
||
`}_renderChainCondSubfields(e,t){if(e.family==="zone"){let n=this._bucketWithPreserve(this._objects?.zones??null,"zone",e.index??0);return a`
|
||
<label class="block">
|
||
Zone
|
||
<select @change=${r=>t({...e,index:parseInt(r.target.value,10)})}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)} ?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${r=>t({...e,active:r.target.value==="1"})}>
|
||
<option value="0" ?selected=${!e.active}>secure</option>
|
||
<option value="1" ?selected=${e.active}>not ready</option>
|
||
</select>
|
||
</label>`}if(e.family==="unit"){let n=this._bucketWithPreserve(this._objects?.units??null,"unit",e.index??0);return a`
|
||
<label class="block">
|
||
Unit
|
||
<select @change=${r=>t({...e,index:parseInt(r.target.value,10)})}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)} ?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${r=>t({...e,active:r.target.value==="1"})}>
|
||
<option value="1" ?selected=${e.active}>ON</option>
|
||
<option value="0" ?selected=${!e.active}>OFF</option>
|
||
</select>
|
||
</label>`}if(e.family==="sec"){let n=this._bucketWithPreserve(this._objects?.areas??null,"area",e.index??0);return a`
|
||
<label class="block">
|
||
Area
|
||
<select @change=${r=>t({...e,index:parseInt(r.target.value,10)})}>
|
||
${n.map(r=>a`
|
||
<option .value=${String(r.index)} ?selected=${r.index===e.index}>
|
||
#${r.index} ${r.name}
|
||
</option>`)}
|
||
</select>
|
||
</label>
|
||
<label class="block">
|
||
Mode
|
||
<select @change=${r=>t({...e,mode:parseInt(r.target.value,10)})}>
|
||
${ge.map(r=>a`
|
||
<option .value=${String(r.value)} ?selected=${r.value===e.mode}>
|
||
${r.label}
|
||
</option>`)}
|
||
</select>
|
||
</label>`}return e.family==="time"?a`
|
||
<label class="block">
|
||
Time clock # (1..3)
|
||
<input type="number" min="1" max="3"
|
||
.value=${String(e.index??1)}
|
||
@input=${n=>{let r=parseInt(n.target.value,10);Number.isFinite(r)&&t({...e,index:r})}}
|
||
/>
|
||
</label>
|
||
<label class="block">
|
||
Is
|
||
<select @change=${n=>t({...e,active:n.target.value==="1"})}>
|
||
<option value="1" ?selected=${e.active}>enabled</option>
|
||
<option value="0" ?selected=${!e.active}>disabled</option>
|
||
</select>
|
||
</label>`:a`
|
||
<label class="block">
|
||
Condition
|
||
<select @change=${n=>t({family:"misc",misc:parseInt(n.target.value,10)})}>
|
||
${fe.map(n=>a`
|
||
<option .value=${String(n.value)} ?selected=${n.value===e.misc}>
|
||
${n.label}
|
||
</option>`)}
|
||
</select>
|
||
</label>`}_renderChainActionsSection(e){return a`
|
||
<fieldset>
|
||
<legend>
|
||
Actions (${e.length})
|
||
<button type="button" class="mini-btn"
|
||
@click=${()=>this._addChainAction()}>+ THEN</button>
|
||
</legend>
|
||
${e.map((t,n)=>this._renderChainActionRow(t,n,e.length))}
|
||
</fieldset>
|
||
`}_renderChainActionRow(e,t,n){let r=H(e.cmd??0),o=r?.ref_kind?this._bucketWithPreserve(this._pickBucket(r.ref_kind),r.ref_kind,e.pr2??0):null,c=e.cmd===9;return a`
|
||
<div class="cond-slot">
|
||
<div class="cond-row-header">
|
||
<strong>${t===0?"THEN":"AND"}</strong>
|
||
${n>1?a`
|
||
<button type="button" class="mini-btn danger"
|
||
@click=${()=>this._removeChainAction(t)}>×</button>`:""}
|
||
</div>
|
||
<label class="block">
|
||
Command
|
||
<select @change=${l=>{let u=parseInt(l.target.value,10),p=H(u),d=e.pr2??0;if(p?.ref_kind&&this._objects){let b=this._pickBucket(p.ref_kind);b&&b.length>0&&!b.some(_=>_.index===d)&&(d=b[0].index)}else p?.ref_kind||(d=0);this._patchChainAction(t,{cmd:u,pr2:d})}}>
|
||
${G.map(l=>a`
|
||
<option .value=${String(l.value)} ?selected=${l.value===e.cmd}>
|
||
${l.label}
|
||
</option>`)}
|
||
</select>
|
||
</label>
|
||
${r?.ref_kind?a`
|
||
<label class="block">
|
||
${r.ref_kind[0].toUpperCase()+r.ref_kind.slice(1)}
|
||
<select @change=${l=>{let u=parseInt(l.target.value,10);Number.isFinite(u)&&this._patchChainAction(t,{pr2:u})}}>
|
||
${(o??[]).map(l=>a`
|
||
<option .value=${String(l.index)} ?selected=${l.index===e.pr2}>
|
||
#${l.index} ${l.name}
|
||
</option>`)}
|
||
</select>
|
||
</label>`:""}
|
||
${c?a`
|
||
<label class="block">
|
||
Level (0..100)
|
||
<input type="number" min="0" max="100"
|
||
.value=${String(e.par??0)}
|
||
@input=${l=>{let u=parseInt(l.target.value,10);Number.isFinite(u)&&u>=0&&u<=100&&this._patchChainAction(t,{par:u})}}
|
||
/>
|
||
</label>`:""}
|
||
</div>
|
||
`}};h.styles=J`
|
||
: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);
|
||
}
|
||
.cond-slot {
|
||
padding: 8px 10px;
|
||
margin-top: 6px;
|
||
background: var(--secondary-background-color, #f5f5f5);
|
||
border-radius: 4px;
|
||
}
|
||
.cond-slot:first-of-type { margin-top: 0; }
|
||
.cond-family-label {
|
||
font-weight: 600;
|
||
color: var(--primary-text-color, #000);
|
||
}
|
||
.cond-row-header {
|
||
display: flex; justify-content: space-between; align-items: center;
|
||
margin-bottom: 4px;
|
||
}
|
||
.mini-btn {
|
||
border: 1px solid var(--divider-color, #ccc);
|
||
background: var(--card-background-color, #fff);
|
||
color: inherit;
|
||
padding: 2px 8px;
|
||
border-radius: 3px;
|
||
font-size: 0.78rem;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
margin-left: 6px;
|
||
}
|
||
.mini-btn:hover { background: var(--secondary-background-color, #eee); }
|
||
.mini-btn.danger {
|
||
color: var(--error-color, #db4437);
|
||
border-color: var(--error-color, #db4437);
|
||
}
|
||
.structured-cond {
|
||
background: rgba(255, 152, 0, 0.08); /* subtle warning tint */
|
||
}
|
||
.chain-meta {
|
||
margin-top: 8px;
|
||
padding: 8px 10px;
|
||
font-size: 0.82rem;
|
||
color: var(--secondary-text-color, #666);
|
||
background: var(--secondary-background-color, #f5f5f5);
|
||
border-radius: 4px;
|
||
}
|
||
`,m([N({attribute:!1})],h.prototype,"hass",2),m([N({attribute:!1})],h.prototype,"narrow",2),m([f()],h.prototype,"_entryId",2),m([f()],h.prototype,"_rows",2),m([f()],h.prototype,"_total",2),m([f()],h.prototype,"_filteredTotal",2),m([f()],h.prototype,"_loading",2),m([f()],h.prototype,"_error",2),m([f()],h.prototype,"_activeTriggerTypes",2),m([f()],h.prototype,"_referenceFilter",2),m([f()],h.prototype,"_searchTerm",2),m([f()],h.prototype,"_selectedSlot",2),m([f()],h.prototype,"_detail",2),m([f()],h.prototype,"_detailLoading",2),m([f()],h.prototype,"_fireFeedback",2),m([f()],h.prototype,"_writeFeedback",2),m([f()],h.prototype,"_cloneTargetSlot",2),m([f()],h.prototype,"_showCloneInput",2),m([f()],h.prototype,"_confirmingClear",2),m([f()],h.prototype,"_editingDraft",2),m([f()],h.prototype,"_objects",2),m([f()],h.prototype,"_chainDraft",2),h=m([Oe("omni-panel-programs")],h);export{h 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
|
||
*)
|
||
*/
|