@panphora/clayjs 1.11.0 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clay.standalone.js +1802 -1454
- package/entries/sap.js +6 -6
- package/package.json +2 -1
- package/src/attrs/save-freeze.js +6 -3
- package/src/core/persist.js +11 -1
- package/src/core/save.js +63 -8
- package/src/core/snapshot.js +8 -16
- package/src/core/source-map.js +61 -19
- package/src/lib/content-dom.js +58 -28
- package/src/lib/ephemeral.js +88 -0
- package/src/lib/extension-noise.js +11 -4
- package/src/lib/mutation.js +4 -1
- package/src/lib/root-attrs.js +24 -1
- package/src/loader.js +2 -0
- package/src/plugins/undo.js +17 -2
- package/src/sync/live-sync.js +8 -6
- package/src/tailwind.js +12 -0
- package/src/vendor/hyper-morph.vendor.js +3 -3
package/entries/sap.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// GENERATED — do not edit. Vendored from sapjs/dist/sap.min.js via sapjs
|
|
2
2
|
// `npm run copy-to-clayjs`. Edit the sapjs source and re-run.
|
|
3
3
|
(function () {
|
|
4
|
-
var Sap=(()=>{var
|
|
5
|
-
|
|
4
|
+
var Sap=(()=>{var Yt=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Je=Object.getOwnPropertyNames;var Qe=Object.prototype.hasOwnProperty;var Ze=(t,e)=>{for(var n in e)Yt(t,n,{get:e[n],enumerable:!0})},tr=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Je(e))!Qe.call(t,i)&&i!==n&&Yt(t,i,{get:()=>e[i],enumerable:!(r=Ke(e,i))||r.enumerable});return t};var er=t=>tr(Yt({},"__esModule",{value:!0}),t);var nn={};Ze(nn,{Sap:()=>F,default:()=>rn,mount:()=>Xe,mountAll:()=>Ut,runtime:()=>dt});function ue(t){let e=!1,n=new Set,r=[];function i(f){f&&(r.push(f),r.length>8&&r.shift())}function s(f,w){i(w),!f._broken&&(n.add(f),!e&&(e=!0,queueMicrotask(a)))}function a(){e=!1;let f=[...n];n.clear();for(let w of f)R(w)}function R(f){if(!f._broken){if(f._passes=(f._passes||0)+1,f._passes>50){f._broken=!0,f._breakerRing=r.slice(),t(f,{breaker:!0});return}f._resetArmed||(f._resetArmed=!0,setTimeout(()=>{f._passes=0,f._resetArmed=!1},0)),t(f)}}function k(f,w){i(w),R(f)}function A(f){f._broken=!1,f._passes=0}return{schedule:s,runNow:k,rearm:A,ring:r}}var Xt={E01:{slug:"foreign-dialect",behavior:"HALT"},E02:{slug:"moustaches-in-text",behavior:"HALT"},E04:{slug:"duplicate-declaration",behavior:"HALT"},E05:{slug:"reserved-name",behavior:"HALT"},E06:{slug:"global-html-name",behavior:"HALT"},E07:{slug:"calc-cycle",behavior:"ERR"},E08:{slug:"expression-syntax",behavior:"HALT"},E10:{slug:"orphan-item",behavior:"HALT"},E12:{slug:"unknown-state-key",behavior:"ERR"},E15:{slug:"write-to-undeclared-key",behavior:"ERR"},E16:{slug:"write-to-computed-field",behavior:"ERR"},E17:{slug:"unresolvable-action-target",behavior:"HALT"},E18:{slug:"paint-on-form-control",behavior:"HALT"},E20:{slug:"bind-on-non-control",behavior:"HALT"},E22:{slug:"format-type",behavior:"ERR"},E24:{slug:"runtime-expression-throw",behavior:"ERR"},E26:{slug:"circuit-breaker",behavior:"HALT"},E30:{slug:"attr-on-bound-control",behavior:"HALT"},E31:{slug:"password-without-transient",behavior:"HALT"},E32:{slug:"file-bind",behavior:"HALT"},E33:{slug:"dialog-state-open",behavior:"HALT"},E34:{slug:"transient-persist-collision",behavior:"HALT"},E35:{slug:"presence-state-misuse",behavior:"HALT"},E40:{slug:"each-not-array",behavior:"ERR"},E41:{slug:"each-bad-key",behavior:"ERR"},E42:{slug:"each-template",behavior:"ERR"},E43:{slug:"bind-in-each-row",behavior:"ERR"},W03:{slug:"unknown-colon-attribute",behavior:"WARN"},W04:{slug:"expression-in-when",behavior:"WARN"},W30:{slug:"nonzero-mount-writes",behavior:"WARN"},W31:{slug:"detail-dialog-saved-open",behavior:"WARN"}},mt=["disabled","readonly","required","checked","selected","multiple","open","inert","autofocus","novalidate","hidden"],St=new Set(["title","style","hidden","lang","dir","translate","class","id","nonce","autofocus","tabindex","contenteditable","spellcheck","draggable","role","slot","part","name","value","type","itemscope","itemtype","itemid","itemprop","itemref"]),Rt=new Set(["sap","scope","items","item","template","bind","calc","text","show","attr","set","trigger","move","sort","detail","each","effect","invalid","confirm","transient","default","persist","sortable","editmode"]);function Dt(t){if(!t||t.nodeType!==1)return"?";if(t.id)return`${t.tagName.toLowerCase()}#${t.id}`;let e=[],n=t,r=0;for(;n&&n.nodeType===1&&r<4;){let i=n.tagName.toLowerCase();if(n.hasAttribute("sap"))i+="[sap]";else if(n.parentElement){let s=[...n.parentElement.children].filter(a=>a.tagName===n.tagName);s.length>1&&(i+=`:nth-of-type(${s.indexOf(n)+1})`)}if(e.unshift(i),n.hasAttribute("sap"))break;n=n.parentElement,r++}return e.join(" > ")}function ce(t){let e=t.toLowerCase();return/^x-text$|^x-html$/.test(e)?'use text="state.x" (Sap paints text only)':/^x-show$|^v-show$|^v-if$/.test(e)?'use show="expr" (toggles native hidden)':/^x-model$|^v-model$/.test(e)?'use bind="field"':/^@|^x-on:|^v-on:|^on:/.test(e)?"use native onclick + Sap(this) (no event directive)":/^:|^x-bind:class$|^v-bind:class$/.test(e)?'use class:NAME="expr" or attr:NAME="expr"':/^x-for$|^v-for$/.test(e)?'use items="name" on the container and item template on the row':/^x-data$/.test(e)?"declare state with state= / bind / items (no JS state object)":/^x-init$/.test(e)?"use a <script> or onclick + Sap(this)":/^bind:/.test(e)?'use bind="field"; one-way paint is attr:NAME="expr"':/^x-/.test(e)||/^v-/.test(e)?"this is a foreign-dialect attribute; Sap has no x-/v- attributes":null}var pt=class{constructor(e){this.appName=e,this.errors=[],this.warnings=[],this.halted=!1,this.haltReason=null}block(e,n,r={}){let i=(Xt[e]||{}).slug||"error",s={code:e,slug:i,el:Dt(n),attr:r.attr||null,expr:r.expr||null,key:r.key||null,problem:r.problem||"",didYouMean:r.didYouMean||null,fix:r.fix||null,phase:r.phase||"runtime"},a=[`
|
|
5
|
+
`+(e[0]==="W"?"sap \u26A0 ":"sap \u2717 ")+e+" "+i];return a.push(` at ${s.el}${s.attr?` \u2014 ${s.attr}="${s.expr??""}"`:""}`),s.problem&&a.push(` problem: ${s.problem}`),s.didYouMean&&a.push(` did you mean: ${s.didYouMean}`),s.fix&&a.push(` fix: ${s.fix}`),console.error(a.join(`
|
|
6
|
+
`)),s}error(e,n,r={}){let i=this.block(e,n,r);return this.errors.push(i),i}warn(e,n,r={}){let i=this.block(e,n,r);return this.warnings.push(i),i}report(){return{ok:this.errors.length===0&&!this.halted,app:this.appName,halted:this.halted,haltReason:this.haltReason,errors:this.errors.slice(),warnings:this.warnings.slice()}}};function ut(t,e){t&&t.getAttribute("sap-error")!==e&&t.setAttribute("sap-error",e)}function Ct(t){t&&t.hasAttribute("sap-error")&&t.removeAttribute("sap-error")}function xt(t,e){let n=null,r=3;for(let i of e){let s=rr(t,i);s<r&&(r=s,n=i)}return n}function rr(t,e){let n=t.length,r=e.length,i=Array.from({length:n+1},(s,a)=>[a,...new Array(r).fill(0)]);for(let s=0;s<=r;s++)i[0][s]=s;for(let s=1;s<=n;s++)for(let a=1;a<=r;a++)i[s][a]=Math.min(i[s-1][a]+1,i[s][a-1]+1,i[s-1][a-1]+(t[s-1]===e[a-1]?0:1));return i[n][r]}var nr=new Set(mt),or={readonly:"readOnly",novalidate:"noValidate"},ir=0,fe=new WeakMap;function Mt(t,e="sap"){let n=t.getAttribute("data-id");if(n)return n;if(t.id)return t.id;let r=fe.get(t);return r||(r=`${e}-${(ir++).toString(36)}`,fe.set(t,r)),r}function le(t,e="row"){for(;;){let n=`${e}-${Math.random().toString(36).slice(2,8)}`;if(!t.getElementById(n)&&!t.querySelector(`[data-id="${n}"]`))return n}}function sr(t){return t.hasAttribute("scope")||t.hasAttribute("items")||t.hasAttribute("detail")||t.hasAttribute("each")}function ar(t){return t.tagName==="TEMPLATE"||t.hasAttribute("sap-ignore")||t.hasAttribute("template")}function K(t,e){for(let r of t.children)n(r);function n(r){if(r.nodeType!==1||ar(r))return;let i=sr(r);if(e(r,i),!i)for(let s of r.children)n(s)}}function Y(t){let e=t;for(;e;){if(e.hasAttribute("sap")||e.hasAttribute("scope")||e.hasAttribute("item")||e.hasAttribute("detail"))return e;e=e.parentElement}return null}function ft(t){for(let e=t;e&&e.nodeType===1;e=e.parentElement){if(e._sapEachRow)return e;if(e.hasAttribute("item")||e.hasAttribute("sap"))return null}return null}function It(t){let e=t;for(;e;){if(e.hasAttribute("detail")||e.hasAttribute("item"))return e;e=e.parentElement}return null}function kt(t){let e=t;for(;e;){if(e.hasAttribute("detail"))return e;e=e.parentElement}return null}function lt(t,e){if(t.hasAttribute("item")&&t.getAttribute("bind")===e)return t;let n=null;return K(t,r=>{!n&&r.getAttribute("bind")===e&&(n=r)}),n}function ht(t,e){let n=null;return K(t,r=>{!n&&r.getAttribute("items")===e&&(n=r)}),n}function bt(t,e){return!t||t.nodeType!==1||!t.hasAttribute("item")?!1:lt(t,e)||ht(t,e)?!0:z(t.getAttribute("state")||"").some(n=>n.name===e)}function de(t){let e=t&&t.$el;return e&&e.nodeType===1&&e.isConnected&&e.hasAttribute("item")?e:null}function Ot(t){return!!t.closest("form[trigger-add]")}function Z(t){return[...t.children].filter(e=>e.hasAttribute("item")&&!e.hasAttribute("template"))}function Kt(t,e){if(!t||!e)return null;let n=[...t.querySelectorAll(`template[items="${e}"]`)].find(i=>i.closest("[sap]")===t),r=n&&n.content.firstElementChild;return r&&r.hasAttribute("item")?r:null}function Ft(t){let e=[...t.children].find(n=>n.hasAttribute("item")&&n.hasAttribute("template"));return e||Kt(t.closest("[sap]"),t.getAttribute("items"))}function z(t){let e=[];if(!t)return e;for(let n of t.trim().split(/\s+/)){if(!n)continue;let r=n,i,s=r.indexOf("=");s>=0&&(i=r.slice(s+1),r=r.slice(0,s));let a=r.split(":"),R=a[0],k="string",A=!1;for(let N of a.slice(1))N==="num"?k="num":N==="bool"?k="bool":N==="presence"?k="presence":N==="transient"&&(A=!0);let f=R,w=f.startsWith("data-")&&f.length>5?f.slice(5).replace(/-([a-z])/g,(N,I)=>I.toUpperCase()):f;e.push({name:w,attr:f,type:k,default:i,transient:A})}return e}function ct(t,e){if(e==="num"){if(t==null||t==="")return 0;let n=Number(t);return Number.isNaN(n)?0:n}return e==="bool"?t==="true"||t===""||t==="1":t??""}function Jt(t,e){return e==="bool"?t?"true":"false":t==null?"":String(t)}function Qt(t,e){return nr.has(e)&&typeof t[or[e]||e]=="boolean"}function gt(t,e){return e.type==="presence"||e.type!=="num"&&Qt(t,e.attr||e.name)}function $t(t){return t.default!=null?t.default:t.type==="num"?"0":t.type==="bool"?"false":""}function pe(t,e){let n=e.attr||e.name;if(gt(t,e))return t.hasAttribute(n);let r=t.getAttribute(n);return ct(r??$t(e),e.type)}function me(t,e){return gt(t,e)?e.default!=null?ct(e.default,"bool"):!1:ct($t(e),e.type)}function _t(t,e,n){let r=e.attr||e.name;if(gt(t,e)){n?t.hasAttribute(r)||t.setAttribute(r,""):t.hasAttribute(r)&&t.removeAttribute(r);return}t.setAttribute(r,Jt(n,e.type))}function Pt(t,e){let n=e.attr||e.name,r=t._sapTransient||(t._sapTransient={});if(!(e.name in r)){let i=t.getAttribute(n);i==null&&(i=$t(e)),r[e.name]=ct(i,e.type)}return t.hasAttribute(n)&&t.removeAttribute(n),r[e.name]}function Tt(t,e,n){let r=e.attr||e.name;(t._sapTransient||(t._sapTransient={}))[e.name]=n,t.hasAttribute(r)&&t.removeAttribute(r)}function Nt(t,e,n){let r=String(n).split("."),i=r[r.length-1];if(r.length===1){let R=ur(e,i);return R||(t.getAttribute("items")===i?t:t.querySelector(`[items="${i}"]:not(template)`))}let s=r[r.length-2],a=[...t.querySelectorAll(`[scope="${s}"]`)].find(R=>ht(R,i));return a?ht(a,i):null}function ur(t,e){let n=Y(t);for(;n;){if(n.getAttribute("items")===e)return n;let r=ht(n,e);if(r)return r;n=Y(n.parentElement)}return null}function tt(t){if(typeof t=="number")return t;if(t==null||t==="")return 0;let e=Number(typeof t=="string"?t.replace(/[$,%\s]/g,""):t);return Number.isNaN(e)?0:e}function Wt(t,e){return Array.isArray(t)?e==null?t:t.map(n=>typeof e=="function"?e(n):n?.[e]):[]}function he(t,e){return Wt(t,e).reduce((n,r)=>n+tt(r),0)}function cr(t,e){return Array.isArray(t)?e==null?t.length:t.reduce((n,r)=>n+(e(r)?1:0),0):0}function fr(t,e){let n=Wt(t,e);return n.length?he(t,e)/n.length:0}function lr(t,e){let n=Wt(t,e).filter(r=>r!=null&&r!=="");return n.length?n.every(r=>typeof r=="number"||!Number.isNaN(Number(r)))?Math.min(...n.map(Number)):n.reduce((r,i)=>String(r)<=String(i)?r:i):0}function dr(t,e){let n=Wt(t,e).filter(r=>r!=null&&r!=="");return n.length?n.every(r=>typeof r=="number"||!Number.isNaN(Number(r)))?Math.max(...n.map(Number)):n.reduce((r,i)=>String(r)>=String(i)?r:i):0}function pr(t,e,n){let r=tt(t)===1?e:n??e+"s";return`${t} ${r}`}function mr(t,e){let n=new Date(t),r=new Date(e);return Number.isNaN(+n)||Number.isNaN(+r)?0:Math.round((r-n)/864e5)}function nt(t){return typeof t=="number"?t:Number(t)}var Lt={usd:t=>"$"+nt(t).toLocaleString("en-US",{maximumFractionDigits:0}),usd2:t=>"$"+nt(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),pct:t=>Math.round(nt(t))+"%",pct1:t=>nt(t).toFixed(1)+"%",int:t=>Math.round(nt(t)).toLocaleString("en-US"),num:t=>nt(t).toLocaleString("en-US"),num2:t=>nt(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),compact:t=>nt(t).toLocaleString("en-US",{notation:"compact"}),date:t=>{let e=new Date(t);return Number.isNaN(+e)?String(t):e.toLocaleDateString("en-US")},clock:t=>{let e=nt(t),n=Math.floor(e/100),r=n%10,i=Math.floor(n/10)%60;return`${Math.floor(n/600)}:${String(i).padStart(2,"0")}.${r}`}},hr=new Set(["usd","usd2","pct","pct1","int","num","num2","compact","clock"]);function be(t,e){if(!t)return e==null?"":String(e);let n=Lt[t];if(typeof n!="function"){let r=new Error(`unknown format "${t}"`);throw r.sapCode="E22",r}if(hr.has(t)){let r=typeof e=="number"?e:Number(e);if(!Number.isFinite(r)){let i=new Error(`format "${t}" received ${typeof e=="string"?`"${e}"`:e}`);throw i.sapCode="E22",i}}return n(e)}function ge(){return[Lt,tt,he,cr,fr,lr,dr,pr,mr]}var br=["state","item","el","root","fmt","num","sum","count","avg","min","max","plural","days"],Bt=new Map,we=/\bstate\.([a-z][a-z0-9_]*)/g,ye=/\bitem\.([a-z][a-z0-9_]*)/g;function gr(t){let e=new Set,n=new Set,r;for(we.lastIndex=0;r=we.exec(t);)e.add(r[1]);for(ye.lastIndex=0;r=ye.exec(t);)n.add(r[1]);return{state:e,item:n}}function H(t,e=!1){let n=(e?"!":"")+t,r=Bt.get(n);if(r)return r;Bt.size>512&&Bt.clear();try{let i=e?`"use strict";
|
|
7
|
+
${t}`:`"use strict"; return (${t});`;r={fn:new Function(...br,i),src:t,statement:e,deps:gr(t),error:null}}catch(i){r={fn:null,src:t,statement:e,deps:{state:new Set,item:new Set},error:i}}return Bt.set(n,r),r}function J(t,e){if(t.error)throw t.error;return t.fn(e.state,e.item,e.el??null,e.root,...ge())}function Ae(t){let e=new Map;for(let a of t)e.set(a.name,a);let n=[],r=new Map,i=[];function s(a){let R=r.get(a.name);if(R!==1){if(R===0){let k=[...i.slice(i.indexOf(a.name)),a.name].join(" -> "),A=new Error(`calc: cycle: ${k}`);throw A.sapCode="E07",A.cycle=k,A}r.set(a.name,0),i.push(a.name);for(let k of a.entry.deps.state){let A=e.get(k);A&&A!==a&&s(A)}for(let k of a.entry.deps.item){let A=e.get(k);A&&A!==a&&s(A)}i.pop(),r.set(a.name,1),n.push(a)}}for(let a of t)s(a);return n}function Ee(t){return(t.getAttribute("type")||"text").toLowerCase()}function wt(t){let e=t.tagName;if(e==="INPUT"){let n=Ee(t);n==="checkbox"||n==="radio"?t.checked?t.setAttribute("checked",""):t.removeAttribute("checked"):t.setAttribute("value",t.value);return}if(e==="TEXTAREA"){t.setAttribute("data-value",t.value);return}if(e==="SELECT"){let n=t.options;for(let r=0;r<n.length;r++)n[r].selected?n[r].setAttribute("selected",""):n[r].removeAttribute("selected")}}function ve(t,e=t){let n=t.tagName;if(n==="INPUT"){let r=Ee(t);r==="checkbox"||r==="radio"?e.checked?t.hasAttribute("checked")||t.setAttribute("checked",""):t.removeAttribute("checked"):e.value!==(t.getAttribute("value")??"")&&t.setAttribute("value",e.value);return}if(n==="TEXTAREA"){let r=e.value.startsWith(`
|
|
6
8
|
`)?`
|
|
7
|
-
`+e.value:e.value;t.textContent!==r&&(t.textContent=r),t.removeAttribute("data-value");return}if(n==="SELECT"){let r=t.options,o=e.options;for(let a=0;a<r.length;a++)o[a]&&o[a].selected?r[a].hasAttribute("selected")||r[a].setAttribute("selected",""):r[a].removeAttribute("selected")}}function Ct(t){t.tagName!=="TEXTAREA"||!t.hasAttribute("data-value")||t!==t.ownerDocument.activeElement&&(t.textContent=t.getAttribute("data-value"),t.removeAttribute("data-value"))}function j(t){if(typeof window>"u")return null;let e=window.clay,n=window.hyperclay;return t==="consent"?e?.confirm||n?.consent||null:e?.[t]||n?.[t]||null}var Ut=["clay:mutation-ready","hyperclay:mutation-ready"],nr=["clay:sync-applied","hyperclay:livesync-applied"],or=["clay:ready","hyperclay:ready"];function vt(t,e,n){let r=null,o=a=>{r!==null&&r!==a.type||(r=a.type,queueMicrotask(()=>{r=null}),n(a))};for(let a of e)t.addEventListener(a,o);return()=>{for(let a of e)t.removeEventListener(a,o)}}function le(t){let e=typeof window<"u"&&window.clay&&window.clay.ready;e&&typeof e.then=="function"?e.then(()=>t(),()=>t()):t()}function Mt(t){let e=j("region");return!e||typeof e.resolveRegionPolicy!="function"||typeof e.skipForPolicy!="function"?!1:e.skipForPolicy(e.resolveRegionPolicy(t),void 0,["no-save","freeze"])}function de(){let t=j("consent");return typeof t=="function"?t:null}function pe(t,e){if(typeof e!="function")throw new Error("Sap.batch(label, fn): fn must be a function");let n=j("undo");n&&n.flush&&n.flush();let r=e();if(r&&typeof r.then=="function")throw new Error("Sap.batch fn must be synchronous (it returned a promise)");return n&&n.commitCaptured&&n.commitCaptured(t),r}function me(t){if(typeof window>"u"||typeof document>"u")return;let e=()=>{let a=!1;for(let u of t.apps())u.root.isConnected?t.runNow(u,"platform"):a=!0;a&&(t.pruneDisconnected(),t.remountIfPresent())};vt(document,nr,e);let n=!1,r=()=>{},o=()=>{if(n)return!0;let a=j("undo");if(!a||typeof a.on!="function")return!1;let u=a.on("undo",e);return typeof u!="function"?!1:typeof a.on("redo",e)!="function"?(u(),!1):(n=!0,r(),!0)};if(!o()){let a=vt(document,Ut,o),u=vt(document,or,o);r=()=>{a(),u()};let R=j("ready");R&&typeof R.then=="function"&&R.then(o,()=>{})}}function sr(t){let e=t.tagName;if(e==="INPUT"){let n=(t.getAttribute("type")||"text").toLowerCase();return n==="checkbox"?"checkbox":n==="radio"?"radio":n==="number"||n==="range"?"number":n==="hidden"?"hidden":"text"}return e==="TEXTAREA"?"text":e==="SELECT"?t.multiple?"select-multiple":"select-one":"leaf"}function ir(t){if(t.validity&&t.validity.badInput)return t.hasAttribute("value")?Number(t.getAttribute("value"))||0:t._sapLastGood??0;if(t.value==="")return 0;let e=Number(t.value);return Number.isNaN(e)?t._sapLastGood??0:(t._sapLastGood=e,e)}function ar(t,e){switch(e){case"checkbox":return t.checked;case"radio":return t.checked?t.value:void 0;case"number":return ir(t);case"select-one":return t.value;case"select-multiple":return[...t.selectedOptions].map(n=>n.value);case"hidden":case"text":return t.value;case"leaf":return t.textContent;default:return t.value}}function ur(t,e,n){switch(e){case"checkbox":t.checked=!!n;break;case"radio":t.checked=String(t.value)===String(n);break;case"number":case"text":case"hidden":t.value=n==null?"":String(n);break;case"select-one":t.value=n==null?"":String(n);break;case"select-multiple":{let r=new Set((Array.isArray(n)?n:[n]).map(String));for(let o of t.options)o.selected=r.has(o.value);break}case"leaf":t.textContent=n==null?"":String(n);break;default:t.value=n==null?"":String(n)}}function he(t){if(t.hasAttribute("transient")){t.removeAttribute("value"),t.removeAttribute("checked"),t.removeAttribute("data-value");return}Mt(t)||lt(t)}function cr(t){t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function F(t){let e=sr(t);return{el:t,kind:e,read(){return ar(t,e)},write(n,r={}){ur(t,e,n),r.noMirror||he(t),r.silent||cr(t)},mirror(){he(t)}}}var Vt={E01:{slug:"foreign-dialect",behavior:"HALT"},E02:{slug:"moustaches-in-text",behavior:"HALT"},E04:{slug:"duplicate-declaration",behavior:"HALT"},E05:{slug:"reserved-name",behavior:"HALT"},E06:{slug:"global-html-name",behavior:"HALT"},E07:{slug:"calc-cycle",behavior:"ERR"},E08:{slug:"expression-syntax",behavior:"HALT"},E10:{slug:"orphan-item",behavior:"HALT"},E12:{slug:"unknown-state-key",behavior:"ERR"},E15:{slug:"write-to-undeclared-key",behavior:"ERR"},E16:{slug:"write-to-computed-field",behavior:"ERR"},E17:{slug:"unresolvable-action-target",behavior:"HALT"},E18:{slug:"paint-on-form-control",behavior:"HALT"},E20:{slug:"bind-on-non-control",behavior:"HALT"},E22:{slug:"format-type",behavior:"ERR"},E24:{slug:"runtime-expression-throw",behavior:"ERR"},E26:{slug:"circuit-breaker",behavior:"HALT"},E30:{slug:"attr-on-bound-control",behavior:"HALT"},E31:{slug:"password-without-transient",behavior:"HALT"},E32:{slug:"file-bind",behavior:"HALT"},E33:{slug:"dialog-state-open",behavior:"HALT"},E34:{slug:"transient-persist-collision",behavior:"HALT"},E40:{slug:"each-not-array",behavior:"ERR"},E41:{slug:"each-bad-key",behavior:"ERR"},E42:{slug:"each-template",behavior:"ERR"},E43:{slug:"bind-in-each-row",behavior:"ERR"},W03:{slug:"unknown-colon-attribute",behavior:"WARN"},W04:{slug:"expression-in-when",behavior:"WARN"},W30:{slug:"nonzero-mount-writes",behavior:"WARN"}},Dt=["disabled","readonly","required","checked","selected","multiple","open","inert","autofocus","novalidate","hidden"],Et=new Set(["title","style","hidden","lang","dir","translate","class","id","nonce","autofocus","tabindex","contenteditable","spellcheck","draggable","role","slot","part","name","value","type","itemscope","itemtype","itemid","itemprop","itemref"]),It=new Set(["sap","scope","items","item","template","bind","calc","text","show","attr","set","trigger","move","sort","detail","each","effect","invalid","confirm","transient","default","persist","sortable","editmode"]);function Wt(t){if(!t||t.nodeType!==1)return"?";if(t.id)return`${t.tagName.toLowerCase()}#${t.id}`;let e=[],n=t,r=0;for(;n&&n.nodeType===1&&r<4;){let o=n.tagName.toLowerCase();if(n.hasAttribute("sap"))o+="[sap]";else if(n.parentElement){let a=[...n.parentElement.children].filter(u=>u.tagName===n.tagName);a.length>1&&(o+=`:nth-of-type(${a.indexOf(n)+1})`)}if(e.unshift(o),n.hasAttribute("sap"))break;n=n.parentElement,r++}return e.join(" > ")}function be(t){let e=t.toLowerCase();return/^x-text$|^x-html$/.test(e)?'use text="state.x" (Sap paints text only)':/^x-show$|^v-show$|^v-if$/.test(e)?'use show="expr" (toggles native hidden)':/^x-model$|^v-model$/.test(e)?'use bind="field"':/^@|^x-on:|^v-on:|^on:/.test(e)?"use native onclick + Sap(this) (no event directive)":/^:|^x-bind:class$|^v-bind:class$/.test(e)?'use class:NAME="expr" or attr:NAME="expr"':/^x-for$|^v-for$/.test(e)?'use items="name" on the container and item template on the row':/^x-data$/.test(e)?"declare state with state= / bind / items (no JS state object)":/^x-init$/.test(e)?"use a <script> or onclick + Sap(this)":/^bind:/.test(e)?'use bind="field"; one-way paint is attr:NAME="expr"':/^x-/.test(e)||/^v-/.test(e)?"this is a foreign-dialect attribute; Sap has no x-/v- attributes":null}var dt=class{constructor(e){this.appName=e,this.errors=[],this.warnings=[],this.halted=!1,this.haltReason=null}block(e,n,r={}){let o=(Vt[e]||{}).slug||"error",a={code:e,slug:o,el:Wt(n),attr:r.attr||null,expr:r.expr||null,key:r.key||null,problem:r.problem||"",didYouMean:r.didYouMean||null,fix:r.fix||null,phase:r.phase||"runtime"},u=[`
|
|
8
|
-
|
|
9
|
-
`)),a}error(e,n,r={}){let o=this.block(e,n,r);return this.errors.push(o),o}warn(e,n,r={}){let o=this.block(e,n,r);return this.warnings.push(o),o}report(){return{ok:this.errors.length===0&&!this.halted,app:this.appName,halted:this.halted,haltReason:this.haltReason,errors:this.errors.slice(),warnings:this.warnings.slice()}}};function at(t,e){t&&t.getAttribute("sap-error")!==e&&t.setAttribute("sap-error",e)}function Ot(t){t&&t.hasAttribute("sap-error")&&t.removeAttribute("sap-error")}function St(t,e){let n=null,r=3;for(let o of e){let a=fr(t,o);a<r&&(r=a,n=o)}return n}function fr(t,e){let n=t.length,r=e.length,o=Array.from({length:n+1},(a,u)=>[u,...new Array(r).fill(0)]);for(let a=0;a<=r;a++)o[0][a]=a;for(let a=1;a<=n;a++)for(let u=1;u<=r;u++)o[a][u]=Math.min(o[a-1][u]+1,o[a][u-1]+1,o[a-1][u-1]+(t[a-1]===e[u-1]?0:1));return o[n][r]}var et=null,Ft=!1,pt=null;function ge(t){let e=null;return{kind:"hub",subscribe(n){let r=t.onAnyChange({debounce:0,require:"observed"},n);typeof r=="function"&&(e=r)},suppress(n){t.pause();try{return n()}finally{t.resume()}},teardown(){if(e){try{e()}catch{}e=null}}}}function lr(){let t=null;return{kind:"native",subscribe(e){t=new MutationObserver(r=>e(dr(r)));let n=typeof document<"u"&&document.body||typeof document<"u"&&document.documentElement;n&&t.observe(n,{childList:!0,subtree:!0,attributes:!0,characterData:!0})},suppress(e){let n=j("undo");n&&n.pause&&n.pause();try{return e()}finally{t&&t.takeRecords(),n&&n.resume&&n.resume()}},teardown(){t&&(t.disconnect(),t=null)}}}function dr(t){let e=[];for(let n of t)if(n.type==="attributes"){let r=n.target;r&&r.nodeType===1&&!Pt(r)&&e.push({type:"attribute",element:r})}else if(n.type==="characterData"){let r=n.target&&n.target.parentElement;r&&!Pt(r)&&e.push({type:"characterData",element:r})}else if(n.type==="childList"){for(let r of n.addedNodes)if(!(r.nodeType!==1||Pt(r))&&(e.push({type:"add",element:r}),r.querySelectorAll))for(let o of r.querySelectorAll("*"))Pt(o)||e.push({type:"add",element:o});for(let r of n.removedNodes)r.nodeType===1&&e.push({type:"remove",element:r,parent:n.target})}return e}function Pt(t){return!!(t.closest&&t.closest("[sap-ignore],[template]"))}function pr(t,e){t.pruneDisconnected();let n=new Set,r=!1;for(let o of e){let a=o.type==="remove"?o.parent:o.element,u=a&&t.appFor(a);u&&n.add(u),o.type==="add"&&o.element&&o.element.nodeType===1&&o.element.hasAttribute&&o.element.hasAttribute("sap")&&!(t.isRegistered&&t.isRegistered(o.element))&&(r=!0)}r&&t.remountIfPresent();for(let o of n)o.root.isConnected&&t.schedule(o,"mutation")}function we(t){if(et)return et.suppress(t);let e=j("undo");if(e&&e.pause&&e.resume){e.pause();try{return t()}finally{e.resume()}}return t()}function Yt(t,e){Ft=!0,et=t,t.subscribe(n=>pr(e,n))}function Gt(t){if(Ft||typeof window>"u"||typeof document>"u")return;let e=j("Mutation");if(e&&typeof e.onAnyChange=="function"){Yt(ge(e),t);return}typeof MutationObserver=="function"&&(Yt(lr(),t),pt=vt(document,Ut,function(){let r=j("Mutation");r&&(pt(),pt=null,et&&et.teardown(),Ft=!1,Yt(ge(r),t))}))}function ye(){if(et)try{et.teardown()}catch{}pt&&typeof document<"u"&&pt(),et=null,Ft=!1,pt=null}var Ee=new Set(Dt);function mt(t,e={}){if(e.breaker){t.diag.error("E26",t.root,{problem:"recompute loop halted after 50 passes; recent triggers: "+(t._breakerRing||[]).join(", ")}),at(t.root,"loop");return}we(()=>mr(t,e)),t._viewsChanged&&(t._viewsChanged=!1,t.root.dispatchEvent(new CustomEvent("sap:views-updated",{bubbles:!0})))}function mr(t,e){let n=t.root,r={},o=[],a=[],u=[],R=[],k=[],y=[],f=[],w=new Set;t.diag.errors=[];let N={root:r,state:r,item:null,ownerEl:n,projection:!1};function W(s,p){let h=p.attr||p.name,d=s.getAttribute(h);return d==null&&(d=p.default!=null?p.default:p.type==="num"?"0":p.type==="bool"?"false":"",k.push({el:s,name:p.name,attr:h,value:Nt(it(d,p.type),p.type)})),it(d,p.type)}function b(s,p){let h=q(s.getAttribute("state")||"");s._sapStateDecls=h;for(let d of h){if(d.type==="string"&&Ee.has(d.attr)&&typeof s[d.attr]=="boolean"){p[d.name]=s.hasAttribute(d.attr);continue}if(d.transient){p[d.name]=Tt(s,d);continue}p[d.name]=W(s,d)}}function g(s,p){if(!s.hasAttribute("bind"))return;let h=s.getAttribute("bind"),d=p.item||p.state,_=F(s);_.kind==="radio"?(h in d||(d[h]=""),s.checked&&(d[h]=s.value)):d[h]=_.read(),s.hasAttribute("transient")&&(s.removeAttribute("value"),s.removeAttribute("checked"))}function c(s,p){for(let h of s.attributes){let d=h.name,_=h.value;if(d.startsWith("calc:"))o.push({owner:p.item||p.state,ownerEl:p.ownerEl,name:d.slice(5),entry:P(_),el:s,ctx:p});else if(d==="text"||d.startsWith("text:"))a.push({el:s,kind:"text",fmt:d.includes(":")?d.slice(5):null,entry:P(_),ctx:p});else if(d==="show")a.push({el:s,kind:"show",entry:P(_),ctx:p});else if(d.startsWith("attr:"))a.push({el:s,kind:"attr",arg:d.slice(5),entry:P(_),ctx:p});else if(d.startsWith("class:"))a.push({el:s,kind:"class",arg:d.slice(6),entry:P(_),ctx:p});else if(d.startsWith("css:"))a.push({el:s,kind:"css",arg:d.slice(4),entry:P(_),ctx:p});else if(d==="effect")u.push({el:s,entry:P(_,!0),ctx:p});else if(d==="invalid")R.push({el:s,entry:P(_),ctx:p});else if(d.startsWith("show-when:")||d.startsWith("option:")){let D=d.slice(d.indexOf(":")+1);w.add(D),a.push({el:s,kind:"when",match:"show",field:D,values:_.split("|"),ctx:p})}else if(d.startsWith("hide-when:")){let D=d.slice(d.indexOf(":")+1);w.add(D),a.push({el:s,kind:"when",match:"hide",field:D,values:_.split("|"),ctx:p})}else if(d.startsWith("option-not:")){let D=d.slice(d.indexOf(":")+1);w.add(D),a.push({el:s,kind:"when",match:"show-not",field:D,values:_.split("|"),ctx:p})}}p.view&&s.hasAttribute("bind")&&t.diag.error("E43",s,{attr:"bind",expr:s.getAttribute("bind"),problem:"bind inside an each row; rows are read-only views of the data",fix:"change the record with set:, Sap(el), or a detail panel"}),p.projection&&s.hasAttribute("bind")&&a.push({el:s,kind:"projection",field:s.getAttribute("bind"),ctx:p})}function A(s,p,h){Object.defineProperty(s,"$key",{value:xt(p,"row"),enumerable:!1}),Object.defineProperty(s,"$index",{value:h,enumerable:!1}),Object.defineProperty(s,"$el",{value:p,enumerable:!1})}function x(s,p,h){b(s,p),s._sapScope=p,!h.projection&&s.hasAttribute("bind")&&g(s,h),c(s,h),s.hasAttribute("items")?O(s,p,h):E(s,p,h)}function E(s,p,h){Y(s,(d,_)=>{_?d.hasAttribute("scope")?$(d,p,h):d.hasAttribute("items")?(c(d,h),O(d,p,h)):d.hasAttribute("detail")?l(d,p,h):d.hasAttribute("each")&&(c(d,h),f.push({el:d,ctx:h})):(!h.projection&&!h.view&&g(d,h),c(d,h))})}function $(s,p,h){let d=s.getAttribute("scope"),_={};p[d]=_;let D={root:h.root,state:_,item:null,ownerEl:s,projection:h.projection};x(s,_,D)}function O(s,p,h){let d=s.getAttribute("items"),_=[];p[d]=_,s._sapList=_,X(s).forEach((D,ct)=>{let V={};A(V,D,ct);let tt={root:h.root,state:h.state,item:V,ownerEl:D,projection:h.projection};x(D,V,tt),_.push(V)})}function U(s,p){let h=String(s).split("."),d=p.state;for(let _ of h)d=d?.[_];if(d===void 0){d=p.root;for(let _ of h)d=d?.[_]}return d}function l(s,p,h){for(let d of q(s.getAttribute("state")||""))d.name in p||(p[d.name]=W(s,d));y.push({el:s,parentObj:p,ctx:h})}function i(s,p,h){s._sapScope=p;let d=s.getAttribute("detail")||"",_=/^([\w.]+)\s+by\s+(.+)$/.exec(d);if(!_){s.hidden=!0,s._sapDetailRow=null;return}let D=_[1],ct=_[2].trim(),V=U(D,h),tt;try{tt=G(P(ct),{state:p,item:h.item,el:s,root:h.root})}catch{tt=void 0}let Q=Array.isArray(V)?V.find(st=>st&&String(st.$key)===String(tt)):null;if(s._sapDetailRow=Q?Q.$el:null,!Q){s.hidden||(s.hidden=!0);return}s.hidden&&(s.hidden=!1);let ot={root:h.root,state:p,item:Q,ownerEl:Q.$el,projection:!0};c(s,ot),E(s,Q,ot)}function m(s,p){let h=[...s.children].find(B=>B.tagName==="TEMPLATE"),d=h&&h.content.children.length===1?h.content.firstElementChild:null;if(!d)return t.diag.error("E42",s,{attr:"each",problem:"each needs one <template> child with exactly one element root"}),0;let _=s.getAttribute("each"),D;try{D=G(P(_),{state:p.state,item:p.item,el:s,root:p.root})}catch(B){return t.diag.error("E24",s,{attr:"each",expr:_,problem:String(B.message)}),0}if(!Array.isArray(D))return t.diag.error("E40",s,{attr:"each",expr:_,problem:"each must evaluate to an array; the list keeps its last good rows"}),0;let ct=P(s.getAttribute("key")||"item.$key"),V=[],tt=new Set;for(let B of D){let z;try{z=G(ct,{state:p.state,item:B,el:s,root:p.root})}catch{z=void 0}let M=z==null?"":String(z);if(M===""||tt.has(M))return t.diag.error("E41",s,{attr:"key",expr:ct.src,problem:M===""?"an item has no key; the list keeps its last good rows":`duplicate key "${M}"; the list keeps its last good rows`}),0;tt.add(M),V.push(M)}let Q=s._sapEach||new Map,ot=new Map,st=0,zt=h;V.forEach((B,z)=>{let M=Q.get(B);if(!M||M.parentElement!==s){M=s.ownerDocument.importNode(d,!0);let ht=(M.getAttribute("clay")||"").split(/\s+/).filter(Boolean);ht.includes("editor-ui")||M.setAttribute("clay",[...ht,"editor-ui"].join(" ")),M._sapEachRow=!0,st++}M.getAttribute("data-key")!==B&&M.setAttribute("data-key",B),zt.nextElementSibling!==M&&(Ar(s,M,zt),st++),M._sapEachItem=D[z],ot.set(B,M),zt=M});for(let[B,z]of Q)ot.get(B)!==z&&z.parentElement===s&&(z.remove(),st++);return s._sapEach=ot,V.forEach((B,z)=>{let M=ot.get(B),ht={root:p.root,state:p.state,item:D[z],ownerEl:M,projection:!1,view:!0};c(M,ht),E(M,{},ht)}),st}x(n,r,N);for(let s=0;s<y.length;s++){let{el:p,parentObj:h,ctx:d}=y[s];i(p,h,d)}if(k.length&&w.size)for(let s of k)w.has(s.attr)&&s.el.getAttribute(s.attr)==null&&s.el.setAttribute(s.attr,s.value);let v=new Map;for(let s of o){let p=v.get(s.owner);p||(p={ownerEl:s.ownerEl,list:[]},v.set(s.owner,p)),p.list.push(s)}let S=[...v.values()].sort((s,p)=>ve(p.ownerEl)-ve(s.ownerEl));for(let s of S){let p;try{p=ue(s.list)}catch(h){t.diag.error("E07",s.list[0].el,{problem:h.message}),p=s.list}for(let h of p)try{h.owner[h.name]=G(h.entry,{state:h.ctx.state,item:h.ctx.item,el:h.el,root:h.ctx.root}),Ot(h.el)}catch(d){h.owner[h.name]=void 0,t.diag.error("E24",h.el,{attr:"calc:"+h.name,expr:h.entry.src,problem:String(d.message)}),at(h.el,d.sapCode||"E24")}}let T=0;for(let s=0;s<f.length;s++)T+=m(f[s].el,f[s].ctx);let L=0,C=T;for(let s of a){let p=gr(s,t);s.ctx.view?C+=p:L+=p}for(let s of u)wr(s,t);for(let s of R)yr(s);t._state=r,t._stats={fields:Object.keys(r).filter(s=>typeof r[s]!="function").length,calcs:o.length,paints:a.length,lists:v.size,writes:L,viewWrites:C},t._viewsChanged=C>0,t._lastPass={trigger:e.trigger||"refresh",writes:L},t._debug&&console.log(`sap pass \xB7 trigger: ${t._lastPass.trigger} \xB7 writes ${L}/${a.length}`)}function hr(t){return t.kind==="text"?t.fmt?"text:"+t.fmt:"text":t.kind==="attr"?"attr:"+t.arg:t.kind==="class"?"class:"+t.arg:t.kind==="css"?"css:"+t.arg:t.kind==="when"?(t.match==="hide"?"hide-when:":t.match==="show-not"?"option-not:":"show-when:")+t.field:t.kind}function Xt(t,e,n,r){let o=t;for(;o&&o.nodeType===1;){if(o.hasAttribute&&o.hasAttribute(e)){let a=n.includes(o.getAttribute(e));if(r?!a:a)return!0}o=o.parentElement}return!1}function br(t,e){if(t===t.ownerDocument.activeElement)return 0;let n=F(t),r=n.read(),o=e??"";return String(r)!==String(o)?(n.write(o,{silent:!0}),1):0}function gr(t,e){if(t.kind==="projection")return br(t.el,t.ctx.item?t.ctx.item[t.field]:"");if(t.kind==="when")return Ae(t,null);let n={state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root};try{let r=G(t.entry,n),o=Ae(t,r);return Ot(t.el),o}catch(r){return e.diag.error(r.sapCode==="E22"?"E22":"E24",t.el,{attr:hr(t),expr:t.entry&&t.entry.src,problem:String(r.message)}),at(t.el,r.sapCode||"E24"),0}}function Ae(t,e){let n=t.el;switch(t.kind){case"text":{let r=t.fmt!=null?oe(t.fmt,e):e==null?"":String(e);return n.textContent!==r?(n.textContent=r,1):0}case"show":{let r=!e;return n.hidden!==r?(n.hidden=r,1):0}case"when":{let r=j("optionVisibility");if(r&&r._started)return n._sapWhen&&n.hidden?(n.hidden=!1,n._sapWhen=!1,1):0;let o;t.match==="hide"?o=!Xt(n,t.field,t.values,!1):t.match==="show-not"?o=Xt(n,t.field,t.values,!0):o=Xt(n,t.field,t.values,!1),n._sapWhen=!0;let a=!o;return n.hidden!==a?(n.hidden=a,1):0}case"attr":{let r=t.arg;if(Ee.has(r)){let a=n.hasAttribute(r);return e&&!a?(n.setAttribute(r,""),1):!e&&a?(n.removeAttribute(r),1):0}let o=typeof e=="boolean"?String(e):e==null?"":String(e);return n.getAttribute(r)!==o?(n.setAttribute(r,o),1):0}case"class":{let r=!!e;return n.classList.contains(t.arg)!==r?(n.classList.toggle(t.arg,r),1):0}case"css":{let r=e==null?"":String(e);return n.style.getPropertyValue("--"+t.arg)!==r?(n.style.setProperty("--"+t.arg,r),1):0}default:return 0}}function wr(t,e){try{G(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root}),Ot(t.el)}catch(n){e.diag.error("E24",t.el,{attr:"effect",expr:t.entry&&t.entry.src,problem:String(n.message)}),at(t.el,"E24")}}function yr(t){let e="";try{let n=G(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root});e=typeof n=="string"?n:""}catch{e=""}typeof t.el.setCustomValidity=="function"&&t.el.setCustomValidity(e)}function ve(t){let e=0,n=t;for(;n&&!(n.hasAttribute&&n.hasAttribute("sap"));)n=n.parentElement,e++;return e}function Ar(t,e,n){let r=n.nextSibling;if(e.isConnected&&t.moveBefore)try{t.moveBefore(e,r);return}catch{}t.insertBefore(e,r)}var vr=new Set(Dt),Se=new Set(["calc","text","attr","class","css","set","move","sort","option","option-not","show-when","hide-when","editmode"]),Er=new Set(["show-when","hide-when","option","option-not"]),Sr=/\b(?:state|item|root)\.|===|!==|&&|\|\||[()]|^\s*!/,xe=new Set(["sap","scope","items","item","template","bind","show","effect","invalid","detail","state","transient","confirm","default","persist","sortable","trigger-add","trigger-remove","trigger-reset","sap-ignore","sap-error","no-save","no-watch","no-undo","no-trigger-autosave","freeze","mutations-ignore","save-remove","save-ignore","save-freeze"]);function xr(t){return t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA"}function Kt(t){return t.hasAttribute("bind")}function kr(t,e){e(t);for(let r of t.children)n(r);function n(r){if(r.nodeType===1&&!((r.hasAttribute("sap-ignore")||r.hasAttribute("template"))&&r.hasAttribute("sap-ignore"))){e(r);for(let o of r.children)n(o)}}}function Bt(t,e){let n=!1,r=(u,R,k)=>{e.error(u,R,k),n=!0},o=t.ownerDocument.createTreeWalker(t,4),a;for(;a=o.nextNode();)if(/\{\{.*\}\}/.test(a.nodeValue||"")){r("E02",a.parentElement||t,{problem:"moustaches in text content are not a Sap feature",fix:'move the expression onto the element: text="state.x"'});break}return kr(t,u=>{let R=u.closest&&u.closest("[detail]");for(let k of[...u.attributes]){let y=k.name,f=be(y);if(f){r("E01",u,{attr:y,expr:k.value,problem:`"${y}" is a foreign-dialect attribute; Sap has no ${y.split(/[:=]/)[0]} directive`,fix:f+" \u2014 or wrap the subtree in sap-ignore if intentional"});continue}if(y.includes(":")){let w=y.slice(0,y.indexOf(":"));if(Se.has(w)){if(Er.has(w)&&Sr.test(k.value)){let N=y.slice(y.indexOf(":")+1);e.warn("W04",u,{attr:y,expr:k.value,problem:`${w}: compares the "${N}" attribute against a literal value, not a JS expression`,fix:`use show="${k.value}" for an expression, or a literal like ${w}:${N}="overview"`})}}else{let N=St(w,[...Se]);e.warn("W03",u,{attr:y,problem:`unknown "${w}:" attribute`,didYouMean:N?`${N}:`:null})}}else if(!xe.has(y)&&!Et.has(y)&&!vr.has(y)&&!/^(data-|aria-|on)/.test(y)&&!(y in u)){let w=St(y,[...xe]);w&&e.warn("W03",u,{attr:y,problem:`unknown "${y}" attribute`,didYouMean:w})}y==="attr:hidden"&&e.warn("W03",u,{attr:y,problem:"attr:hidden paints the wrong attribute",fix:'use show="expr"'}),(y==="attr:value"||y==="attr:checked"||y==="attr:selected")&&Kt(u)&&r("E30",u,{attr:y,problem:"attr: on a bound control collides with persist ownership",fix:"remove it; bind owns this attribute"}),y==="effect"&&Kt(u)&&/\b(value|checked)\s*=[^=]/.test(k.value)&&r("E30",u,{attr:y,expr:k.value,problem:"effect writes value/checked on a bound control (writes a stale value with no synthetic event)",fix:"write through onclick + Sap(this) instead"}),(y==="text"||y.startsWith("text:")||y==="show")&&xr(u)&&(y==="show"||r("E18",u,{attr:y,problem:"paint belongs on output elements, not form controls",fix:"move the paint to an <output> or <span>"}))}if(u.hasAttribute("state")){let k=q(u.getAttribute("state")),y=new Set;for(let f of k)f.name.includes("-")&&r("E08",u,{attr:"state",problem:`field "${f.name}" is not a valid identifier (the hyphen parses as subtraction)`,fix:`rename to ${f.name.replace(/-/g,"")}`}),y.has(f.name)&&r("E04",u,{attr:"state",problem:`field "${f.name}" is declared twice in one scope`}),y.add(f.name),It.has(f.attr)&&r("E05",u,{attr:"state",problem:`"${f.name}" is a reserved Sap word`}),Et.has(f.attr)&&r("E06",u,{attr:"state",problem:`"${f.name}" is a global HTML attribute name; pick another field name`}),f.name==="open"&&u.tagName==="DIALOG"&&r("E33",u,{attr:"state",problem:"dialog open is transient",fix:"use showModal() \u2014 declare state= only on <details> or popovers"})}if(Kt(u)){if(u.hasAttribute("-"),u.tagName==="INPUT"){let k=(u.getAttribute("type")||"text").toLowerCase();k==="file"&&r("E32",u,{attr:"bind",problem:"files never serialize into an HTML file",fix:"use no-save + effect instead of bind"}),k==="password"&&!u.hasAttribute("transient")&&r("E31",u,{attr:"bind",problem:"a password must never serialize into a world-readable file",fix:"add transient to the password input"})}else if(u.tagName!=="SELECT"&&u.tagName!=="TEXTAREA"){let k=u.getAttribute("contenteditable");!(k!=null&&k!=="false")&&u.children.length>0&&r("E20",u,{attr:"bind",problem:"bind on a container element is not a control; a write would overwrite its children",fix:"bind a control (input/select/textarea), a contenteditable, or an empty text leaf"})}}if(u.hasAttribute("transient")&&u.hasAttribute("persist")&&r("E34",u,{problem:"transient and persist are opposite: persist forces the live value into the saved bytes, leaking exactly what transient drops",fix:"remove one \u2014 transient to keep it out of the file, or persist to save it"}),u.hasAttribute("item")&&!u.hasAttribute("template")){let k=u.parentElement;(!k||!k.hasAttribute("items"))&&r("E10",u,{problem:"an [item] must be a direct child of an [items] list",fix:'wrap it in a container with items="name"'})}if(u.hasAttribute("items")&&R&&r("E17",u,{attr:"items",problem:"nested items inside a detail panel is a v1 mount error (nested collections ship in v1.1)"}),u.hasAttribute("items")){let k=t.querySelector(`[trigger-add="${u.getAttribute("items")}"]`);!_t(u)&&X(u).length===0&&k&&r("E17",u,{attr:"items",problem:`trigger-add targets items="${u.getAttribute("items")}" but it has no [item template] to clone`})}}),n&&(e.halted=!0,e.haltReason=e.errors[0]?e.errors[0].code:"halt",at(t,e.haltReason)),!n}var ke="sap-styles",$e="[item][template]{display:none!important}[hidden]{display:none!important}[sap-error]{outline:2px solid #e5484d;outline-offset:1px}",Jt=new WeakSet;function $r(t){if(Jt.has(t))return;let e=t.defaultView,n=e&&e.CSSStyleSheet;if(n&&"adoptedStyleSheets"in t)try{let r=new n;r.replaceSync($e),t.adoptedStyleSheets=[...t.adoptedStyleSheets,r],Jt.add(t);return}catch{}if(!t.getElementById(ke)){let r=t.createElement("style");r.id=ke,r.textContent=$e,(t.head||t.documentElement).appendChild(r)}Jt.add(t)}var _r=0;function _e(){return typeof performance<"u"&&performance.now?performance.now():0}function Qt(t){let e=t.id||t.getAttribute("sap")||`app-${_r++}`,n=new dt(e),r={root:t,name:e,diag:n,_state:null,_stats:null,_lastPass:null,_passes:0,_broken:!1,_mountMs:0,_mountWrites:0};if(!Bt(t,n))return r.halted=!0,r;$r(t.ownerDocument);for(let u of t.querySelectorAll("textarea[data-value]"))Ct(u);let a=_e();return mt(r,{trigger:"mount"}),r._mountMs=_e()-a,r._mountWrites=r._stats?r._stats.writes:0,r._mountWrites>0&&n.warn("W30",t,{problem:`${r._mountWrites} paint(s) ran at mount; the saved file was out of sync with its declared state`,fix:"re-save once so the file mounts clean (a settled file writes nothing)"}),r}function Nr(t,e){let n=null;return Y(t,r=>{!n&&r.getAttribute("scope")===e&&(n=r)}),n}function Ne(t,e,n){let r=H(t)||e;for(;r;){for(let o of q(r.getAttribute("state")||""))if(o.name===n)return{el:r,decl:o};if(r.hasAttribute("sap"))break;r=H(r.parentElement)}return null}function Tr(t){return typeof t=="number"?"num":typeof t=="boolean"?"bool":"string"}function Te(t){function e(b){let g=t.appFor(b);if(!g)return null;let c=gt(b),A=c&&c._sapEachItem&&c._sapEachItem.$el;if(A&&A.isConnected)return{ctxEl:A,appRec:g,isRow:!0};let x=wt(b);if(x)return x._sapDetailRow?{ctxEl:x._sapDetailRow,appRec:g,isRow:!0}:{ctxEl:H(x.parentElement)||g.root,appRec:g,isRow:!1};let E=$t(b);if(E&&E.hasAttribute("item"))return{ctxEl:E,appRec:g,isRow:!0};let $=H(b)||g.root;return{ctxEl:$,appRec:g,isRow:$.hasAttribute("item")}}function n(b){let g=typeof b=="string"?document.querySelector(b):b;if(!g||g.nodeType!==1)return null;let c=e(g);return c?W(c.ctxEl,c.appRec,c.isRow):null}function r(b,g,c){let A=ft(b,c);if(A)return F(A).read();let x=bt(b,c);if(x)return X(x).map(U=>W(U,g,!0));let E=Nr(b,c);if(E)return W(E,g,!1);let $=Ne(b,g.root,c);if($)return $.decl.transient?Tt($.el,$.decl):it($.el.getAttribute($.decl.attr||c),$.decl.type);let O=b._sapScope;return O?O[c]:void 0}function o(b,g,c,A,x){A.transient?jt(b,A,c):b.setAttribute(A.attr||g,Nt(c,A.type)),t.schedule(x,"set:"+g)}function a(b,g){let c=new Set,A=H(b)||g;for(;A;){for(let x of q(A.getAttribute("state")||""))c.add(x.name);if(A.hasAttribute("sap"))break;A=H(A.parentElement)}return Y(b,x=>{let E=x.getAttribute("bind");E&&c.add(E)}),c}function u(b,g,c,A){let x=ft(b,c);if(x){F(x).write(A);return}let E=b;for(;E;){for(let S of E.attributes)if(S.name==="calc:"+c){g.diag.error("E16",E,{attr:"calc:"+c,problem:`"${c}" is a computed field; computed fields are read-only`});return}if(E.hasAttribute("sap"))break;E=E.parentElement}let $=Ne(b,g.root,c);if($){o($.el,c,A,$.decl,g);return}let O=a(b,g.root);O.delete(c);let U=c.length>=4?St(c,[...O]):null;if(U){g.diag.error("E12",b,{key:c,problem:`unknown state key "${c}"`,didYouMean:U});return}if(It.has(c)||Et.has(c)){g.diag.error("E15",b,{key:c,problem:`cannot write undeclared field "${c}" \u2014 it is a reserved/global name and cannot become state`,fix:"pick a different field name, or declare it explicitly in a state= attribute"});return}let l=g.root,i=Tr(A),m=l.getAttribute("state")||"",v=i==="string"?c:`${c}:${i}`;l.setAttribute("state",m?`${m} ${v}`:v),o(l,c,A,{name:c,type:i,transient:!1},g)}function R(b){let g=b.ownerDocument;b.querySelectorAll("[id]").forEach(c=>{c.id=kt(g)}),b.querySelectorAll("[sap-error]").forEach(c=>c.removeAttribute("sap-error")),b.removeAttribute("sap-error"),b.hasAttribute("data-id")?(b.removeAttribute("id"),b.setAttribute("data-id",kt(g))):b.id=kt(g)}function k(b,g,c){let A=yt(g.root,b,c);if(!A)return g.diag.error("E17",b,{problem:`cannot resolve a list named "${c}" from here`}),null;let x=_t(A);if(!x)return g.diag.error("E17",A,{problem:`items="${c}" has no [item template] to clone`}),null;let E=x.cloneNode(!0);return E.removeAttribute("template"),R(E),A.appendChild(E),t.schedule(g,"trigger-add:"+c),W(E,g,!0)}function y(b,g){Y(b,c=>{if(c.hasAttribute("bind")){let A=F(c),x=c.getAttribute("default");A.kind==="checkbox"||A.kind==="radio"?A.write(x!=null?x===""||x==="true"||c.value===x:c.hasAttribute("checked")):A.write(x??(c.getAttribute("value")||""))}});for(let c of q(b.getAttribute("state")||"")){let A=c.default!=null?c.default:c.type==="num"?"0":c.type==="bool"?"false":"";c.transient?jt(b,c,it(A,c.type)):b.setAttribute(c.attr,A)}t.schedule(g,"trigger-reset")}function f(b,g){if(!b.isConnected)throw new Error("stale row handle: $remove() on a removed row");b.remove(),t.schedule(g,"trigger-remove")}function w(b,g,c){if(!b.isConnected)throw new Error("stale row handle: $move() on a removed row");let A=null;if(c&&c.nodeType===1?A=c:typeof c=="string"&&(A=yt(g.root,b,c)),!A){g.diag.error("E17",b,{problem:`$move() cannot resolve target "${c}"`});return}t.moveInto(A,b),t.schedule(g,"trigger-move")}function N(b){let g=b.parentElement;return g?X(g).indexOf(b):-1}function W(b,g,c){let A={get $el(){return b},get $key(){return xt(b,c?"row":"scope")},get $index(){return N(b)},$add(E){return k(b,g,E)},$reset(){return y(b,g),x},$remove(){f(b,g)},$move(E){w(b,g,E)},get $appRec(){return g}},x=new Proxy(A,{get(E,$){return typeof $=="symbol"||$[0]==="$"?E[$]:r(b,g,$)},set(E,$,O){return typeof $=="string"&&$[0]==="$"?(E[$]=O,!0):(u(b,g,$,O),!0)},has(E,$){return typeof $=="string"&&$[0]==="$"?$ in E:r(b,g,$)!==void 0}});return x}return{Sap:n,contextElFor:e,readField:r,writeField:u,makeProxy:W}}var Lr=["trigger-add","trigger-remove","trigger-reset"];function Rr(t){if(t.nodeType!==1)return!1;for(let e of t.attributes){let n=e.name;if(n.startsWith("set:")||n.startsWith("move:")||n.startsWith("sort:")||Lr.includes(n))return!0}return!1}function Cr(t,e){let n=t,r=e.parentElement;for(;n&&n!==r;){if(n.nodeType===1&&Rr(n)&&!(n.tagName==="FORM"&&n.hasAttribute("trigger-add")))return n;n=n.parentElement}return null}function Le(t,e){let{Sap:n}=e;function r(l,i){let m=null,v=gt(l),S=wt(l);if(v)m=v._sapEachItem??null;else if(S&&S._sapDetailRow)m=S._sapDetailRow._sapScope||null;else{let C=$t(l);C&&C.hasAttribute("item")&&(m=C._sapScope||null)}return{state:(H(l)||i.root)._sapScope||i._state||{},item:m,el:l,root:i._state||{}}}function o(l,i,m){if(!l.hasAttribute("confirm")){m();return}let v=l.getAttribute("confirm"),S=v,T=P(v);if(!T.error)try{let s=G(T,r(l,i));(typeof s=="string"||typeof s=="number")&&(S=String(s))}catch{}let L=de();if(!L){window.confirm(S)&&m();return}if(l._sapGatePending)return;l._sapGatePending=!0;let C=()=>{l._sapGatePending=!1};L(S,()=>{C(),m()}).catch(C)}function a(l,i){for(let m of l.attributes){if(!m.name.startsWith("set:"))continue;let v=m.name.slice(4),S=P(m.value);if(S.error){i.diag.error("E08",l,{attr:m.name,expr:m.value,problem:String(S.error.message)});continue}let T;try{T=G(S,r(l,i))}catch(C){i.diag.error("E24",l,{attr:m.name,expr:m.value,problem:String(C.message)});continue}let L=n(l);L&&(L[v]=T)}}function u(l){let i=gt(l);if(!i)return l.closest("[item]");let m=i._sapEachItem&&i._sapEachItem.$el;return m&&m.nodeType===1&&m.hasAttribute("item")?m:null}function R(l,i){let m=u(l);if(!m)return;let v=X(m.parentElement),S=v.indexOf(m);i==="up"&&S>0?t.placeBefore(m,v[S-1]):i==="down"&&S<v.length-1&&t.placeBefore(v[S+1],m)}function k(l,i,m){if(i)return yt(m.root,l,i);let v=l;for(;v;){if(v.hasAttribute&&v.hasAttribute("items"))return v;v=v.parentElement}let S=H(l)||m.root,T=[];return Y(S,L=>{L.hasAttribute("items")&&T.push(L)}),T[0]||null}function y(l,i){let m=l==null||l==="",v=i==null||i==="";if(m&&v)return 0;if(m)return 1;if(v)return-1;let S=Number(l),T=Number(i);return!Number.isNaN(S)&&!Number.isNaN(T)?S-T:String(l)<String(i)?-1:String(l)>String(i)?1:0}function f(l,i,m,v){let S=k(l,m,v);if(!S){v.diag.error("E17",l,{attr:"sort:"+i,problem:`no items list resolvable for sort:${i}`});return}let T=X(S),L=h=>h._sapScope?h._sapScope[i]:void 0,C=[...T].sort((h,d)=>y(L(h),L(d))),p=C.every((h,d)=>h===T[d])?[...C].reverse():C;for(let h of p)t.moveInto(S,h);t.schedule(v,"sort:"+i)}function w(l){if(!l||l.hidden)return;let i=l.querySelector("[bind]:not([type=hidden]), [contenteditable]");i&&typeof i.focus=="function"&&i.focus()}function N(l,i){o(l,i,()=>{let m=n(l);for(let v of[...l.attributes]){let S=v.name;if(S==="trigger-remove")m&&m.$remove();else if(S==="trigger-reset")m&&m.$reset();else if(S==="trigger-add"){let T=m&&m.$add(v.value);T&&w(T.$el)}else S==="move:up"?(R(l,"up"),t.schedule(i,"move:up")):S==="move:down"?(R(l,"down"),t.schedule(i,"move:down")):S.startsWith("move:to")?m&&m.$move(v.value):S.startsWith("sort:")&&f(l,S.slice(5),v.value,i)}[...l.attributes].some(v=>v.name.startsWith("set:"))&&a(l,i)})}function W(l){let i=l.target;if(!i||i.nodeType!==1)return;let m=t.appFor(i);if(!m)return;let v=Cr(i,m.root);v&&N(v,m)}function b(l){let i=F(l),m=l.getAttribute("default");i.kind==="checkbox"?i.write(m===""||m==="true"):i.write(m??"")}function g(l,i,m){let v=n(l);if(!v)return;let S=v.$add(m);if(!S)return;let T=[];Y(l,L=>{L.hasAttribute("bind")&&T.push(L)});for(let L of T){let C=ft(S.$el,L.getAttribute("bind"));C&&F(C).write(F(L).read())}T.forEach(b),T.length?typeof T[0].focus=="function"&&T[0].focus():w(S.$el)}function c(l){let i=l.target;if(!i||!i.hasAttribute||!i.hasAttribute("trigger-add"))return;let m=t.appFor(i);m&&(l.preventDefault(),o(i,m,()=>g(i,m,i.getAttribute("trigger-add"))))}function A(l){let i=l.target,m=t.appFor(i);m&&setTimeout(()=>{i.querySelectorAll("[bind]").forEach(v=>{v.dispatchEvent(new Event("input",{bubbles:!0})),v.dispatchEvent(new Event("change",{bubbles:!0}))}),t.schedule(m,"reset")},0)}function x(l){let i=t.appFor(l.target);i&&t.schedule(i,"toggle")}function E(l){let i=l.target;if(!i||i.nodeType!==1)return;let m=t.appFor(i);if(!m)return;i.hasAttribute("persist")&&!Mt(i)&<(i);let v=wt(i);if(v&&v._sapDetailRow&&i.hasAttribute("bind")){let S=v._sapDetailRow,T=i.getAttribute("bind"),L=ft(S,T);if(L&&L!==i){F(L).write(F(i).read());return}if(!L&&q(S.getAttribute("state")||"").some(C=>C.name===T)){e.writeField(S,m,T,F(i).read());return}}t.schedule(m,l.type+" "+(i.id||i.tagName.toLowerCase()))}function $(l){let i=l.detail||{};for(let m of[i.from,i.to,l.target]){if(!m||m.nodeType!==1)continue;let v=t.appFor(m);v&&t.schedule(v,"sorted")}}function O(l){if(l.key!=="ArrowUp"&&l.key!=="ArrowDown")return;let i=l.target;if(!i||i.nodeType!==1||i.tagName!=="INPUT"||!i.hasAttribute("bind")||!i.hasAttribute("step"))return;let m=(i.getAttribute("type")||"text").toLowerCase();if(m!=="text"&&m!=="tel"&&m!=="search"||!t.appFor(i))return;l.preventDefault();let S=K(i.getAttribute("step"))||1,T=l.key==="ArrowUp"?1:-1,L=K(i.value)+S*(l.shiftKey?10:1)*T,C=i.getAttribute("min"),s=i.getAttribute("max");C!==null&&C!==""&&L<K(C)&&(L=K(C)),s!==null&&s!==""&&L>K(s)&&(L=K(s)),F(i).write(String(Number(L.toFixed(2))))}function U(l=document){l.addEventListener("click",W),l.addEventListener("submit",c),l.addEventListener("reset",A),l.addEventListener("toggle",x,!0),l.addEventListener("input",E),l.addEventListener("change",E),l.addEventListener("clay:sorted",$),l.addEventListener("keydown",O)}return{install:U}}var Re=/^(set:|move:|sort:|trigger-add$|trigger-remove$|trigger-reset$)/;function Zt(t){return`${t.tagName.toLowerCase()}[sap]`}function Mr(t){let e=0;for(let n of t.querySelectorAll("*"))for(let r of n.attributes)if(Re.test(r.name)){e++;break}for(let n of t.attributes)if(Re.test(n.name)){e++;break}return e}function Ce(t){let e=[],n=r=>{for(let o of r.attributes){let a=o.name;(a.startsWith("calc:")||a==="text"||a.startsWith("text:")||a==="show"||a.startsWith("attr:")||a.startsWith("class:")||a.startsWith("css:")||a==="effect"||a==="invalid"||a.startsWith("set:")||a==="detail")&&e.push({el:r,attr:a,src:o.value})}};n(t);for(let r of t.querySelectorAll("*"))n(r);return e}function Me(t){function e(f){let w=f._stats||{},N=f.root;return{root:Zt(N),fields:w.fields||0,calcs:w.calcs||0,paints:w.paints||0,actions:Mr(N),lists:(N.hasAttribute("items")?1:0)+N.querySelectorAll("[items]").length,rows:N.querySelectorAll("[item]:not([template])").length,warnings:f.diag.warnings.length,errors:f.diag.errors.length,mountWrites:f._mountWrites||0,ms:Math.round((f._mountMs||0)*10)/10,passes:f._passes||0,lastPass:f._lastPass||null,ok:f.diag.errors.length===0&&!f.halted}}function n(){let f=t.apps().map(e);return{ok:f.every(w=>w.ok),apps:f}}function r(f){let w=e(f);return w.ok?`sap \u2713 ${w.root} \xB7 fields ${w.fields} \xB7 calcs ${w.calcs} \xB7 paints ${w.paints} \xB7 actions ${w.actions} \xB7 lists ${w.lists} \xB7 rows ${w.rows} \xB7 warnings ${w.warnings} \xB7 mount writes ${w.mountWrites} \xB7 ${w.ms}ms`:`sap \u2717 ${w.root} \xB7 errors ${w.errors} \xB7 warnings ${w.warnings} \xB7 ${w.ms}ms`}function o(){for(let f of t.apps()){let w=r(f);f.diag.errors.length||f.halted?console.error(w):console.log(w)}}function a(){let f=[],w=[];for(let N of t.apps())f.push(...N.diag.errors),w.push(...N.diag.warnings);return{ok:f.length===0,errors:f,warnings:w,counts:{errors:f.length,warnings:w.length}}}function u(f){return f?typeof f=="string"?document.querySelector(f):f.nodeType===1?f:null:null}function R(f,w){let N=u(f);if(!N)return console.warn("sap why: element not found"),null;let W=[`sap why <${N.tagName.toLowerCase()}> \u2014 ${Wt(N)}`],b=[...N.attributes].filter(c=>/^(bind|text|show|effect|invalid|detail|calc:|text:|attr:|class:|css:|set:|state|items|scope)/.test(c.name));for(let c of b)W.push(` ${c.name}="${c.value}"`);let g=N;for(;g&&!g._sapScope;)g=g.parentElement;if(g&&g._sapScope){let c=g._sapScope,A=w?[w]:Object.keys(c);W.push(" reads:");for(let x of A){let E=c[x];typeof E!="function"&&W.push(` ${x} = ${JSON.stringify(Array.isArray(E)?`[${E.length} rows]`:E)}`)}}return W.push(" serialization: textContent and value/checked attributes save with the file; reads live from properties"),console.log(W.join(`
|
|
10
|
-
`)),null}function k(f){let w=f===void 0?!0:!!f;for(let N of t.apps())N._debug=w;return console.log(`sap debug ${w?"on":"off"} \u2014 per-pass headers will ${w?"":"no longer "}log`),w}function y(){let f=[],w=0;for(let c of t.apps()){let A=c.root,x=Zt(A);w++;let E=new dt(c.name);Bt(A,E);for(let i of E.errors)f.push({code:i.code,severity:"error",message:`${x}: ${i.code} ${i.slug} at ${i.el}`});for(let i of E.warnings)f.push({code:i.code,severity:"warn",message:`${x}: ${i.code} ${i.slug} at ${i.el}`});w++,mt(c,{trigger:"doctor-dryrun"});let $=c._stats?c._stats.writes:0;$>0&&f.push({code:"W30",severity:"warn",message:`${x}: dry recompute wrote ${$} cells on a quiet page; an element is stale or non-idempotent`}),w++;let O=Ce(A).map(i=>i.src).join(" \0 "),U=[];for(let i of[A,...A.querySelectorAll("[state]")])for(let m of q(i.getAttribute("state")||""))U.push(m.name);for(let i of U)new RegExp(`(state|item)\\.${i}\\b`).test(O)||f.push({code:"I33",severity:"info",message:`${x}: field "${i}" is declared but read nowhere (dead state)`});w++;let l=new Map;for(let i of A.querySelectorAll("[id]"))l.set(i.id,(l.get(i.id)||0)+1);for(let[i,m]of l)m>1&&f.push({code:"W32",severity:"warn",message:`${x}: duplicate id "${i}" (${m} elements) \u2014 clone/edit collision`});w++;for(let i of Ce(A))i.src.length>120&&f.push({code:"I33",severity:"info",message:`${x}: ${i.attr} expression is ${i.src.length} chars; consider a calc: field`});w++;for(let i of A.querySelectorAll("[text], [text\\:num]")){let m=i.textContent||"";/\.\d{5,}/.test(m)&&f.push({code:"I33",severity:"info",message:`${x}: ${Wt(i)} paints >4 decimals; consider text:FMT`})}}let N=f.filter(c=>c.severity==="error").length,W=f.filter(c=>c.severity==="warn").length,b=f.filter(c=>c.severity==="info").length;console.log(`sap doctor \xB7 ${t.apps().map(c=>Zt(c.root)).join(", ")} \xB7 errors ${N} \xB7 warnings ${W} \xB7 info ${b} \xB7 ${w} checks \xB7 0ms`);for(let c of f)(c.severity==="error"?console.error:c.severity==="warn"?console.warn:console.info)(` ${c.severity==="error"?"\u2717":c.severity==="warn"?"\u26A0":"\xB7"} ${c.message}`);return f}return{status:n,report:a,why:R,debug:k,doctor:y,greenLine:r,printGreenLines:o,REGISTRY:Vt}}var Dr="0.2.0",J=new Map,rt=[],te=ee(mt);function Ir(t){let e=t;for(;e;){if(e.nodeType===1&&e.hasAttribute&&e.hasAttribute("sap"))return J.get(e)||null;e=e.parentNode&&e.parentNode.host?e.parentNode.host:e.parentElement}return null}function Wr(){for(let t=rt.length-1;t>=0;t--){let e=rt[t];e.root.isConnected||(J.delete(e.root),rt.splice(t,1))}}function Or(t,e){if(t.moveBefore)try{t.moveBefore(e,null);return}catch{}t.appendChild(e)}function Pr(t,e){let n=e.parentElement;if(n){if(n.moveBefore)try{n.moveBefore(t,e);return}catch{}n.insertBefore(t,e)}}var ut={apps:()=>rt.slice(),appFor:Ir,isRegistered:t=>J.has(t),pruneDisconnected:Wr,schedule:(t,e)=>te.schedule(t,e),runNow:(t,e)=>te.runNow(t,e),moveInto:Or,placeBefore:Pr,remountIfPresent:()=>qt()},Ie=Te(ut),Fr=Le(ut,Ie),nt=Me(ut),De=!1;function We(){De||(De=!0,Fr.install(document),me(ut))}function qt(t=document){We(),Gt(ut);let e=t.querySelectorAll("[sap]"),n=[];for(let r of e){if(J.has(r))continue;let o=Qt(r);J.set(r,o),rt.push(o),n.push(o)}for(let r of n){let o=nt.greenLine(r);r.diag.errors.length||r.halted?console.error(o):console.log(o)}return n}function Oe(t){if(We(),Gt(ut),!t)return qt();let e=typeof t=="string"?document.querySelector(t):t;if(!e)return null;if(J.has(e))return J.get(e);let n=Qt(e);J.set(e,n),rt.push(n);let r=nt.greenLine(n);return n.diag.errors.length||n.halted?console.error(r):console.log(r),n}var I=Ie.Sap;I.version=Dr;I.refresh=function(){for(let e of rt)e.root.isConnected&&te.runNow(e,"refresh")};I.batch=pe;I.status=nt.status;I.report=nt.report;I.why=nt.why;I.debug=nt.debug;I.doctor=nt.doctor;I.greenLine=nt.greenLine;I.formats=At;I.serializeControlToAttributes=lt;I.finalizeControlForSave=fe;I.rehydrateControlFromAttributes=Ct;I.mount=Oe;I.config=function(e={}){return e.formats&&Object.assign(At,e.formats),I};I._registry=J;I._reset=function(){J.clear(),rt.length=0,ye()};function Br(){if(typeof document>"u")return;let t=()=>le(()=>qt());document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t):t()}Br();typeof window<"u"&&(window.Sap=I);var qr=I;return He(zr);})();
|
|
9
|
+
`+e.value:e.value;t.textContent!==r&&(t.textContent=r),t.removeAttribute("data-value");return}if(n==="SELECT"){let r=t.options,i=e.options;for(let s=0;s<r.length;s++)i[s]&&i[s].selected?r[s].hasAttribute("selected")||r[s].setAttribute("selected",""):r[s].removeAttribute("selected")}}function qt(t){t.tagName!=="TEXTAREA"||!t.hasAttribute("data-value")||t!==t.ownerDocument.activeElement&&(t.textContent=t.getAttribute("data-value"),t.removeAttribute("data-value"))}function X(t){if(typeof window>"u")return null;let e=window.clay,n=window.hyperclay;return t==="consent"?e?.confirm||n?.consent||null:e?.[t]||n?.[t]||null}var Zt=["clay:mutation-ready","hyperclay:mutation-ready"],wr=["clay:sync-applied","hyperclay:livesync-applied"],yr=["clay:ready","hyperclay:ready"],Ar=["clay:route"];function yt(t,e,n){let r=null,i=s=>{r!==null&&r!==s.type||(r=s.type,queueMicrotask(()=>{r=null}),n(s))};for(let s of e)t.addEventListener(s,i);return()=>{for(let s of e)t.removeEventListener(s,i)}}function Se(t){let e=typeof window<"u"&&window.clay&&window.clay.ready;e&&typeof e.then=="function"?e.then(()=>t(),()=>t()):t()}function Vt(t){let e=X("region");return!e||typeof e.resolveRegionPolicy!="function"||typeof e.skipForPolicy!="function"?!1:e.skipForPolicy(e.resolveRegionPolicy(t),void 0,["no-save","freeze"])}function xe(){let t=X("consent");return typeof t=="function"?t:null}function ke(t,e){if(typeof e!="function")throw new Error("Sap.batch(label, fn): fn must be a function");let n=X("undo");n&&n.flush&&n.flush();let r=e();if(r&&typeof r.then=="function")throw new Error("Sap.batch fn must be synchronous (it returned a promise)");return n&&n.commitCaptured&&n.commitCaptured(t),r}function $e(t){if(typeof window>"u"||typeof document>"u")return;let e=()=>{let s=!1;for(let a of t.apps())a.root.isConnected?t.runNow(a,"platform"):s=!0;s&&(t.pruneDisconnected(),t.remountIfPresent())};yt(document,wr,e),yt(document,Ar,e);let n=!1,r=()=>{},i=()=>{if(n)return!0;let s=X("undo");if(!s||typeof s.on!="function")return!1;let a=s.on("undo",e);return typeof a!="function"?!1:typeof s.on("redo",e)!="function"?(a(),!1):(n=!0,r(),!0)};if(!i()){let s=yt(document,Zt,i),a=yt(document,yr,i);r=()=>{s(),a()};let R=X("ready");R&&typeof R.then=="function"&&R.then(i,()=>{})}}function Er(t){let e=t.tagName;if(e==="INPUT"){let n=(t.getAttribute("type")||"text").toLowerCase();return n==="checkbox"?"checkbox":n==="radio"?"radio":n==="number"||n==="range"?"number":n==="hidden"?"hidden":"text"}return e==="TEXTAREA"?"text":e==="SELECT"?t.multiple?"select-multiple":"select-one":"leaf"}function vr(t){if(t.validity&&t.validity.badInput)return t.hasAttribute("value")?Number(t.getAttribute("value"))||0:t._sapLastGood??0;if(t.value==="")return 0;let e=Number(t.value);return Number.isNaN(e)?t._sapLastGood??0:(t._sapLastGood=e,e)}function Sr(t,e){switch(e){case"checkbox":return t.checked;case"radio":return t.checked?t.value:void 0;case"number":return vr(t);case"select-one":return t.value;case"select-multiple":return[...t.selectedOptions].map(n=>n.value);case"hidden":case"text":return t.value;case"leaf":return t.textContent;default:return t.value}}function xr(t,e,n){switch(e){case"checkbox":t.checked=!!n;break;case"radio":t.checked=String(t.value)===String(n);break;case"number":case"text":case"hidden":t.value=n==null?"":String(n);break;case"select-one":t.value=n==null?"":String(n);break;case"select-multiple":{let r=new Set((Array.isArray(n)?n:[n]).map(String));for(let i of t.options)i.selected=r.has(i.value);break}case"leaf":t.textContent=n==null?"":String(n);break;default:t.value=n==null?"":String(n)}}function _e(t){if(t.hasAttribute("transient")){t.removeAttribute("value"),t.removeAttribute("checked"),t.removeAttribute("data-value");return}Vt(t)||wt(t)}function kr(t){t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function P(t){let e=Er(t);return{el:t,kind:e,read(){return Sr(t,e)},write(n,r={}){xr(t,e,n),r.noMirror||_e(t),r.silent||kr(t)},mirror(){_e(t)}}}var ot=null,Ht=!1,At=null;function Te(t){let e=null;return{kind:"hub",subscribe(n){let r=t.onAnyChange({debounce:0,require:"observed"},n);typeof r=="function"&&(e=r)},suppress(n){t.pause();try{return n()}finally{t.resume()}},teardown(){if(e){try{e()}catch{}e=null}}}}function $r(){let t=null;return{kind:"native",subscribe(e){t=new MutationObserver(r=>e(_r(r)));let n=typeof document<"u"&&document.body||typeof document<"u"&&document.documentElement;n&&t.observe(n,{childList:!0,subtree:!0,attributes:!0,characterData:!0})},suppress(e){let n=X("undo");n&&n.pause&&n.pause();try{return e()}finally{t&&t.takeRecords(),n&&n.resume&&n.resume()}},teardown(){t&&(t.disconnect(),t=null)}}}function _r(t){let e=[];for(let n of t)if(n.type==="attributes"){let r=n.target;r&&r.nodeType===1&&!zt(r)&&e.push({type:"attribute",element:r})}else if(n.type==="characterData"){let r=n.target&&n.target.parentElement;r&&!zt(r)&&e.push({type:"characterData",element:r})}else if(n.type==="childList"){for(let r of n.addedNodes)if(!(r.nodeType!==1||zt(r))&&(e.push({type:"add",element:r}),r.querySelectorAll))for(let i of r.querySelectorAll("*"))zt(i)||e.push({type:"add",element:i});for(let r of n.removedNodes)r.nodeType===1&&e.push({type:"remove",element:r,parent:n.target})}return e}function zt(t){return!!(t.closest&&t.closest("[sap-ignore],[template]"))}function Tr(t,e){t.pruneDisconnected();let n=new Set,r=!1;for(let i of e){let s=i.type==="remove"?i.parent:i.element,a=s&&t.appFor(s);a&&n.add(a),i.type==="add"&&i.element&&i.element.nodeType===1&&i.element.hasAttribute&&i.element.hasAttribute("sap")&&!(t.isRegistered&&t.isRegistered(i.element))&&(r=!0)}r&&t.remountIfPresent();for(let i of n)i.root.isConnected&&t.schedule(i,"mutation")}function Ne(t){if(ot)return ot.suppress(t);let e=X("undo");if(e&&e.pause&&e.resume){e.pause();try{return t()}finally{e.resume()}}return t()}function te(t,e){Ht=!0,ot=t,t.subscribe(n=>Tr(e,n))}function ee(t){if(Ht||typeof window>"u"||typeof document>"u")return;let e=X("Mutation");if(e&&typeof e.onAnyChange=="function"){te(Te(e),t);return}typeof MutationObserver=="function"&&(te($r(),t),At=yt(document,Zt,function(){let r=X("Mutation");r&&(At(),At=null,ot&&ot.teardown(),Ht=!1,te(Te(r),t))}))}function Le(){if(ot)try{ot.teardown()}catch{}At&&typeof document<"u"&&At(),ot=null,Ht=!1,At=null}var Nr=new Set(mt);function Et(t,e={}){if(e.breaker){t.diag.error("E26",t.root,{problem:"recompute loop halted after 50 passes; recent triggers: "+(t._breakerRing||[]).join(", ")}),ut(t.root,"loop");return}Ne(()=>Lr(t,e)),t._viewsChanged&&(t._viewsChanged=!1,t.root.dispatchEvent(new CustomEvent("sap:views-updated",{bubbles:!0})))}function Lr(t,e){let n=t.root,r={},i=[],s=[],a=[],R=[],k=[],A=[],f=[],w=new Set;t.diag.errors=[];let N={root:r,state:r,item:null,ownerEl:n,projection:!1};function I(o,p){let l=p.attr||p.name,g=o.getAttribute(l);return g==null&&(g=$t(p),k.push({el:o,name:p.name,attr:l,value:Jt(ct(g,p.type),p.type)})),ct(g,p.type)}function W(o,p){let l=z(o.getAttribute("state")||"");o._sapStateDecls=l;for(let g of l){if(g.transient){p[g.name]=Pt(o,g);continue}if(gt(o,g)){p[g.name]=o.hasAttribute(g.attr);continue}p[g.name]=I(o,g)}}function h(o,p){if(!o.hasAttribute("bind"))return;let l=o.getAttribute("bind"),g=p.item||p.state,L=P(o);L.kind==="radio"?(l in g||(g[l]=""),o.checked&&(g[l]=o.value)):g[l]=L.read(),o.hasAttribute("transient")&&(o.removeAttribute("value"),o.removeAttribute("checked"))}function d(o,p){for(let l of o.attributes){let g=l.name,L=l.value;if(g.startsWith("calc:"))i.push({owner:p.item||p.state,ownerEl:p.ownerEl,name:g.slice(5),entry:H(L),el:o,ctx:p});else if(g==="text"||g.startsWith("text:"))s.push({el:o,kind:"text",fmt:g.includes(":")?g.slice(5):null,entry:H(L),ctx:p});else if(g==="show")s.push({el:o,kind:"show",entry:H(L),ctx:p});else if(g.startsWith("attr:"))s.push({el:o,kind:"attr",arg:g.slice(5),entry:H(L),ctx:p});else if(g.startsWith("class:"))s.push({el:o,kind:"class",arg:g.slice(6),entry:H(L),ctx:p});else if(g.startsWith("css:"))s.push({el:o,kind:"css",arg:g.slice(4),entry:H(L),ctx:p});else if(g==="effect")a.push({el:o,entry:H(L,!0),ctx:p});else if(g==="invalid")R.push({el:o,entry:H(L),ctx:p});else if(g.startsWith("show-when:")||g.startsWith("option:")){let C=g.slice(g.indexOf(":")+1);w.add(C),s.push({el:o,kind:"when",match:"show",field:C,values:L.split("|"),ctx:p})}else if(g.startsWith("hide-when:")){let C=g.slice(g.indexOf(":")+1);w.add(C),s.push({el:o,kind:"when",match:"hide",field:C,values:L.split("|"),ctx:p})}else if(g.startsWith("option-not:")){let C=g.slice(g.indexOf(":")+1);w.add(C),s.push({el:o,kind:"when",match:"show-not",field:C,values:L.split("|"),ctx:p})}}if(o.hasAttribute("bind")&&(p.view||p.projection)&&!Ot(o)){let l=o.getAttribute("bind");p.view?bt(de(p.item),l)?(o._sapViewBind="item",s.push({el:o,kind:"projection",field:l,ctx:p,from:"item"})):l in p.state||l in p.root?(o._sapViewBind="drawn",s.push({el:o,kind:"projection",field:l,ctx:p,from:"drawn"})):(o._sapViewBind=null,t.diag.error("E43",o,{attr:"bind",expr:l,problem:`bind="${l}" inside an each row matches no field of the row's record or of the scope the row is drawn in`,fix:"bind a field the record owns (bind, state= or items= on the [item]), or declare it with state= where the list is drawn"})):s.push({el:o,kind:"projection",field:l,ctx:p})}}function m(o,p,l){Object.defineProperty(o,"$key",{value:Mt(p,"row"),enumerable:!1}),Object.defineProperty(o,"$index",{value:l,enumerable:!1}),Object.defineProperty(o,"$el",{value:p,enumerable:!1})}function y(o,p,l){W(o,p),o._sapScope=p,!l.projection&&o.hasAttribute("bind")&&h(o,l),d(o,l),o.hasAttribute("items")?$(o,p,l):E(o,p,l)}function E(o,p,l){K(o,(g,L)=>{L?g.hasAttribute("scope")?x(g,p,l):g.hasAttribute("items")?(d(g,l),$(g,p,l)):g.hasAttribute("detail")?B(g,p,l):g.hasAttribute("each")&&(d(g,l),f.push({el:g,ctx:l})):(!l.projection&&!l.view&&h(g,l),d(g,l))})}function x(o,p,l){let g=o.getAttribute("scope"),L={};p[g]=L;let C={root:l.root,state:L,item:null,ownerEl:o,projection:l.projection};y(o,L,C)}function $(o,p,l){let g=o.getAttribute("items"),L=[];p[g]=L,o._sapList=L,Z(o).forEach((C,Q)=>{let q={};m(q,C,Q);let rt={root:l.root,state:l.state,item:q,ownerEl:C,projection:l.projection};y(C,q,rt),L.push(q)})}function O(o,p){let l=String(o).split("."),g=C=>{for(let Q of l){if(C==null)return;C=Array.isArray(C)?C.flatMap(q=>q&&q[Q]!=null?q[Q]:[]):C[Q]}return C},L=g(p.state);return L===void 0?g(p.root):L}function B(o,p,l){for(let g of z(o.getAttribute("state")||""))g.name in p||(p[g.name]=gt(o,g)?o.hasAttribute(g.attr):I(o,g));A.push({el:o,parentObj:p,ctx:l})}function c(o,p,l){o._sapScope=p;let g=o.getAttribute("detail")||"",L=/^([\w.]+)\s+by\s+(.+)$/.exec(g);if(!L){o.hidden=!0,o._sapDetailRow=null;return}let C=L[1],Q=L[2].trim(),q=O(C,l),rt;try{rt=J(H(Q),{state:p,item:l.item,el:o,root:l.root})}catch{rt=void 0}let U=Array.isArray(q)&&rt!=null?q.find(V=>V&&typeof V=="object"&&V.$el&&String(V.$key)===String(rt)):null;if(o._sapDetailRow=U?U.$el:null,o.tagName==="DIALOG"){let V=U?String(U.$key):null;if(V!==o._sapDetailKey&&(o._sapDetailKey=V,o._sapDismissed=!1),!U){o._sapOpenedFor=null,o.open&&typeof o.close=="function"&&(o._sapEngineClose=!0,o.close());return}o.open?o._sapOpenedFor=V:(o._sapOpenedFor===V&&(o._sapDismissed=!0),o._sapOpenedFor=null,!o._sapDismissed&&o.isConnected&&typeof o.showModal=="function"&&(o.hidden&&(o.hidden=!1),o.showModal(),o._sapOpenedFor=V))}else{if(!U){o.hidden||(o.hidden=!0);return}o.hidden&&(o.hidden=!1)}let at={root:l.root,state:p,item:U,ownerEl:U.$el,projection:!0};d(o,at),E(o,U,at)}function u(o,p){for(let l=o.parentElement;l;l=l.parentElement)if(l._sapScope===p&&!l.hasAttribute("detail")||l.hasAttribute("sap"))return l;return n}function b(o,p){o._sapDrawnEl=u(o,p.state);let l=[...o.children].find(j=>j.tagName==="TEMPLATE"),g=l&&l.content.children.length===1?l.content.firstElementChild:null;if(!g)return t.diag.error("E42",o,{attr:"each",problem:"each needs one <template> child with exactly one element root"}),0;let L=o.getAttribute("each"),C;try{C=J(H(L),{state:p.state,item:p.item,el:o,root:p.root})}catch(j){return t.diag.error("E24",o,{attr:"each",expr:L,problem:String(j.message)}),0}if(!Array.isArray(C))return t.diag.error("E40",o,{attr:"each",expr:L,problem:"each must evaluate to an array; the list keeps its last good rows"}),0;let Q=H(o.getAttribute("key")||"item.$key"),q=[],rt=new Set;for(let j of C){let G;try{G=J(Q,{state:p.state,item:j,el:o,root:p.root})}catch{G=void 0}let M=G==null?"":String(G);if(M===""||rt.has(M))return t.diag.error("E41",o,{attr:"key",expr:Q.src,problem:M===""?"an item has no key; the list keeps its last good rows":`duplicate key "${M}"; the list keeps its last good rows`}),0;rt.add(M),q.push(M)}let U=o._sapEach||new Map,at=new Map,V=0,Gt=l;q.forEach((j,G)=>{let M=U.get(j);if(!M||M.parentElement!==o){M=o.ownerDocument.importNode(g,!0);let vt=(M.getAttribute("clay")||"").split(/\s+/).filter(Boolean);vt.includes("editor-ui")||M.setAttribute("clay",[...vt,"editor-ui"].join(" ")),M._sapEachRow=!0,V++}M.getAttribute("data-key")!==j&&M.setAttribute("data-key",j),Gt.nextElementSibling!==M&&(Ir(o,M,Gt),V++),M._sapEachItem=C[G],at.set(j,M),Gt=M});for(let[j,G]of U)at.get(j)!==G&&G.parentElement===o&&(G.remove(),V++);return o._sapEach=at,q.forEach((j,G)=>{let M=at.get(j),vt={root:p.root,state:p.state,item:C[G],ownerEl:M,projection:!1,view:!0};d(M,vt),E(M,{},vt)}),V}y(n,r,N);for(let o=0;o<A.length;o++){let{el:p,parentObj:l,ctx:g}=A[o];c(p,l,g)}if(k.length&&w.size)for(let o of k)w.has(o.attr)&&o.el.getAttribute(o.attr)==null&&o.el.setAttribute(o.attr,o.value);let v=new Map;for(let o of i){let p=v.get(o.owner);p||(p={ownerEl:o.ownerEl,list:[]},v.set(o.owner,p)),p.list.push(o)}let S=[...v.values()].sort((o,p)=>Ce(p.ownerEl)-Ce(o.ownerEl));for(let o of S){let p;try{p=Ae(o.list)}catch(l){t.diag.error("E07",o.list[0].el,{problem:l.message}),p=o.list}for(let l of p)try{l.owner[l.name]=J(l.entry,{state:l.ctx.state,item:l.ctx.item,el:l.el,root:l.ctx.root}),Ct(l.el)}catch(g){l.owner[l.name]=void 0,t.diag.error("E24",l.el,{attr:"calc:"+l.name,expr:l.entry.src,problem:String(g.message)}),ut(l.el,g.sapCode||"E24")}}let _=0;for(let o=0;o<f.length;o++)_+=b(f[o].el,f[o].ctx);let T=0,D=_;for(let o of s){let p=Dr(o,t);o.ctx.view?D+=p:T+=p}for(let o of a)Cr(o,t);for(let o of R)Mr(o);t._state=r,t._stats={fields:Object.keys(r).filter(o=>typeof r[o]!="function").length,calcs:i.length,paints:s.length,lists:v.size,writes:T,viewWrites:D},t._viewsChanged=D>0,t._lastPass={trigger:e.trigger||"refresh",writes:T},t._debug&&console.log(`sap pass \xB7 trigger: ${t._lastPass.trigger} \xB7 writes ${T}/${s.length}`)}function Rr(t){return t.kind==="text"?t.fmt?"text:"+t.fmt:"text":t.kind==="attr"?"attr:"+t.arg:t.kind==="class"?"class:"+t.arg:t.kind==="css"?"css:"+t.arg:t.kind==="when"?(t.match==="hide"?"hide-when:":t.match==="show-not"?"option-not:":"show-when:")+t.field:t.kind}function re(t,e,n,r){let i=t;for(;i&&i.nodeType===1;){if(i.hasAttribute&&i.hasAttribute(e)){let s=n.includes(i.getAttribute(e));if(r?!s:s)return!0}i=i.parentElement}return!1}function Re(t,e){if(t===t.ownerDocument.activeElement)return 0;if(t.type==="radio"){let s=e!=null&&String(t.value)===String(e);return t.checked===s?0:(t.checked=s,1)}let n=P(t),r=n.read(),i=e??"";return String(r)!==String(i)?(n.write(i,{silent:!0}),1):0}function Dr(t,e){if(t.kind==="projection"){if(t.from==="drawn"){let r=t.field in t.ctx.state?t.ctx.state:t.ctx.root;return Re(t.el,r[t.field])}return Re(t.el,t.ctx.item?t.ctx.item[t.field]:"")}if(t.kind==="when")return De(t,null);let n={state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root};try{let r=J(t.entry,n),i=De(t,r);return Ct(t.el),i}catch(r){return e.diag.error(r.sapCode==="E22"?"E22":"E24",t.el,{attr:Rr(t),expr:t.entry&&t.entry.src,problem:String(r.message)}),ut(t.el,r.sapCode||"E24"),0}}function De(t,e){let n=t.el;switch(t.kind){case"text":{let r=t.fmt!=null?be(t.fmt,e):e==null?"":String(e);return n.textContent!==r?(n.textContent=r,1):0}case"show":{let r=!e;return n.hidden!==r?(n.hidden=r,1):0}case"when":{let r=X("optionVisibility");if(r&&r._started)return n._sapWhen&&n.hidden?(n.hidden=!1,n._sapWhen=!1,1):0;let i;t.match==="hide"?i=!re(n,t.field,t.values,!1):t.match==="show-not"?i=re(n,t.field,t.values,!0):i=re(n,t.field,t.values,!1),n._sapWhen=!0;let s=!i;return n.hidden!==s?(n.hidden=s,1):0}case"attr":{let r=t.arg;if((r==="checked"||r==="selected")&&typeof n[r]=="boolean"&&!n.hasAttribute("bind")&&!n.closest("select[bind]")){let s=0;return n[r]!==!!e&&(n[r]=!!e,s=1),!!e!==n.hasAttribute(r)&&(e?n.setAttribute(r,""):n.removeAttribute(r),s=1),s}if(Nr.has(r)){let s=n.hasAttribute(r);return e&&!s?(n.setAttribute(r,""),1):!e&&s?(n.removeAttribute(r),1):0}let i=typeof e=="boolean"?String(e):e==null?"":String(e);return n.getAttribute(r)!==i?(n.setAttribute(r,i),1):0}case"class":{let r=!!e;return n.classList.contains(t.arg)!==r?(n.classList.toggle(t.arg,r),1):0}case"css":{let r=e==null?"":String(e);return n.style.getPropertyValue("--"+t.arg)!==r?(n.style.setProperty("--"+t.arg,r),1):0}default:return 0}}function Cr(t,e){try{J(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root}),Ct(t.el)}catch(n){e.diag.error("E24",t.el,{attr:"effect",expr:t.entry&&t.entry.src,problem:String(n.message)}),ut(t.el,"E24")}}function Mr(t){let e="";try{let n=J(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root});e=typeof n=="string"?n:""}catch{e=""}typeof t.el.setCustomValidity=="function"&&t.el.setCustomValidity(e)}function Ce(t){let e=0,n=t;for(;n&&!(n.hasAttribute&&n.hasAttribute("sap"));)n=n.parentElement,e++;return e}function Ir(t,e,n){let r=n.nextSibling;if(e.isConnected&&t.moveBefore)try{t.moveBefore(e,r);return}catch{}t.insertBefore(e,r)}var Or=new Set(mt),Me=new Set(["calc","text","attr","class","css","set","move","sort","option","option-not","show-when","hide-when","editmode"]),Fr=new Set(["show-when","hide-when","option","option-not"]),Pr=/\b(?:state|item|root)\.|===|!==|&&|\|\||[()]|^\s*!/,Ie=new Set(["sap","scope","items","item","template","bind","show","effect","invalid","detail","state","transient","confirm","default","persist","sortable","trigger-add","trigger-remove","trigger-reset","sap-ignore","sap-error","no-save","no-watch","no-undo","no-trigger-autosave","freeze","mutations-ignore","save-remove","save-ignore","save-freeze"]);function Wr(t){return t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA"}function ne(t){return t.hasAttribute("bind")}function Br(t,e){e(t);for(let r of t.children)n(r);function n(r){if(r.nodeType===1&&!r.hasAttribute("sap-ignore")){if(r.tagName==="TEMPLATE"){if(r.hasAttribute("items"))for(let i of r.content.children)n(i);return}e(r);for(let i of r.children)n(i)}}}function jt(t,e){let n=!1,r=(a,R,k)=>{e.error(a,R,k),n=!0},i=t.ownerDocument.createTreeWalker(t,4),s;for(;s=i.nextNode();)if(/\{\{.*\}\}/.test(s.nodeValue||"")){r("E02",s.parentElement||t,{problem:"moustaches in text content are not a Sap feature",fix:'move the expression onto the element: text="state.x"'});break}return Br(t,a=>{let R=a.closest&&a.closest("[detail]");for(let k of[...a.attributes]){let A=k.name,f=ce(A);if(f){r("E01",a,{attr:A,expr:k.value,problem:`"${A}" is a foreign-dialect attribute; Sap has no ${A.split(/[:=]/)[0]} directive`,fix:f+" \u2014 or wrap the subtree in sap-ignore if intentional"});continue}if(A.includes(":")){let N=A.slice(0,A.indexOf(":"));if(Me.has(N)){if(Fr.has(N)&&Pr.test(k.value)){let I=A.slice(A.indexOf(":")+1);e.warn("W04",a,{attr:A,expr:k.value,problem:`${N}: compares the "${I}" attribute against a literal value, not a JS expression`,fix:`use show="${k.value}" for an expression, or a literal like ${N}:${I}="overview"`})}}else{let I=xt(N,[...Me]);e.warn("W03",a,{attr:A,problem:`unknown "${N}:" attribute`,didYouMean:I?`${I}:`:null})}}else if(!Ie.has(A)&&!St.has(A)&&!Or.has(A)&&!/^(data-|aria-|on)/.test(A)&&!(A in a)){let N=xt(A,[...Ie]);N&&e.warn("W03",a,{attr:A,problem:`unknown "${A}" attribute`,didYouMean:N})}A==="attr:hidden"&&e.warn("W03",a,{attr:A,problem:"attr:hidden paints the wrong attribute",fix:'use show="expr"'});let w=ne(a)||A==="attr:selected"&&a.tagName==="OPTION"&&!!a.closest("select[bind]");(A==="attr:value"||A==="attr:checked"||A==="attr:selected")&&w&&r("E30",a,{attr:A,problem:"attr: on a bound control collides with persist ownership",fix:"remove it; bind owns this attribute"}),A==="effect"&&ne(a)&&/\b(value|checked)\s*=[^=]/.test(k.value)&&r("E30",a,{attr:A,expr:k.value,problem:"effect writes value/checked on a bound control (writes a stale value with no synthetic event)",fix:"write through onclick + Sap(this) instead"}),(A==="text"||A.startsWith("text:")||A==="show")&&Wr(a)&&(A==="show"||r("E18",a,{attr:A,problem:"paint belongs on output elements, not form controls",fix:"move the paint to an <output> or <span>"}))}if(a.hasAttribute("state")){let k=z(a.getAttribute("state")),A=new Set;for(let f of k){f.name.includes("-")&&r("E08",a,{attr:"state",problem:`field "${f.name}" is not a valid identifier (the hyphen parses as subtraction)`,fix:`rename to ${f.name.replace(/-/g,"")}`}),A.has(f.name)&&r("E04",a,{attr:"state",problem:`field "${f.name}" is declared twice in one scope`}),A.add(f.name),Rt.has(f.attr)&&r("E05",a,{attr:"state",problem:`"${f.name}" is a reserved Sap word`}),St.has(f.attr)&&r("E06",a,{attr:"state",problem:`"${f.name}" is a global HTML attribute name; pick another field name`}),f.name==="open"&&a.tagName==="DIALOG"&&r("E33",a,{attr:"state",problem:"dialog open is transient",fix:"use showModal() \u2014 declare state= only on <details> or popovers"});let w=Qt(a,f.attr);w&&(f.attr==="checked"||f.attr==="selected")&&r("E35",a,{attr:"state",problem:`"${f.attr}" on a form control is the control's own state, not a declared field`,fix:'bind the control instead, e.g. <input type="checkbox" bind="done">'}),w&&f.type==="num"&&r("E35",a,{attr:"state",problem:`"${f.attr}" is an HTML boolean attribute; it cannot hold a number`,fix:`declare it bare: state="${f.attr}"`}),f.transient&&(w||f.type==="presence")&&r("E35",a,{attr:"state",problem:`"${f.name}" is carried by attribute presence, which transient would strip`,fix:"declare a separate name:bool:transient field and paint the attribute from it"})}}if(ne(a)){if(a.hasAttribute("-"),a.tagName==="INPUT"){let k=(a.getAttribute("type")||"text").toLowerCase();k==="file"&&r("E32",a,{attr:"bind",problem:"files never serialize into an HTML file",fix:"use no-save + effect instead of bind"}),k==="password"&&!a.hasAttribute("transient")&&r("E31",a,{attr:"bind",problem:"a password must never serialize into a world-readable file",fix:"add transient to the password input"})}else if(a.tagName!=="SELECT"&&a.tagName!=="TEXTAREA"){let k=a.getAttribute("contenteditable");!(k!=null&&k!=="false")&&a.children.length>0&&r("E20",a,{attr:"bind",problem:"bind on a container element is not a control; a write would overwrite its children",fix:"bind a control (input/select/textarea), a contenteditable, or an empty text leaf"})}}if(a.hasAttribute("transient")&&a.hasAttribute("persist")&&r("E34",a,{problem:"transient and persist are opposite: persist forces the live value into the saved bytes, leaking exactly what transient drops",fix:"remove one \u2014 transient to keep it out of the file, or persist to save it"}),a.tagName==="DIALOG"&&a.hasAttribute("detail")&&!(a.parentElement&&a.parentElement.closest('[clay~="freeze"], [freeze], [save-freeze]'))&&e.warn("W31",a,{attr:"detail",problem:"a detail dialog writes open when it opens, and that attribute would be saved into the file",fix:'wrap the dialog in an element with clay="freeze" (not editor-ui, which removes it from the file), and make its key field transient'}),a.hasAttribute("item")&&!a.hasAttribute("template")&&a.parentNode&&a.parentNode.nodeType===1){let k=a.parentElement;(!k||!k.hasAttribute("items"))&&r("E10",a,{problem:"an [item] must be a direct child of an [items] list",fix:'wrap it in a container with items="name"'})}if(a.hasAttribute("items")&&R&&r("E17",a,{attr:"items",problem:"nested items inside a detail panel is a v1 mount error (nested collections ship in v1.1)"}),a.hasAttribute("items")){let k=t.querySelector(`[trigger-add="${a.getAttribute("items")}"]`);!Ft(a)&&!Kt(t,a.getAttribute("items"))&&Z(a).length===0&&k&&r("E17",a,{attr:"items",problem:`trigger-add targets items="${a.getAttribute("items")}" but it has no [item template] to clone`})}}),n&&(e.halted=!0,e.haltReason=e.errors[0]?e.errors[0].code:"halt",ut(t,e.haltReason)),!n}var Oe="sap-styles",Fe="[item][template]{display:none!important}[hidden]{display:none!important}[sap-error]{outline:2px solid #e5484d;outline-offset:1px}",oe=new WeakSet;function qr(t){if(oe.has(t))return;let e=t.defaultView,n=e&&e.CSSStyleSheet;if(n&&"adoptedStyleSheets"in t)try{let r=new n;r.replaceSync(Fe),t.adoptedStyleSheets=[...t.adoptedStyleSheets,r],oe.add(t);return}catch{}if(!t.getElementById(Oe)){let r=t.createElement("style");r.id=Oe,r.textContent=Fe,(t.head||t.documentElement).appendChild(r)}oe.add(t)}var Vr=0;function Pe(){return typeof performance<"u"&&performance.now?performance.now():0}function ie(t){let e=t.id||t.getAttribute("sap")||`app-${Vr++}`,n=new pt(e),r={root:t,name:e,diag:n,_state:null,_stats:null,_lastPass:null,_passes:0,_broken:!1,_mountMs:0,_mountWrites:0};if(!jt(t,n))return r.halted=!0,r;qr(t.ownerDocument);for(let a of t.querySelectorAll("textarea[data-value]"))qt(a);let s=Pe();return Et(r,{trigger:"mount"}),r._mountMs=Pe()-s,r._mountWrites=r._stats?r._stats.writes:0,r._mountWrites>0&&n.warn("W30",t,{problem:`${r._mountWrites} paint(s) ran at mount; the saved file was out of sync with its declared state`,fix:"re-save once so the file mounts clean (a settled file writes nothing)"}),r}var zr=["for","form","list","headers","popovertarget","commandfor","anchor","aria-activedescendant","aria-controls","aria-describedby","aria-details","aria-errormessage","aria-flowto","aria-labelledby","aria-owns"];function Hr(t,e){let n=null;return K(t,r=>{!n&&r.getAttribute("scope")===e&&(n=r)}),n}function We(t,e,n){let r=Y(t)||e;for(;r;){for(let i of z(r.getAttribute("state")||""))if(i.name===n)return{el:r,decl:i};if(r.hasAttribute("sap"))break;r=Y(r.parentElement)}return null}function jr(t){return typeof t=="number"?"num":typeof t=="boolean"?"bool":"string"}function Be(t){function e(h){let d=t.appFor(h);if(!d)return null;let m=ft(h),y=m&&m._sapEachItem&&m._sapEachItem.$el;if(y&&y.isConnected)return{ctxEl:y,appRec:d,isRow:!0};let E=kt(h);if(E)return E._sapDetailRow?{ctxEl:E._sapDetailRow,appRec:d,isRow:!0}:{ctxEl:Y(E.parentElement)||d.root,appRec:d,isRow:!1};let x=It(h);if(x&&x.hasAttribute("item"))return{ctxEl:x,appRec:d,isRow:!0};let $=Y(h)||d.root;return{ctxEl:$,appRec:d,isRow:$.hasAttribute("item")}}function n(h){let d=typeof h=="string"?document.querySelector(h):h;if(!d||d.nodeType!==1)return null;let m=e(d);return m?W(m.ctxEl,m.appRec,m.isRow):null}function r(h,d){let m=ft(h);if(!m)return n(h);let y=t.appFor(h),E=m._sapEachItem&&m._sapEachItem.$el;if(E&&E.nodeType===1&&E.hasAttribute("item")&&bt(E,d))return E.isConnected?W(E,y,!0):null;let x=m.parentElement&&m.parentElement._sapDrawnEl;return!x||!x.isConnected?null:W(x,y,x.hasAttribute("item"))}function i(h,d,m){let y=lt(h,m);if(y)return P(y).read();let E=ht(h,m);if(E)return Z(E).map(B=>W(B,d,!0));let x=Hr(h,m);if(x)return W(x,d,!1);let $=We(h,d.root,m);if($)return $.decl.transient?Pt($.el,$.decl):pe($.el,$.decl);let O=h._sapScope;return O?O[m]:void 0}function s(h,d,m,y,E){y.transient?Tt(h,y,m):_t(h,y,m),t.schedule(E,"set:"+d)}function a(h,d){let m=new Set,y=Y(h)||d;for(;y;){for(let E of z(y.getAttribute("state")||""))m.add(E.name);if(y.hasAttribute("sap"))break;y=Y(y.parentElement)}return K(h,E=>{let x=E.getAttribute("bind");x&&m.add(x)}),m}function R(h,d,m,y){let E=lt(h,m);if(E){P(E).write(y);return}let x=h;for(;x;){for(let S of x.attributes)if(S.name==="calc:"+m){d.diag.error("E16",x,{attr:"calc:"+m,problem:`"${m}" is a computed field; computed fields are read-only`});return}if(x.hasAttribute("sap"))break;x=x.parentElement}let $=We(h,d.root,m);if($){s($.el,m,y,$.decl,d);return}let O=a(h,d.root);O.delete(m);let B=m.length>=4?xt(m,[...O]):null;if(B){d.diag.error("E12",h,{key:m,problem:`unknown state key "${m}"`,didYouMean:B});return}if(Rt.has(m)||St.has(m)){d.diag.error("E15",h,{key:m,problem:`cannot write undeclared field "${m}" \u2014 it is a reserved/global name and cannot become state`,fix:"pick a different field name, or declare it explicitly in a state= attribute"});return}let c=d.root,u=jr(y),b=c.getAttribute("state")||"",v=u==="string"?m:`${m}:${u}`;c.setAttribute("state",b?`${b} ${v}`:v),s(c,m,y,{name:m,attr:m,type:u,transient:!1},d)}function k(h){let d=h.ownerDocument,m=new Map,y=(E,x)=>{let $=le(d),O=E.getAttribute(x);O&&x==="id"&&m.set(O,$),E.setAttribute(x,$)};h.querySelectorAll("[id]").forEach(E=>y(E,"id")),h.querySelectorAll("[data-id]").forEach(E=>y(E,"data-id")),h.querySelectorAll("[sap-error]").forEach(E=>E.removeAttribute("sap-error")),h.removeAttribute("sap-error"),h.hasAttribute("data-id")?(h.removeAttribute("id"),y(h,"data-id")):y(h,"id");for(let E of[h,...h.querySelectorAll("*")])for(let x of zr){let $=E.getAttribute(x);if($==null)continue;let O=$.split(/\s+/).map(B=>m.get(B)||B).join(" ");O!==$&&E.setAttribute(x,O)}}function A(h,d,m){let y=Nt(d.root,h,m);if(!y)return d.diag.error("E17",h,{problem:`cannot resolve a list named "${m}" from here`}),null;let E=Ft(y);if(!E)return d.diag.error("E17",y,{problem:`items="${m}" has no [item template] to clone`}),null;let x=y.ownerDocument.importNode(E,!0);return x.removeAttribute("template"),k(x),y.appendChild(x),t.schedule(d,"trigger-add:"+m),W(x,d,!0)}function f(h,d){K(h,m=>{if(m.hasAttribute("bind")){let y=P(m),E=m.getAttribute("default");y.kind==="checkbox"||y.kind==="radio"?y.write(E!=null?E===""||E==="true"||m.value===E:m.hasAttribute("checked")):y.write(E??(m.getAttribute("value")||""))}});for(let m of z(h.getAttribute("state")||"")){let y=me(h,m);m.transient?Tt(h,m,y):_t(h,m,y)}t.schedule(d,"trigger-reset")}function w(h,d){if(!h.isConnected)throw new Error("stale row handle: $remove() on a removed row");h.remove(),t.schedule(d,"trigger-remove")}function N(h,d,m){if(!h.isConnected)throw new Error("stale row handle: $move() on a removed row");let y=null;if(m&&m.nodeType===1?y=m:typeof m=="string"&&(y=Nt(d.root,h,m)),!y){d.diag.error("E17",h,{problem:`$move() cannot resolve target "${m}"`});return}t.moveInto(y,h),t.schedule(d,"trigger-move")}function I(h){let d=h.parentElement;return d?Z(d).indexOf(h):-1}function W(h,d,m){let y={get $el(){return h},get $key(){return Mt(h,m?"row":"scope")},get $index(){return I(h)},$add(x){return A(h,d,x)},$reset(){return f(h,d),E},$remove(){w(h,d)},$move(x){N(h,d,x)},get $appRec(){return d}},E=new Proxy(y,{get(x,$){return typeof $=="symbol"||$[0]==="$"?x[$]:i(h,d,$)},set(x,$,O){return typeof $=="string"&&$[0]==="$"?(x[$]=O,!0):(R(h,d,$,O),!0)},has(x,$){return typeof $=="string"&&$[0]==="$"?$ in x:i(h,d,$)!==void 0}});return E}return{Sap:n,contextElFor:e,readField:i,writeField:R,makeProxy:W,writeTargetFor:r}}var Ur=["trigger-add","trigger-remove","trigger-reset"];function Gr(t){if(t.nodeType!==1)return!1;for(let e of t.attributes){let n=e.name;if(n.startsWith("set:")||n.startsWith("move:")||n.startsWith("sort:")||Ur.includes(n))return!0}return!1}function Yr(t,e){let n=t,r=e.parentElement;for(;n&&n!==r;){if(n.nodeType===1&&Gr(n)&&!(n.tagName==="FORM"&&n.hasAttribute("trigger-add")))return n;n=n.parentElement}return null}function qe(t,e){let{Sap:n}=e;function r(c,u){let b=null,v=ft(c),S=kt(c);if(v)b=v._sapEachItem??null;else if(S&&S._sapDetailRow)b=S._sapDetailRow._sapScope||null;else{let D=It(c);D&&D.hasAttribute("item")&&(b=D._sapScope||null)}return{state:(Y(c)||u.root)._sapScope||u._state||{},item:b,el:c,root:u._state||{}}}function i(c,u,b){if(!c.hasAttribute("confirm")){b();return}let v=c.getAttribute("confirm"),S=v,_=H(v);if(!_.error)try{let o=J(_,r(c,u));(typeof o=="string"||typeof o=="number")&&(S=String(o))}catch{}let T=xe();if(!T){window.confirm(S)&&b();return}if(c._sapGatePending)return;c._sapGatePending=!0;let D=()=>{c._sapGatePending=!1};T(S,()=>{D(),b()}).catch(D)}function s(c,u){for(let b of c.attributes){if(!b.name.startsWith("set:"))continue;let v=b.name.slice(4),S=H(b.value);if(S.error){u.diag.error("E08",c,{attr:b.name,expr:b.value,problem:String(S.error.message)});continue}let _;try{_=J(S,r(c,u))}catch(D){u.diag.error("E24",c,{attr:b.name,expr:b.value,problem:String(D.message)});continue}let T=e.writeTargetFor(c,v);T&&(T[v]=_)}}function a(c){let u=ft(c);if(!u)return c.closest("[item]");let b=u._sapEachItem&&u._sapEachItem.$el;return b&&b.nodeType===1&&b.hasAttribute("item")?b:null}function R(c,u){let b=a(c);if(!b)return;let v=Z(b.parentElement),S=v.indexOf(b);u==="up"&&S>0?t.placeBefore(b,v[S-1]):u==="down"&&S<v.length-1&&t.placeBefore(v[S+1],b)}function k(c,u,b){if(u)return Nt(b.root,c,u);let v=c;for(;v;){if(v.hasAttribute&&v.hasAttribute("items"))return v;v=v.parentElement}let S=Y(c)||b.root,_=[];return K(S,T=>{T.hasAttribute("items")&&_.push(T)}),_[0]||null}function A(c,u){let b=c==null||c==="",v=u==null||u==="";if(b&&v)return 0;if(b)return 1;if(v)return-1;let S=Number(c),_=Number(u);return!Number.isNaN(S)&&!Number.isNaN(_)?S-_:String(c)<String(u)?-1:String(c)>String(u)?1:0}function f(c,u,b,v){let S=k(c,b,v);if(!S){v.diag.error("E17",c,{attr:"sort:"+u,problem:`no items list resolvable for sort:${u}`});return}let _=Z(S),T=l=>l._sapScope?l._sapScope[u]:void 0,D=[..._].sort((l,g)=>A(T(l),T(g))),p=D.every((l,g)=>l===_[g])?[...D].reverse():D;for(let l of p)t.moveInto(S,l);t.schedule(v,"sort:"+u)}function w(c){if(!c||c.hidden)return;let u=c.querySelector("[bind]:not([type=hidden]), [contenteditable]");u&&typeof u.focus=="function"&&u.focus()}function N(c,u){i(c,u,()=>{let b=n(c);for(let v of[...c.attributes]){let S=v.name;if(S==="trigger-remove")b&&b.$remove();else if(S==="trigger-reset")b&&b.$reset();else if(S==="trigger-add"){let _=b&&b.$add(v.value);_&&w(_.$el)}else S==="move:up"?(R(c,"up"),t.schedule(u,"move:up")):S==="move:down"?(R(c,"down"),t.schedule(u,"move:down")):S.startsWith("move:to")?b&&b.$move(v.value):S.startsWith("sort:")&&f(c,S.slice(5),v.value,u)}[...c.attributes].some(v=>v.name.startsWith("set:"))&&s(c,u)})}function I(c){let u=c.target;if(!u||u.nodeType!==1)return;let b=t.appFor(u);if(!b)return;let v=Yr(u,b.root);v&&N(v,b)}function W(c){let u=P(c),b=c.getAttribute("default");u.kind==="checkbox"?u.write(b===""||b==="true"):u.write(b??"")}function h(c,u,b){let v=n(c);if(!v)return;let S=v.$add(b);if(!S)return;let _=[];K(c,T=>{T.hasAttribute("bind")&&_.push(T)});for(let T of _){if(T.type==="radio"&&!T.checked)continue;let D=T.getAttribute("bind"),o=lt(S.$el,D);o?P(o).write(P(T).read()):bt(S.$el,D)&&(S[D]=P(T).read())}_.forEach(W),_.length?typeof _[0].focus=="function"&&_[0].focus():w(S.$el)}function d(c){let u=c.target;if(!u||!u.hasAttribute||!u.hasAttribute("trigger-add"))return;let b=t.appFor(u);b&&(c.preventDefault(),i(u,b,()=>h(u,b,u.getAttribute("trigger-add"))))}function m(c){let u=c.target,b=t.appFor(u);b&&setTimeout(()=>{u.querySelectorAll("[bind]").forEach(v=>{v.dispatchEvent(new Event("input",{bubbles:!0})),v.dispatchEvent(new Event("change",{bubbles:!0}))}),t.schedule(b,"reset")},0)}function y(c){let u=t.appFor(c.target);u&&t.schedule(u,"toggle")}function E(c){let u=c.target;if(!u||u.tagName!=="DIALOG"||!u.hasAttribute("detail"))return;if(u._sapEngineClose){u._sapEngineClose=!1;return}if(u.open)return;let b=/^[\w.]+\s+by\s+state\.(\w+)\s*$/.exec(u.getAttribute("detail")||""),v=t.appFor(u);if(!b||!v)return;let S=z(u.getAttribute("state")||"").find(T=>T.name===b[1]);if(S){S.transient?Tt(u,S,""):_t(u,S,""),t.schedule(v,"close");return}let _=n(u.parentElement);_&&_[b[1]]!==""&&(_[b[1]]="")}function x(c){let u=c.target;if(!u||u.nodeType!==1)return;let b=t.appFor(u);if(!b)return;u.hasAttribute("persist")&&!Vt(u)&&wt(u);let v=u.hasAttribute("bind")&&Ot(u);if(!v&&u.hasAttribute("bind")&&ft(u)){let _=u.getAttribute("bind"),T=u._sapViewBind?e.writeTargetFor(u,_):null;T&&(T[_]=P(u).read());return}let S=kt(u);if(S&&S._sapDetailRow&&u.hasAttribute("bind")&&!v){let _=S._sapDetailRow,T=u.getAttribute("bind"),D=lt(_,T);if(D&&D!==u){P(D).write(P(u).read());return}if(!D&&z(_.getAttribute("state")||"").some(o=>o.name===T)){e.writeField(_,b,T,P(u).read());return}}t.schedule(b,c.type+" "+(u.id||u.tagName.toLowerCase()))}function $(c){let u=c.detail||{};for(let b of[u.from,u.to,c.target]){if(!b||b.nodeType!==1)continue;let v=t.appFor(b);v&&t.schedule(v,"sorted")}}function O(c){if(c.key!=="ArrowUp"&&c.key!=="ArrowDown")return;let u=c.target;if(!u||u.nodeType!==1||u.tagName!=="INPUT"||!u.hasAttribute("bind")||!u.hasAttribute("step"))return;let b=(u.getAttribute("type")||"text").toLowerCase();if(b!=="text"&&b!=="tel"&&b!=="search"||!t.appFor(u))return;c.preventDefault();let S=tt(u.getAttribute("step"))||1,_=c.key==="ArrowUp"?1:-1,T=tt(u.value)+S*(c.shiftKey?10:1)*_,D=u.getAttribute("min"),o=u.getAttribute("max");D!==null&&D!==""&&T<tt(D)&&(T=tt(D)),o!==null&&o!==""&&T>tt(o)&&(T=tt(o)),P(u).write(String(Number(T.toFixed(2))))}function B(c=document){c.addEventListener("click",I),c.addEventListener("submit",d),c.addEventListener("reset",m),c.addEventListener("toggle",y,!0),c.addEventListener("close",E,!0),c.addEventListener("input",x),c.addEventListener("change",x),c.addEventListener("clay:sorted",$),c.addEventListener("keydown",O)}return{install:B}}var Ve=/^(set:|move:|sort:|trigger-add$|trigger-remove$|trigger-reset$)/;function se(t){return`${t.tagName.toLowerCase()}[sap]`}function Xr(t){let e=0;for(let n of t.querySelectorAll("*"))for(let r of n.attributes)if(Ve.test(r.name)){e++;break}for(let n of t.attributes)if(Ve.test(n.name)){e++;break}return e}function ze(t){let e=[],n=r=>{for(let i of r.attributes){let s=i.name;(s.startsWith("calc:")||s==="text"||s.startsWith("text:")||s==="show"||s.startsWith("attr:")||s.startsWith("class:")||s.startsWith("css:")||s==="effect"||s==="invalid"||s.startsWith("set:")||s==="detail")&&e.push({el:r,attr:s,src:i.value})}};n(t);for(let r of t.querySelectorAll("*"))n(r);return e}function He(t){function e(f){let w=f._stats||{},N=f.root;return{root:se(N),fields:w.fields||0,calcs:w.calcs||0,paints:w.paints||0,actions:Xr(N),lists:(N.hasAttribute("items")?1:0)+N.querySelectorAll("[items]").length,rows:N.querySelectorAll("[item]:not([template])").length,warnings:f.diag.warnings.length,errors:f.diag.errors.length,mountWrites:f._mountWrites||0,ms:Math.round((f._mountMs||0)*10)/10,passes:f._passes||0,lastPass:f._lastPass||null,ok:f.diag.errors.length===0&&!f.halted}}function n(){let f=t.apps().map(e);return{ok:f.every(w=>w.ok),apps:f}}function r(f){let w=e(f);return w.ok?`sap \u2713 ${w.root} \xB7 fields ${w.fields} \xB7 calcs ${w.calcs} \xB7 paints ${w.paints} \xB7 actions ${w.actions} \xB7 lists ${w.lists} \xB7 rows ${w.rows} \xB7 warnings ${w.warnings} \xB7 mount writes ${w.mountWrites} \xB7 ${w.ms}ms`:`sap \u2717 ${w.root} \xB7 errors ${w.errors} \xB7 warnings ${w.warnings} \xB7 ${w.ms}ms`}function i(){for(let f of t.apps()){let w=r(f);f.diag.errors.length||f.halted?console.error(w):console.log(w)}}function s(){let f=[],w=[];for(let N of t.apps())f.push(...N.diag.errors),w.push(...N.diag.warnings);return{ok:f.length===0,errors:f,warnings:w,counts:{errors:f.length,warnings:w.length}}}function a(f){return f?typeof f=="string"?document.querySelector(f):f.nodeType===1?f:null:null}function R(f,w){let N=a(f);if(!N)return console.warn("sap why: element not found"),null;let I=[`sap why <${N.tagName.toLowerCase()}> \u2014 ${Dt(N)}`],W=[...N.attributes].filter(d=>/^(bind|text|show|effect|invalid|detail|calc:|text:|attr:|class:|css:|set:|state|items|scope)/.test(d.name));for(let d of W)I.push(` ${d.name}="${d.value}"`);let h=N;for(;h&&!h._sapScope;)h=h.parentElement;if(h&&h._sapScope){let d=h._sapScope,m=w?[w]:Object.keys(d);I.push(" reads:");for(let y of m){let E=d[y];typeof E!="function"&&I.push(` ${y} = ${JSON.stringify(Array.isArray(E)?`[${E.length} rows]`:E)}`)}}return I.push(" serialization: textContent and value/checked attributes save with the file; reads live from properties"),console.log(I.join(`
|
|
10
|
+
`)),null}function k(f){let w=f===void 0?!0:!!f;for(let N of t.apps())N._debug=w;return console.log(`sap debug ${w?"on":"off"} \u2014 per-pass headers will ${w?"":"no longer "}log`),w}function A(){let f=[],w=0;for(let d of t.apps()){let m=d.root,y=se(m);w++;let E=new pt(d.name);jt(m,E);for(let c of E.errors)f.push({code:c.code,severity:"error",message:`${y}: ${c.code} ${c.slug} at ${c.el}`});for(let c of E.warnings)f.push({code:c.code,severity:"warn",message:`${y}: ${c.code} ${c.slug} at ${c.el}`});w++,Et(d,{trigger:"doctor-dryrun"});let x=d._stats?d._stats.writes:0;x>0&&f.push({code:"W30",severity:"warn",message:`${y}: dry recompute wrote ${x} cells on a quiet page; an element is stale or non-idempotent`}),w++;let $=ze(m).map(c=>c.src).join(" \0 "),O=[];for(let c of[m,...m.querySelectorAll("[state]")])for(let u of z(c.getAttribute("state")||""))O.push(u.name);for(let c of O)new RegExp(`(state|item)\\.${c}\\b`).test($)||f.push({code:"I33",severity:"info",message:`${y}: field "${c}" is declared but read nowhere (dead state)`});w++;let B=new Map;for(let c of m.querySelectorAll("[id]"))B.set(c.id,(B.get(c.id)||0)+1);for(let[c,u]of B)u>1&&f.push({code:"W32",severity:"warn",message:`${y}: duplicate id "${c}" (${u} elements) \u2014 clone/edit collision`});w++;for(let c of ze(m))c.src.length>120&&f.push({code:"I33",severity:"info",message:`${y}: ${c.attr} expression is ${c.src.length} chars; consider a calc: field`});w++;for(let c of m.querySelectorAll("[text], [text\\:num]")){let u=c.textContent||"";/\.\d{5,}/.test(u)&&f.push({code:"I33",severity:"info",message:`${y}: ${Dt(c)} paints >4 decimals; consider text:FMT`})}}let N=f.filter(d=>d.severity==="error").length,I=f.filter(d=>d.severity==="warn").length,W=f.filter(d=>d.severity==="info").length;console.log(`sap doctor \xB7 ${t.apps().map(d=>se(d.root)).join(", ")} \xB7 errors ${N} \xB7 warnings ${I} \xB7 info ${W} \xB7 ${w} checks \xB7 0ms`);for(let d of f)(d.severity==="error"?console.error:d.severity==="warn"?console.warn:console.info)(` ${d.severity==="error"?"\u2717":d.severity==="warn"?"\u26A0":"\xB7"} ${d.message}`);return f}return{status:n,report:s,why:R,debug:k,doctor:A,greenLine:r,printGreenLines:i,REGISTRY:Xt}}var je="0.5.0";var et=new Map,it=[],ae=ue(Et);function Kr(t){let e=t;for(;e;){if(e.nodeType===1&&e.hasAttribute&&e.hasAttribute("sap"))return et.get(e)||null;e=e.parentNode&&e.parentNode.host?e.parentNode.host:e.parentElement}return null}function Jr(){for(let t=it.length-1;t>=0;t--){let e=it[t];e.root.isConnected||(et.delete(e.root),it.splice(t,1))}}function Qr(t,e){if(t.moveBefore)try{t.moveBefore(e,null);return}catch{}t.appendChild(e)}function Zr(t,e){let n=e.parentElement;if(n){if(n.moveBefore)try{n.moveBefore(t,e);return}catch{}n.insertBefore(t,e)}}var dt={apps:()=>it.slice(),appFor:Kr,isRegistered:t=>et.has(t),pruneDisconnected:Jr,schedule:(t,e)=>ae.schedule(t,e),runNow:(t,e)=>ae.runNow(t,e),moveInto:Qr,placeBefore:Zr,remountIfPresent:()=>Ut()},Ge=Be(dt),tn=qe(dt,Ge),st=He(dt),Ue=!1;function Ye(){Ue||(Ue=!0,tn.install(document),$e(dt))}function Ut(t=document){Ye(),ee(dt);let e=t.querySelectorAll("[sap]"),n=[];for(let r of e){if(et.has(r))continue;let i=ie(r);et.set(r,i),it.push(i),n.push(i)}for(let r of n){let i=st.greenLine(r);r.diag.errors.length||r.halted?console.error(i):console.log(i)}return n}function Xe(t){if(Ye(),ee(dt),!t)return Ut();let e=typeof t=="string"?document.querySelector(t):t;if(!e)return null;if(et.has(e))return et.get(e);let n=ie(e);et.set(e,n),it.push(n);let r=st.greenLine(n);return n.diag.errors.length||n.halted?console.error(r):console.log(r),n}var F=Ge.Sap;F.version=je;F.refresh=function(){for(let e of it)e.root.isConnected&&ae.runNow(e,"refresh")};F.batch=ke;F.status=st.status;F.report=st.report;F.why=st.why;F.debug=st.debug;F.doctor=st.doctor;F.greenLine=st.greenLine;F.formats=Lt;F.serializeControlToAttributes=wt;F.finalizeControlForSave=ve;F.rehydrateControlFromAttributes=qt;F.mount=Xe;F.config=function(e={}){return e.formats&&Object.assign(Lt,e.formats),F};F._registry=et;F._reset=function(){et.clear(),it.length=0,Le()};function en(){if(typeof document>"u")return;let t=()=>Se(()=>Ut());document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t):t()}en();typeof window<"u"&&(window.Sap=F);var rn=F;return er(nn);})();
|
|
11
11
|
if (typeof window !== 'undefined' && Sap && Sap.default) window.Sap = Sap.default;
|
|
12
12
|
var sapDefault = Sap.default;
|
|
13
13
|
window.clay = window.clay || {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@panphora/clayjs",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "clayjs: malleable documents. Save lifecycle for self-saving HTML.",
|
|
6
6
|
"license": "MIT-0",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"./src/*": "./src/*",
|
|
33
33
|
"./entries/*": "./entries/*",
|
|
34
34
|
"./clay.standalone.js": "./dist/clay.standalone.js",
|
|
35
|
+
"./tailwind": "./src/tailwind.js",
|
|
35
36
|
"./dist/*": "./dist/*",
|
|
36
37
|
"./*": "./entries/*"
|
|
37
38
|
},
|
package/src/attrs/save-freeze.js
CHANGED
|
@@ -20,6 +20,7 @@ import { onSnapshot, addDocumentTransform } from "../core/snapshot.js";
|
|
|
20
20
|
import { isEditMode } from "../core/is-edit-mode.js";
|
|
21
21
|
import { FREEZE_SELECTOR } from "../lib/region-policy.js";
|
|
22
22
|
import { ROUTE_ACTIVE_ATTR } from "../lib/root-attrs.js";
|
|
23
|
+
import { stripEphemeral } from "../lib/ephemeral.js";
|
|
23
24
|
import Mutation from "../lib/mutation.js";
|
|
24
25
|
|
|
25
26
|
const originals = new WeakMap();
|
|
@@ -30,12 +31,14 @@ function log(...args) {
|
|
|
30
31
|
if (saveFreeze.debug) console.log('[save-freeze]', ...args);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
// The captured original is what the file keeps, so it must hold no router stamp
|
|
34
|
-
//
|
|
34
|
+
// The captured original is what the file keeps, so it must hold no router stamp
|
|
35
|
+
// and no ephemeral state: either can be set on a child before this capture runs.
|
|
35
36
|
function authoredInnerHTML(el) {
|
|
36
|
-
|
|
37
|
+
const html = el.innerHTML;
|
|
38
|
+
if (!el.querySelector(`[${ROUTE_ACTIVE_ATTR}]`) && !html.includes("ephemeral") && !html.includes("<dialog")) return html;
|
|
37
39
|
const copy = el.cloneNode(true);
|
|
38
40
|
for (const s of copy.querySelectorAll(`[${ROUTE_ACTIVE_ATTR}]`)) s.removeAttribute(ROUTE_ACTIVE_ATTR);
|
|
41
|
+
for (const child of copy.children) stripEphemeral(child);
|
|
39
42
|
return copy.innerHTML;
|
|
40
43
|
}
|
|
41
44
|
|
package/src/core/persist.js
CHANGED
|
@@ -96,7 +96,17 @@ export default function enablePersistentFormInputValues(filterBySelector = PERSI
|
|
|
96
96
|
};
|
|
97
97
|
finalize(inputSelector);
|
|
98
98
|
finalize(textareaSelector);
|
|
99
|
-
|
|
99
|
+
// A select's options pair through provenance, not by index: an excluded option
|
|
100
|
+
// (editor-ui, no-snapshot) is already gone from the copy, so its options are a
|
|
101
|
+
// subset of the live ones.
|
|
102
|
+
for (const control of doc.querySelectorAll(selectSelector)) {
|
|
103
|
+
if (!provenance.original(control)) continue;
|
|
104
|
+
for (const option of control.options) {
|
|
105
|
+
const live = provenance.original(option);
|
|
106
|
+
if (!(live && live.selected)) option.removeAttribute('selected');
|
|
107
|
+
else if (!option.hasAttribute('selected')) option.setAttribute('selected', '');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
100
110
|
});
|
|
101
111
|
}
|
|
102
112
|
|
package/src/core/save.js
CHANGED
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
saveFateIsUnknown,
|
|
22
22
|
withKeepalive
|
|
23
23
|
} from "./save-core.js";
|
|
24
|
-
import { captureForComparison, captureForComparisonAndDirty, captureForSaveAndComparison } from "./snapshot.js";
|
|
24
|
+
import { captureForComparison, captureForComparisonAndDirty, captureForSaveAndComparison, captureForDirtyCheck } from "./snapshot.js";
|
|
25
|
+
import { NO_TRIGGER_AUTOSAVE_SELECTOR } from "../lib/region-policy.js";
|
|
25
26
|
import { seedEtag, lastSeenEtag } from "./etag.js";
|
|
26
27
|
import { gateCaptureToken, gateClearIfUnchanged, pageMaybeDirty } from "../lib/dirty-gate.js";
|
|
27
28
|
import { hasUnsavedState } from "../lib/unsaved-state.js";
|
|
@@ -189,6 +190,12 @@ let lastSavedContents = '';
|
|
|
189
190
|
let lastSavedDirty = '';
|
|
190
191
|
// A save was requested while one was on the wire; run one more when it settles.
|
|
191
192
|
let pendingSave = false;
|
|
193
|
+
// An autosave arrived while one of our saves was on the wire. When that save lands
|
|
194
|
+
// it runs the autosave check again, rules and all, rather than an explicit save.
|
|
195
|
+
let pendingAutosave = false;
|
|
196
|
+
// True while a savePage/savePageForce request is on the wire. Only those drain the
|
|
197
|
+
// queue when they land, so an autosave never queues behind a raw saveHtml call.
|
|
198
|
+
let ownSaveOnWire = false;
|
|
192
199
|
|
|
193
200
|
// ============================================
|
|
194
201
|
// AUTOSAVE SUSPENSION
|
|
@@ -236,6 +243,9 @@ export function autosaveIsSuspended() {
|
|
|
236
243
|
// save asked for meanwhile is remembered and runs on release.
|
|
237
244
|
let previewHold = 0;
|
|
238
245
|
let previewMissed = false;
|
|
246
|
+
// An autosave skipped by the hold. Replayed as an autosave, so it keeps autosave
|
|
247
|
+
// rules (a batching-region edit still waits for an explicit save).
|
|
248
|
+
let previewAutosaveMissed = false;
|
|
239
249
|
const PREVIEW_HOLD_REASON = 'Waiting for the AI edit to be kept or reverted';
|
|
240
250
|
const holdReasons = new Map();
|
|
241
251
|
|
|
@@ -252,8 +262,12 @@ export function releaseAllSaves({ replay = true, reason = PREVIEW_HOLD_REASON }
|
|
|
252
262
|
previewHold--;
|
|
253
263
|
if (previewHold > 0) return;
|
|
254
264
|
const missed = previewMissed;
|
|
265
|
+
const autosaveMissedInHold = previewAutosaveMissed;
|
|
255
266
|
previewMissed = false;
|
|
256
|
-
|
|
267
|
+
previewAutosaveMissed = false;
|
|
268
|
+
if (!replay) return;
|
|
269
|
+
if (missed) savePage();
|
|
270
|
+
else if (autosaveMissedInHold) savePageThrottled();
|
|
257
271
|
}
|
|
258
272
|
|
|
259
273
|
export function savesHeld() {
|
|
@@ -407,10 +421,16 @@ function applySaveResult(result, forComparison, forDirty, label, gateToken, forS
|
|
|
407
421
|
// dropped, so the newer bytes still go out on the next save; the page is still
|
|
408
422
|
// dirty, so an edit or a close warning will produce one.
|
|
409
423
|
function drainPendingSave() {
|
|
410
|
-
if (!pendingSave) return;
|
|
424
|
+
if (!pendingSave && !pendingAutosave) return;
|
|
411
425
|
if (saveFateIsUnknown()) return;
|
|
412
|
-
pendingSave
|
|
413
|
-
|
|
426
|
+
if (pendingSave) {
|
|
427
|
+
pendingSave = false;
|
|
428
|
+
pendingAutosave = false;
|
|
429
|
+
savePage();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
pendingAutosave = false;
|
|
433
|
+
savePageThrottled();
|
|
414
434
|
}
|
|
415
435
|
|
|
416
436
|
// State accessors for autosave module
|
|
@@ -526,7 +546,9 @@ export function savePage(callback = () => {}) {
|
|
|
526
546
|
setSavingState();
|
|
527
547
|
|
|
528
548
|
// Use saveHtml directly with our pre-captured content (avoids double capture)
|
|
549
|
+
ownSaveOnWire = true;
|
|
529
550
|
saveHtml(forSave, (result) => {
|
|
551
|
+
ownSaveOnWire = false;
|
|
530
552
|
applySaveResult(result, forComparison, forDirty, 'updated after save', gateToken, forSave);
|
|
531
553
|
if (typeof callback === 'function') {
|
|
532
554
|
callback(result);
|
|
@@ -581,7 +603,9 @@ export function savePageForce(callback = () => {}) {
|
|
|
581
603
|
|
|
582
604
|
setSavingState();
|
|
583
605
|
|
|
606
|
+
ownSaveOnWire = true;
|
|
584
607
|
saveHtml(forSave, (result) => {
|
|
608
|
+
ownSaveOnWire = false;
|
|
585
609
|
applySaveResult(result, forComparison, forDirty, 'updated after force save', gateToken, forSave);
|
|
586
610
|
if (typeof callback === 'function') {
|
|
587
611
|
callback(result);
|
|
@@ -878,7 +902,7 @@ export function savePageThrottled(callback = () => {}) {
|
|
|
878
902
|
}
|
|
879
903
|
|
|
880
904
|
if (previewHold > 0) {
|
|
881
|
-
|
|
905
|
+
previewAutosaveMissed = true;
|
|
882
906
|
const skipped = skipped_(saveHoldReason());
|
|
883
907
|
callback(skipped);
|
|
884
908
|
return Promise.resolve(skipped);
|
|
@@ -894,6 +918,17 @@ export function savePageThrottled(callback = () => {}) {
|
|
|
894
918
|
return Promise.resolve(skipped);
|
|
895
919
|
}
|
|
896
920
|
|
|
921
|
+
// One of our saves is on the wire: queue this autosave instead of copying the
|
|
922
|
+
// page to compare. When that save lands, drainPendingSave runs this check again.
|
|
923
|
+
// Not while the page is settling, where every candidate save must pass the
|
|
924
|
+
// baseline veto below.
|
|
925
|
+
if (!baselineActive && ownSaveOnWire) {
|
|
926
|
+
pendingAutosave = true;
|
|
927
|
+
const skipped = skipped_('Save already in progress');
|
|
928
|
+
callback(skipped);
|
|
929
|
+
return Promise.resolve(skipped);
|
|
930
|
+
}
|
|
931
|
+
|
|
897
932
|
// For autosave: while the page is still settling, content must differ from BOTH
|
|
898
933
|
// the load-time baseline and the last save, so module setup churn cannot trigger
|
|
899
934
|
// a save. Once settled, the baseline veto is disarmed and only the last save
|
|
@@ -901,7 +936,21 @@ export function savePageThrottled(callback = () => {}) {
|
|
|
901
936
|
// persisted, because it matches the baseline forever.
|
|
902
937
|
// Compare directly - stored versions are already stripped
|
|
903
938
|
const gateToken = gateCaptureToken();
|
|
904
|
-
|
|
939
|
+
let currentForCompare;
|
|
940
|
+
let dirtyMatchesLastSave;
|
|
941
|
+
try {
|
|
942
|
+
currentForCompare = captureForComparison();
|
|
943
|
+
// This comparison leaves out batching (no-trigger-autosave) regions, which the
|
|
944
|
+
// gate counts, so on a page that has one the dirty domain must match too.
|
|
945
|
+
dirtyMatchesLastSave = () => !document.querySelector(NO_TRIGGER_AUTOSAVE_SELECTOR)
|
|
946
|
+
|| (pageMaybeDirty() && captureForDirtyCheck({ flushUndo: false }) === lastSavedDirty);
|
|
947
|
+
} catch (err) {
|
|
948
|
+
console.error('savePageThrottled: captureForComparison failed', err);
|
|
949
|
+
setSaveState('error', err.message);
|
|
950
|
+
const result = { msg: err.message, msgType: 'error', code: null, etag: null };
|
|
951
|
+
callback(result);
|
|
952
|
+
return Promise.resolve(result);
|
|
953
|
+
}
|
|
905
954
|
const differsFromBaseline = !baselineActive || currentForCompare !== baselineContents;
|
|
906
955
|
const differsFromLastSave = currentForCompare !== lastSavedContents;
|
|
907
956
|
|
|
@@ -909,7 +958,13 @@ export function savePageThrottled(callback = () => {}) {
|
|
|
909
958
|
logSaveCheck('throttled vs lastSave', !differsFromLastSave);
|
|
910
959
|
|
|
911
960
|
if (!(differsFromBaseline && differsFromLastSave)) {
|
|
912
|
-
|
|
961
|
+
let clear = false;
|
|
962
|
+
try {
|
|
963
|
+
clear = !differsFromLastSave && dirtyMatchesLastSave();
|
|
964
|
+
} catch (err) {
|
|
965
|
+
console.error('savePageThrottled: captureForDirtyCheck failed', err);
|
|
966
|
+
}
|
|
967
|
+
if (clear) gateClearIfUnchanged(gateToken);
|
|
913
968
|
const skipped = skipped_('No changes to save');
|
|
914
969
|
callback(skipped);
|
|
915
970
|
return Promise.resolve(skipped);
|
package/src/core/snapshot.js
CHANGED
|
@@ -42,6 +42,7 @@ import { stripExtensionNoise } from '../lib/extension-noise.js';
|
|
|
42
42
|
import { restoreAuthoredUrls } from '../lib/authored-url.js';
|
|
43
43
|
import { STRIP_FROM_SAVE, STRIP_FROM_COMPARISON, STRIP_FROM_DIRTY_CHECK, NO_TRIGGER_AUTOSAVE_SELECTOR, SNAPSHOT_REMOVE_SELECTOR } from '../lib/region-policy.js';
|
|
44
44
|
import { TAB_LOCAL_ROOT_ATTRS, stripRouteAttrs } from '../lib/root-attrs.js';
|
|
45
|
+
import { stripEphemeral } from '../lib/ephemeral.js';
|
|
45
46
|
import { createContentView } from '../lib/content-dom.js';
|
|
46
47
|
|
|
47
48
|
// =============================================================================
|
|
@@ -236,23 +237,11 @@ export function captureSnapshot({ flushUndo = true, authored = true } = {}) {
|
|
|
236
237
|
window.clay.undo.flush();
|
|
237
238
|
}
|
|
238
239
|
|
|
239
|
-
|
|
240
|
+
// The view records each clone node's live original straight into the provenance
|
|
241
|
+
// map as it clones, including the nodes inside a <template>'s content fragment,
|
|
242
|
+
// so the source map can ask which live node any clone node came from.
|
|
243
|
+
const view = createContentView(document.documentElement, { capability: 'snapshot', provenance: snapshotProvenance });
|
|
240
244
|
const clone = view.root;
|
|
241
|
-
// A <template>'s children are not its childNodes, they are its content fragment's,
|
|
242
|
-
// so walking childNodes alone leaves everything inside a template with no provenance.
|
|
243
|
-
// Nothing noticed until the source map asked which live node a clone node came from
|
|
244
|
-
// and got null for every node in a template, which reprinted the whole template on
|
|
245
|
-
// every save. createContentView already maps the fragment itself, so descending into
|
|
246
|
-
// it is all that was missing.
|
|
247
|
-
const remember = (node) => {
|
|
248
|
-
const live = view.original(node);
|
|
249
|
-
if (live) snapshotProvenance.set(node, live);
|
|
250
|
-
const children = node.nodeType === 1 && node.tagName === 'TEMPLATE' && node.content
|
|
251
|
-
? node.content.childNodes
|
|
252
|
-
: node.childNodes;
|
|
253
|
-
for (const child of children || []) remember(child);
|
|
254
|
-
};
|
|
255
|
-
remember(clone);
|
|
256
245
|
|
|
257
246
|
for (const hook of snapshotHooks) {
|
|
258
247
|
stripSnapshotRegions(clone);
|
|
@@ -280,6 +269,9 @@ export function captureSnapshot({ flushUndo = true, authored = true } = {}) {
|
|
|
280
269
|
// Router state says where this tab is, not what the document holds.
|
|
281
270
|
stripRouteAttrs(clone);
|
|
282
271
|
|
|
272
|
+
// So does ephemeral state: a selection, an open dialog, a marked attribute.
|
|
273
|
+
stripEphemeral(clone);
|
|
274
|
+
|
|
283
275
|
return clone;
|
|
284
276
|
}
|
|
285
277
|
|