@panphora/sapjs 0.2.1 → 0.2.3

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/sap.js CHANGED
@@ -458,20 +458,44 @@ ${src}` : `"use strict"; return (${src});`;
458
458
  }
459
459
 
460
460
  // src/platform.js
461
+ function capability(name) {
462
+ if (typeof window === "undefined") return null;
463
+ const clay = window.clay, hyperclay = window.hyperclay;
464
+ if (name === "consent") return clay?.confirm || hyperclay?.consent || null;
465
+ return clay?.[name] || hyperclay?.[name] || null;
466
+ }
467
+ var MUTATION_READY = ["clay:mutation-ready", "hyperclay:mutation-ready"];
468
+ var LIVESYNC_APPLIED = ["clay:sync-applied", "hyperclay:livesync-applied"];
469
+ var PLATFORM_READY = ["clay:ready", "hyperclay:ready"];
470
+ function onPlatformEvent(target, names, handler) {
471
+ let claimedBy = null;
472
+ const wrapped = (event) => {
473
+ if (claimedBy !== null && claimedBy !== event.type) return;
474
+ claimedBy = event.type;
475
+ queueMicrotask(() => {
476
+ claimedBy = null;
477
+ });
478
+ handler(event);
479
+ };
480
+ for (const name of names) target.addEventListener(name, wrapped);
481
+ return () => {
482
+ for (const name of names) target.removeEventListener(name, wrapped);
483
+ };
484
+ }
461
485
  function regionSkipsSave(el) {
462
- const region = typeof window !== "undefined" && window.hyperclay && window.hyperclay.region;
486
+ const region = capability("region");
463
487
  if (!region || typeof region.resolveRegionPolicy !== "function" || typeof region.skipForPolicy !== "function") {
464
488
  return false;
465
489
  }
466
490
  return region.skipForPolicy(region.resolveRegionPolicy(el), void 0, ["no-save", "freeze"]);
467
491
  }
468
492
  function platformConsent() {
469
- const h = typeof window !== "undefined" && window.hyperclay;
470
- return h && typeof h.consent === "function" ? h.consent : null;
493
+ const fn = capability("consent");
494
+ return typeof fn === "function" ? fn : null;
471
495
  }
472
496
  function batch(label, fn) {
473
497
  if (typeof fn !== "function") throw new Error("Sap.batch(label, fn): fn must be a function");
474
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
498
+ const u = capability("undo");
475
499
  if (u && u.flush) u.flush();
476
500
  const r = fn();
477
501
  if (r && typeof r.then === "function") throw new Error("Sap.batch fn must be synchronous (it returned a promise)");
@@ -491,18 +515,34 @@ ${src}` : `"use strict"; return (${src});`;
491
515
  runtime2.remountIfPresent();
492
516
  }
493
517
  };
494
- document.addEventListener("hyperclay:livesync-applied", refreshConnected);
495
- const undo = window.hyperclay && window.hyperclay.undo;
496
- if (undo && typeof undo.on === "function") {
497
- undo.on("undo", refreshConnected);
498
- undo.on("redo", refreshConnected);
499
- } else {
500
- document.addEventListener("hyperclay:mutation-ready", () => {
501
- const u = window.hyperclay && window.hyperclay.undo;
502
- if (u && typeof u.on === "function") {
503
- u.on("undo", refreshConnected);
504
- u.on("redo", refreshConnected);
505
- }
518
+ onPlatformEvent(document, LIVESYNC_APPLIED, refreshConnected);
519
+ let undoBound = false;
520
+ let stopWaiting = () => {
521
+ };
522
+ const bindUndo = () => {
523
+ if (undoBound) return true;
524
+ const undo = capability("undo");
525
+ if (!undo || typeof undo.on !== "function") return false;
526
+ const offUndo = undo.on("undo", refreshConnected);
527
+ if (typeof offUndo !== "function") return false;
528
+ const offRedo = undo.on("redo", refreshConnected);
529
+ if (typeof offRedo !== "function") {
530
+ offUndo();
531
+ return false;
532
+ }
533
+ undoBound = true;
534
+ stopWaiting();
535
+ return true;
536
+ };
537
+ if (!bindUndo()) {
538
+ const offMutationReady = onPlatformEvent(document, MUTATION_READY, bindUndo);
539
+ const offPlatformReady = onPlatformEvent(document, PLATFORM_READY, bindUndo);
540
+ stopWaiting = () => {
541
+ offMutationReady();
542
+ offPlatformReady();
543
+ };
544
+ const ready = capability("ready");
545
+ if (ready && typeof ready.then === "function") ready.then(bindUndo, () => {
506
546
  });
507
547
  }
508
548
  }
@@ -871,7 +911,7 @@ ${src}` : `"use strict"; return (${src});`;
871
911
  }
872
912
  },
873
913
  suppress(fn) {
874
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
914
+ const u = capability("undo");
875
915
  if (u && u.pause) u.pause();
876
916
  try {
877
917
  return fn();
@@ -935,7 +975,7 @@ ${src}` : `"use strict"; return (${src});`;
935
975
  }
936
976
  function withDomMutationPaused(fn) {
937
977
  if (activeSource) return activeSource.suppress(fn);
938
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
978
+ const u = capability("undo");
939
979
  if (u && u.pause && u.resume) {
940
980
  u.pause();
941
981
  try {
@@ -954,24 +994,22 @@ ${src}` : `"use strict"; return (${src});`;
954
994
  function installMutationBridge(runtime2) {
955
995
  if (installed) return;
956
996
  if (typeof window === "undefined" || typeof document === "undefined") return;
957
- const w = window;
958
- const M = w.hyperclay && w.hyperclay.Mutation;
997
+ const M = capability("Mutation");
959
998
  if (M && typeof M.onAnyChange === "function") {
960
999
  activate(hubSource(M), runtime2);
961
1000
  return;
962
1001
  }
963
1002
  if (typeof MutationObserver === "function") {
964
1003
  activate(nativeSource(), runtime2);
965
- lateHubListener = function onLateHub() {
966
- const M2 = w.hyperclay && w.hyperclay.Mutation;
1004
+ lateHubListener = onPlatformEvent(document, MUTATION_READY, function onLateHub() {
1005
+ const M2 = capability("Mutation");
967
1006
  if (!M2) return;
968
- document.removeEventListener("hyperclay:mutation-ready", lateHubListener);
1007
+ lateHubListener();
969
1008
  lateHubListener = null;
970
1009
  if (activeSource) activeSource.teardown();
971
1010
  installed = false;
972
1011
  activate(hubSource(M2), runtime2);
973
- };
974
- document.addEventListener("hyperclay:mutation-ready", lateHubListener);
1012
+ });
975
1013
  }
976
1014
  }
977
1015
  function resetMutationBridge() {
@@ -982,7 +1020,7 @@ ${src}` : `"use strict"; return (${src});`;
982
1020
  }
983
1021
  }
984
1022
  if (lateHubListener && typeof document !== "undefined") {
985
- document.removeEventListener("hyperclay:mutation-ready", lateHubListener);
1023
+ lateHubListener();
986
1024
  }
987
1025
  activeSource = null;
988
1026
  installed = false;
@@ -1306,7 +1344,7 @@ ${src}` : `"use strict"; return (${src});`;
1306
1344
  return 0;
1307
1345
  }
1308
1346
  case "when": {
1309
- const ov = typeof window !== "undefined" && window.hyperclay && window.hyperclay.optionVisibility;
1347
+ const ov = capability("optionVisibility");
1310
1348
  if (ov && ov._started) {
1311
1349
  if (el._sapWhen && el.hidden) {
1312
1350
  el.hidden = false;
package/dist/sap.min.js CHANGED
@@ -1,6 +1,6 @@
1
- var Sap=(()=>{var Nt=Object.defineProperty;var Ae=Object.getOwnPropertyDescriptor;var ve=Object.getOwnPropertyNames;var Ee=Object.prototype.hasOwnProperty;var Se=(t,e)=>{for(var n in e)Nt(t,n,{get:e[n],enumerable:!0})},xe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ve(e))!Ee.call(t,s)&&s!==n&&Nt(t,s,{get:()=>e[s],enumerable:!(r=Ae(e,s))||r.enumerable});return t};var $e=t=>xe(Nt({},"__esModule",{value:!0}),t);var En={};Se(En,{Sap:()=>_,default:()=>vn,mount:()=>ye,mountAll:()=>lt,runtime:()=>K});function Pt(t){let e=!1,n=new Set,r=[];function s(l){l&&(r.push(l),r.length>8&&r.shift())}function f(l,w){s(w),!l._broken&&(n.add(l),!e&&(e=!0,queueMicrotask(u)))}function u(){e=!1;let l=[...n];n.clear();for(let w of l)T(w)}function T(l){if(!l._broken){if(l._passes=(l._passes||0)+1,l._passes>50){l._broken=!0,l._breakerRing=r.slice(),t(l,{breaker:!0});return}l._resetArmed||(l._resetArmed=!0,setTimeout(()=>{l._passes=0,l._resetArmed=!1},0)),t(l)}}function E(l,w){s(w),T(l)}function y(l){l._broken=!1,l._passes=0}return{schedule:f,runNow:E,rearm:y,ring:r}}var ke=0;function Z(t,e="sap"){return t.id||(t.id=`${e}-${(ke++).toString(36)}`),t.id}function Ne(t){return t.hasAttribute("scope")||t.hasAttribute("items")||t.hasAttribute("detail")}function Te(t){return t.hasAttribute("sap-ignore")||t.hasAttribute("template")}function W(t,e){for(let r of t.children)n(r);function n(r){if(r.nodeType!==1||Te(r))return;let s=Ne(r);if(e(r,s),!s)for(let f of r.children)n(f)}}function I(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 dt(t){let e=t;for(;e;){if(e.hasAttribute("detail")||e.hasAttribute("item"))return e;e=e.parentElement}return null}function it(t){let e=t;for(;e;){if(e.hasAttribute("detail"))return e;e=e.parentElement}return null}function tt(t,e){let n=null;return W(t,r=>{!n&&r.getAttribute("bind")===e&&(n=r)}),n}function st(t,e){let n=null;return W(t,r=>{!n&&r.getAttribute("items")===e&&(n=r)}),n}function O(t){return[...t.children].filter(e=>e.hasAttribute("item")&&!e.hasAttribute("template"))}function pt(t){return[...t.children].find(e=>e.hasAttribute("item")&&e.hasAttribute("template"))||null}function F(t){let e=[];if(!t)return e;for(let n of t.trim().split(/\s+/)){if(!n)continue;let r=n,s,f=r.indexOf("=");f>=0&&(s=r.slice(f+1),r=r.slice(0,f));let u=r.split(":"),T=u[0],E="string",y=!1;for(let l of u.slice(1))l==="num"?E="num":l==="bool"?E="bool":l==="transient"&&(y=!0);e.push({name:T,type:E,default:s,transient:y})}return e}function G(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 mt(t,e){return e==="bool"?t?"true":"false":t==null?"":String(t)}function ht(t,e){let n=t._sapTransient||(t._sapTransient={});if(!(e.name in n)){let r=t.getAttribute(e.name);r==null&&(r=e.default!=null?e.default:e.type==="num"?"0":e.type==="bool"?"false":""),n[e.name]=G(r,e.type)}return t.hasAttribute(e.name)&&t.removeAttribute(e.name),n[e.name]}function Tt(t,e,n){(t._sapTransient||(t._sapTransient={}))[e.name]=n,t.hasAttribute(e.name)&&t.removeAttribute(e.name)}function at(t,e,n){let r=String(n).split("."),s=r[r.length-1];if(r.length===1){let T=_e(e,s);return T||(t.getAttribute("items")===s?t:t.querySelector(`[items="${s}"]`))}let f=r[r.length-2],u=[...t.querySelectorAll(`[scope="${f}"]`)].find(T=>st(T,s));return u?st(u,s):null}function _e(t,e){let n=I(t);for(;n;){if(n.getAttribute("items")===e)return n;let r=st(n,e);if(r)return r;n=I(n.parentElement)}return null}function P(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 bt(t,e){return Array.isArray(t)?e==null?t:t.map(n=>typeof e=="function"?e(n):n?.[e]):[]}function Bt(t,e){return bt(t,e).reduce((n,r)=>n+P(r),0)}function Le(t,e){return Array.isArray(t)?e==null?t.length:t.reduce((n,r)=>n+(e(r)?1:0),0):0}function Ce(t,e){let n=bt(t,e);return n.length?Bt(t,e)/n.length:0}function Me(t,e){let n=bt(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,s)=>String(r)<=String(s)?r:s):0}function Re(t,e){let n=bt(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,s)=>String(r)>=String(s)?r:s):0}function De(t,e,n){let r=P(t)===1?e:n??e+"s";return`${t} ${r}`}function Ie(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 z(t){return typeof t=="number"?t:Number(t)}var ut={usd:t=>"$"+z(t).toLocaleString("en-US",{maximumFractionDigits:0}),usd2:t=>"$"+z(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),pct:t=>Math.round(z(t))+"%",pct1:t=>z(t).toFixed(1)+"%",int:t=>Math.round(z(t)).toLocaleString("en-US"),num:t=>z(t).toLocaleString("en-US"),num2:t=>z(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),compact:t=>z(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=z(t),n=Math.floor(e/100),r=n%10,s=Math.floor(n/10)%60;return`${Math.floor(n/600)}:${String(s).padStart(2,"0")}.${r}`}},We=new Set(["usd","usd2","pct","pct1","int","num","num2","compact","clock"]);function qt(t,e){if(!t)return e==null?"":String(e);let n=ut[t];if(typeof n!="function"){let r=new Error(`unknown format "${t}"`);throw r.sapCode="E22",r}if(We.has(t)){let r=typeof e=="number"?e:Number(e);if(!Number.isFinite(r)){let s=new Error(`format "${t}" received ${typeof e=="string"?`"${e}"`:e}`);throw s.sapCode="E22",s}}return n(e)}function zt(){return[ut,P,Bt,Le,Ce,Me,Re,De,Ie]}var Fe=["state","item","el","root","fmt","num","sum","count","avg","min","max","plural","days"],gt=new Map,Ht=/\bstate\.([a-z][a-z0-9_]*)/g,jt=/\bitem\.([a-z][a-z0-9_]*)/g;function Oe(t){let e=new Set,n=new Set,r;for(Ht.lastIndex=0;r=Ht.exec(t);)e.add(r[1]);for(jt.lastIndex=0;r=jt.exec(t);)n.add(r[1]);return{state:e,item:n}}function D(t,e=!1){let n=(e?"!":"")+t,r=gt.get(n);if(r)return r;gt.size>512&&gt.clear();try{let s=e?`"use strict";
2
- ${t}`:`"use strict"; return (${t});`;r={fn:new Function(...Fe,s),src:t,statement:e,deps:Oe(t),error:null}}catch(s){r={fn:null,src:t,statement:e,deps:{state:new Set,item:new Set},error:s}}return gt.set(n,r),r}function H(t,e){if(t.error)throw t.error;return t.fn(e.state,e.item,e.el??null,e.root,...zt())}function Vt(t){let e=new Map;for(let u of t)e.set(u.name,u);let n=[],r=new Map,s=[];function f(u){let T=r.get(u.name);if(T!==1){if(T===0){let E=[...s.slice(s.indexOf(u.name)),u.name].join(" -> "),y=new Error(`calc: cycle: ${E}`);throw y.sapCode="E07",y.cycle=E,y}r.set(u.name,0),s.push(u.name);for(let E of u.entry.deps.state){let y=e.get(E);y&&y!==u&&f(y)}for(let E of u.entry.deps.item){let y=e.get(E);y&&y!==u&&f(y)}s.pop(),r.set(u.name,1),n.push(u)}}for(let u of t)f(u);return n}function Ut(t){return(t.getAttribute("type")||"text").toLowerCase()}function et(t){let e=t.tagName;if(e==="INPUT"){let n=Ut(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 Gt(t,e=t){let n=t.tagName;if(n==="INPUT"){let r=Ut(t);r==="checkbox"||r==="radio"?e.checked?t.setAttribute("checked",""):t.removeAttribute("checked"):t.setAttribute("value",e.value);return}if(n==="TEXTAREA"){t.textContent=e.value,t.removeAttribute("data-value");return}if(n==="SELECT"){let r=t.options,s=e.options;for(let f=0;f<r.length;f++)s[f]&&s[f].selected?r[f].setAttribute("selected",""):r[f].removeAttribute("selected")}}function wt(t){t.tagName!=="TEXTAREA"||!t.hasAttribute("data-value")||t!==t.ownerDocument.activeElement&&(t.textContent=t.getAttribute("data-value"),t.removeAttribute("data-value"))}function yt(t){let e=typeof window<"u"&&window.hyperclay&&window.hyperclay.region;return!e||typeof e.resolveRegionPolicy!="function"||typeof e.skipForPolicy!="function"?!1:e.skipForPolicy(e.resolveRegionPolicy(t),void 0,["no-save","freeze"])}function Yt(){let t=typeof window<"u"&&window.hyperclay;return t&&typeof t.consent=="function"?t.consent:null}function Xt(t,e){if(typeof e!="function")throw new Error("Sap.batch(label, fn): fn must be a function");let n=typeof window<"u"&&window.hyperclay&&window.hyperclay.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 Kt(t){if(typeof window>"u"||typeof document>"u")return;let e=()=>{let r=!1;for(let s of t.apps())s.root.isConnected?t.runNow(s,"platform"):r=!0;r&&(t.pruneDisconnected(),t.remountIfPresent())};document.addEventListener("hyperclay:livesync-applied",e);let n=window.hyperclay&&window.hyperclay.undo;n&&typeof n.on=="function"?(n.on("undo",e),n.on("redo",e)):document.addEventListener("hyperclay:mutation-ready",()=>{let r=window.hyperclay&&window.hyperclay.undo;r&&typeof r.on=="function"&&(r.on("undo",e),r.on("redo",e))})}function Pe(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 Be(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 qe(t,e){switch(e){case"checkbox":return t.checked;case"radio":return t.checked?t.value:void 0;case"number":return Be(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 ze(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 s of t.options)s.selected=r.has(s.value);break}case"leaf":t.textContent=n==null?"":String(n);break;default:t.value=n==null?"":String(n)}}function Jt(t){if(t.hasAttribute("transient")){t.removeAttribute("value"),t.removeAttribute("checked"),t.removeAttribute("data-value");return}yt(t)||et(t)}function He(t){t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function R(t){let e=Pe(t);return{el:t,kind:e,read(){return qe(t,e)},write(n,r={}){ze(t,e,n),r.noMirror||Jt(t),r.silent||He(t)},mirror(){Jt(t)}}}var _t={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"},W03:{slug:"unknown-colon-attribute",behavior:"WARN"},W04:{slug:"expression-in-when",behavior:"WARN"},W30:{slug:"nonzero-mount-writes",behavior:"WARN"}},At=["disabled","readonly","required","checked","selected","multiple","open","inert","autofocus","novalidate","hidden"],ct=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"]),vt=new Set(["sap","scope","items","item","template","bind","calc","text","show","attr","set","trigger","move","sort","detail","effect","invalid","confirm","transient","default","persist","sortable","editmode"]);function Et(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 s=n.tagName.toLowerCase();if(n.hasAttribute("sap"))s+="[sap]";else if(n.parentElement){let f=[...n.parentElement.children].filter(u=>u.tagName===n.tagName);f.length>1&&(s+=`:nth-of-type(${f.indexOf(n)+1})`)}if(e.unshift(s),n.hasAttribute("sap"))break;n=n.parentElement,r++}return e.join(" > ")}function Qt(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 nt=class{constructor(e){this.appName=e,this.errors=[],this.warnings=[],this.halted=!1,this.haltReason=null}block(e,n,r={}){let s=(_t[e]||{}).slug||"error",f={code:e,slug:s,el:Et(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=[`
3
- `+(e[0]==="W"?"sap \u26A0 ":"sap \u2717 ")+e+" "+s];return u.push(` at ${f.el}${f.attr?` \u2014 ${f.attr}="${f.expr??""}"`:""}`),f.problem&&u.push(` problem: ${f.problem}`),f.didYouMean&&u.push(` did you mean: ${f.didYouMean}`),f.fix&&u.push(` fix: ${f.fix}`),console.error(u.join(`
4
- `)),f}error(e,n,r={}){let s=this.block(e,n,r);return this.errors.push(s),s}warn(e,n,r={}){let s=this.block(e,n,r);return this.warnings.push(s),s}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 Y(t,e){t&&t.getAttribute("sap-error")!==e&&t.setAttribute("sap-error",e)}function St(t){t&&t.hasAttribute("sap-error")&&t.removeAttribute("sap-error")}function ft(t,e){let n=null,r=3;for(let s of e){let f=je(t,s);f<r&&(r=f,n=s)}return n}function je(t,e){let n=t.length,r=e.length,s=Array.from({length:n+1},(f,u)=>[u,...new Array(r).fill(0)]);for(let f=0;f<=r;f++)s[0][f]=f;for(let f=1;f<=n;f++)for(let u=1;u<=r;u++)s[f][u]=Math.min(s[f-1][u]+1,s[f][u-1]+1,s[f-1][u-1]+(t[f-1]===e[u-1]?0:1));return s[n][r]}var j=null,$t=!1,X=null;function Zt(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 Ve(){let t=null;return{kind:"native",subscribe(e){t=new MutationObserver(r=>e(Ue(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=typeof window<"u"&&window.hyperclay&&window.hyperclay.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 Ue(t){let e=[];for(let n of t)if(n.type==="attributes"){let r=n.target;r&&r.nodeType===1&&!xt(r)&&e.push({type:"attribute",element:r})}else if(n.type==="characterData"){let r=n.target&&n.target.parentElement;r&&!xt(r)&&e.push({type:"characterData",element:r})}else if(n.type==="childList"){for(let r of n.addedNodes)if(!(r.nodeType!==1||xt(r))&&(e.push({type:"add",element:r}),r.querySelectorAll))for(let s of r.querySelectorAll("*"))xt(s)||e.push({type:"add",element:s});for(let r of n.removedNodes)r.nodeType===1&&e.push({type:"remove",element:r,parent:n.target})}return e}function xt(t){return!!(t.closest&&t.closest("[sap-ignore],[template]"))}function Ge(t,e){t.pruneDisconnected();let n=new Set,r=!1;for(let s of e){let f=s.type==="remove"?s.parent:s.element,u=f&&t.appFor(f);u&&n.add(u),s.type==="add"&&s.element&&s.element.nodeType===1&&s.element.hasAttribute&&s.element.hasAttribute("sap")&&!(t.isRegistered&&t.isRegistered(s.element))&&(r=!0)}r&&t.remountIfPresent();for(let s of n)s.root.isConnected&&t.schedule(s,"mutation")}function te(t){if(j)return j.suppress(t);let e=typeof window<"u"&&window.hyperclay&&window.hyperclay.undo;if(e&&e.pause&&e.resume){e.pause();try{return t()}finally{e.resume()}}return t()}function Lt(t,e){$t=!0,j=t,t.subscribe(n=>Ge(e,n))}function Ct(t){if($t||typeof window>"u"||typeof document>"u")return;let e=window,n=e.hyperclay&&e.hyperclay.Mutation;if(n&&typeof n.onAnyChange=="function"){Lt(Zt(n),t);return}typeof MutationObserver=="function"&&(Lt(Ve(),t),X=function(){let s=e.hyperclay&&e.hyperclay.Mutation;s&&(document.removeEventListener("hyperclay:mutation-ready",X),X=null,j&&j.teardown(),$t=!1,Lt(Zt(s),t))},document.addEventListener("hyperclay:mutation-ready",X))}function ee(){if(j)try{j.teardown()}catch{}X&&typeof document<"u"&&document.removeEventListener("hyperclay:mutation-ready",X),j=null,$t=!1,X=null}var oe=new Set(At);function rt(t,e={}){if(e.breaker){t.diag.error("E26",t.root,{problem:"recompute loop halted after 50 passes; recent triggers: "+(t._breakerRing||[]).join(", ")}),Y(t.root,"loop");return}te(()=>Ye(t,e))}function Ye(t,e){let n=t.root,r={},s=[],f=[],u=[],T=[],E=[],y=new Set;t.diag.errors=[];let l={root:r,state:r,item:null,ownerEl:n,projection:!1};function w(o,i){let h=o.getAttribute(i.name);return h==null&&(h=i.default!=null?i.default:i.type==="num"?"0":i.type==="bool"?"false":"",E.push({el:o,name:i.name,value:mt(G(h,i.type),i.type)})),G(h,i.type)}function k(o,i){let h=F(o.getAttribute("state")||"");o._sapStateDecls=h;for(let p of h){if(p.type==="string"&&oe.has(p.name)&&typeof o[p.name]=="boolean"){i[p.name]=o.hasAttribute(p.name);continue}if(p.transient){i[p.name]=ht(o,p);continue}i[p.name]=w(o,p)}}function L(o,i){if(!o.hasAttribute("bind"))return;let h=o.getAttribute("bind"),p=i.item||i.state,v=R(o);v.kind==="radio"?(h in p||(p[h]=""),o.checked&&(p[h]=o.value)):p[h]=v.read(),o.hasAttribute("transient")&&(o.removeAttribute("value"),o.removeAttribute("checked"))}function b(o,i){for(let h of o.attributes){let p=h.name,v=h.value;if(p.startsWith("calc:"))s.push({owner:i.item||i.state,ownerEl:i.ownerEl,name:p.slice(5),entry:D(v),el:o,ctx:i});else if(p==="text"||p.startsWith("text:"))f.push({el:o,kind:"text",fmt:p.includes(":")?p.slice(5):null,entry:D(v),ctx:i});else if(p==="show")f.push({el:o,kind:"show",entry:D(v),ctx:i});else if(p.startsWith("attr:"))f.push({el:o,kind:"attr",arg:p.slice(5),entry:D(v),ctx:i});else if(p.startsWith("class:"))f.push({el:o,kind:"class",arg:p.slice(6),entry:D(v),ctx:i});else if(p.startsWith("css:"))f.push({el:o,kind:"css",arg:p.slice(4),entry:D(v),ctx:i});else if(p==="effect")u.push({el:o,entry:D(v,!0),ctx:i});else if(p==="invalid")T.push({el:o,entry:D(v),ctx:i});else if(p.startsWith("show-when:")||p.startsWith("option:")){let N=p.slice(p.indexOf(":")+1);y.add(N),f.push({el:o,kind:"when",match:"show",field:N,values:v.split("|"),ctx:i})}else if(p.startsWith("hide-when:")){let N=p.slice(p.indexOf(":")+1);y.add(N),f.push({el:o,kind:"when",match:"hide",field:N,values:v.split("|"),ctx:i})}else if(p.startsWith("option-not:")){let N=p.slice(p.indexOf(":")+1);y.add(N),f.push({el:o,kind:"when",match:"show-not",field:N,values:v.split("|"),ctx:i})}}i.projection&&o.hasAttribute("bind")&&f.push({el:o,kind:"projection",field:o.getAttribute("bind"),ctx:i})}function g(o,i,h){Z(i,"row"),Object.defineProperty(o,"$key",{value:i.id,enumerable:!1}),Object.defineProperty(o,"$index",{value:h,enumerable:!1}),Object.defineProperty(o,"$el",{value:i,enumerable:!1})}function a(o,i,h){k(o,i),o._sapScope=i,!h.projection&&o.hasAttribute("bind")&&L(o,h),b(o,h),o.hasAttribute("items")?x(o,i,h):A(o,i,h)}function A(o,i,h){W(o,(p,v)=>{v?p.hasAttribute("scope")?S(p,i,h):p.hasAttribute("items")?(b(p,h),x(p,i,h)):p.hasAttribute("detail")&&M(p,i,h):(h.projection||L(p,h),b(p,h))})}function S(o,i,h){let p=o.getAttribute("scope"),v={};i[p]=v;let N={root:h.root,state:v,item:null,ownerEl:o,projection:h.projection};a(o,v,N)}function x(o,i,h){let p=o.getAttribute("items"),v=[];i[p]=v,o._sapList=v,O(o).forEach((N,ot)=>{let C={};g(C,N,ot);let q={root:h.root,state:h.state,item:C,ownerEl:N,projection:h.projection};a(N,C,q),v.push(C)})}function $(o,i){let h=String(o).split("."),p=i.state;for(let v of h)p=p?.[v];if(p===void 0){p=i.root;for(let v of h)p=p?.[v]}return p}function M(o,i,h){for(let Q of F(o.getAttribute("state")||""))Q.name in i||(i[Q.name]=w(o,Q));o._sapScope=i;let p=o.getAttribute("detail")||"",v=/^([\w.]+)\s+by\s+(.+)$/.exec(p);if(!v){o.hidden=!0,o._sapDetailRow=null;return}let N=v[1],ot=v[2].trim(),C=$(N,h),q;try{q=H(D(ot),{state:i,item:h.item,el:o,root:h.root})}catch{q=void 0}let J=Array.isArray(C)?C.find(Q=>Q&&String(Q.$key)===String(q)):null;if(o._sapDetailRow=J?J.$el:null,!J){o.hidden||(o.hidden=!0);return}o.hidden&&(o.hidden=!1);let Ot={root:h.root,state:i,item:J,ownerEl:J.$el,projection:!0};b(o,Ot),A(o,J,Ot)}if(a(n,r,l),E.length&&y.size)for(let o of E)y.has(o.name)&&o.el.getAttribute(o.name)==null&&o.el.setAttribute(o.name,o.value);let m=new Map;for(let o of s){let i=m.get(o.owner);i||(i={ownerEl:o.ownerEl,list:[]},m.set(o.owner,i)),i.list.push(o)}let d=[...m.values()].sort((o,i)=>re(i.ownerEl)-re(o.ownerEl));for(let o of d){let i;try{i=Vt(o.list)}catch(h){t.diag.error("E07",o.list[0].el,{problem:h.message}),i=o.list}for(let h of i)try{h.owner[h.name]=H(h.entry,{state:h.ctx.state,item:h.ctx.item,el:h.el,root:h.ctx.root}),St(h.el)}catch(p){h.owner[h.name]=void 0,t.diag.error("E24",h.el,{attr:"calc:"+h.name,expr:h.entry.src,problem:String(p.message)}),Y(h.el,p.sapCode||"E24")}}let c=0;for(let o of f)c+=Je(o,t);for(let o of u)Qe(o,t);for(let o of T)Ze(o);t._state=r,t._stats={fields:Object.keys(r).filter(o=>typeof r[o]!="function").length,calcs:s.length,paints:f.length,lists:m.size,writes:c},t._lastPass={trigger:e.trigger||"refresh",writes:c},t._debug&&console.log(`sap pass \xB7 trigger: ${t._lastPass.trigger} \xB7 writes ${c}/${f.length}`)}function Xe(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 Mt(t,e,n,r){let s=t;for(;s&&s.nodeType===1;){if(s.hasAttribute&&s.hasAttribute(e)){let f=n.includes(s.getAttribute(e));if(r?!f:f)return!0}s=s.parentElement}return!1}function Ke(t,e){if(t===t.ownerDocument.activeElement)return 0;let n=R(t),r=n.read(),s=e??"";return String(r)!==String(s)?(n.write(s,{silent:!0}),1):0}function Je(t,e){if(t.kind==="projection")return Ke(t.el,t.ctx.item?t.ctx.item[t.field]:"");if(t.kind==="when")return ne(t,null);let n={state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root};try{let r=H(t.entry,n),s=ne(t,r);return St(t.el),s}catch(r){return e.diag.error(r.sapCode==="E22"?"E22":"E24",t.el,{attr:Xe(t),expr:t.entry&&t.entry.src,problem:String(r.message)}),Y(t.el,r.sapCode||"E24"),0}}function ne(t,e){let n=t.el;switch(t.kind){case"text":{let r=t.fmt!=null?qt(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=typeof window<"u"&&window.hyperclay&&window.hyperclay.optionVisibility;if(r&&r._started)return n._sapWhen&&n.hidden?(n.hidden=!1,n._sapWhen=!1,1):0;let s;t.match==="hide"?s=!Mt(n,t.field,t.values,!1):t.match==="show-not"?s=Mt(n,t.field,t.values,!0):s=Mt(n,t.field,t.values,!1),n._sapWhen=!0;let f=!s;return n.hidden!==f?(n.hidden=f,1):0}case"attr":{let r=t.arg;if(oe.has(r)){let f=n.hasAttribute(r);return e&&!f?(n.setAttribute(r,""),1):!e&&f?(n.removeAttribute(r),1):0}let s=typeof e=="boolean"?String(e):e==null?"":String(e);return n.getAttribute(r)!==s?(n.setAttribute(r,s),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 Qe(t,e){try{H(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root}),St(t.el)}catch(n){e.diag.error("E24",t.el,{attr:"effect",expr:t.entry&&t.entry.src,problem:String(n.message)}),Y(t.el,"E24")}}function Ze(t){let e="";try{let n=H(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 re(t){let e=0,n=t;for(;n&&!(n.hasAttribute&&n.hasAttribute("sap"));)n=n.parentElement,e++;return e}var tn=new Set(At),se=new Set(["calc","text","attr","class","css","set","move","sort","option","option-not","show-when","hide-when","editmode"]),en=new Set(["show-when","hide-when","option","option-not"]),nn=/\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 rn(t){return t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA"}function Rt(t){return t.hasAttribute("bind")}function on(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 s of r.children)n(s)}}}function kt(t,e){let n=!1,r=(u,T,E)=>{e.error(u,T,E),n=!0},s=t.ownerDocument.createTreeWalker(t,4),f;for(;f=s.nextNode();)if(/\{\{.*\}\}/.test(f.nodeValue||"")){r("E02",f.parentElement||t,{problem:"moustaches in text content are not a Sap feature",fix:'move the expression onto the element: text="state.x"'});break}return on(t,u=>{let T=u.closest&&u.closest("[detail]");for(let E of[...u.attributes]){let y=E.name,l=Qt(y);if(l){r("E01",u,{attr:y,expr:E.value,problem:`"${y}" is a foreign-dialect attribute; Sap has no ${y.split(/[:=]/)[0]} directive`,fix:l+" \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(en.has(w)&&nn.test(E.value)){let k=y.slice(y.indexOf(":")+1);e.warn("W04",u,{attr:y,expr:E.value,problem:`${w}: compares the "${k}" attribute against a literal value, not a JS expression`,fix:`use show="${E.value}" for an expression, or a literal like ${w}:${k}="overview"`})}}else{let k=ft(w,[...se]);e.warn("W03",u,{attr:y,problem:`unknown "${w}:" attribute`,didYouMean:k?`${k}:`:null})}}else if(!ie.has(y)&&!ct.has(y)&&!tn.has(y)&&!/^(data-|aria-|on)/.test(y)&&!(y in u)){let w=ft(y,[...ie]);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")&&Rt(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"&&Rt(u)&&/\b(value|checked)\s*=[^=]/.test(E.value)&&r("E30",u,{attr:y,expr:E.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")&&rn(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 E=F(u.getAttribute("state")),y=new Set;for(let l of E)l.name.includes("-")&&r("E08",u,{attr:"state",problem:`field "${l.name}" is not a valid identifier (the hyphen parses as subtraction)`,fix:`rename to ${l.name.replace(/-/g,"")}`}),y.has(l.name)&&r("E04",u,{attr:"state",problem:`field "${l.name}" is declared twice in one scope`}),y.add(l.name),vt.has(l.name)&&r("E05",u,{attr:"state",problem:`"${l.name}" is a reserved Sap word`}),ct.has(l.name)&&r("E06",u,{attr:"state",problem:`"${l.name}" is a global HTML attribute name; pick another field name`}),l.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(Rt(u)){if(u.hasAttribute("-"),u.tagName==="INPUT"){let E=(u.getAttribute("type")||"text").toLowerCase();E==="file"&&r("E32",u,{attr:"bind",problem:"files never serialize into an HTML file",fix:"use no-save + effect instead of bind"}),E==="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 E=u.getAttribute("contenteditable");!(E!=null&&E!=="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 E=u.parentElement;(!E||!E.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")&&T&&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 E=t.querySelector(`[trigger-add="${u.getAttribute("items")}"]`);!pt(u)&&O(u).length===0&&E&&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",Y(t,e.haltReason)),!n}var ae="sap-styles",ue="[item][template]{display:none!important}[hidden]{display:none!important}[sap-error]{outline:2px solid #e5484d;outline-offset:1px}",Dt=new WeakSet;function sn(t){if(Dt.has(t))return;let e=t.defaultView,n=e&&e.CSSStyleSheet;if(n&&"adoptedStyleSheets"in t)try{let r=new n;r.replaceSync(ue),t.adoptedStyleSheets=[...t.adoptedStyleSheets,r],Dt.add(t);return}catch{}if(!t.getElementById(ae)){let r=t.createElement("style");r.id=ae,r.textContent=ue,(t.head||t.documentElement).appendChild(r)}Dt.add(t)}var an=0;function ce(){return typeof performance<"u"&&performance.now?performance.now():0}function It(t){let e=t.id||t.getAttribute("sap")||`app-${an++}`,n=new nt(e),r={root:t,name:e,diag:n,_state:null,_stats:null,_lastPass:null,_passes:0,_broken:!1,_mountMs:0,_mountWrites:0};if(!kt(t,n))return r.halted=!0,r;sn(t.ownerDocument);for(let u of t.querySelectorAll("textarea[data-value]"))wt(u);let f=ce();return rt(r,{trigger:"mount"}),r._mountMs=ce()-f,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 un(t,e){let n=null;return W(t,r=>{!n&&r.getAttribute("scope")===e&&(n=r)}),n}function fe(t,e,n){let r=I(t)||e;for(;r;){for(let s of F(r.getAttribute("state")||""))if(s.name===n)return{el:r,decl:s};if(r.hasAttribute("sap"))break;r=I(r.parentElement)}return null}function cn(t){return typeof t=="number"?"num":typeof t=="boolean"?"bool":"string"}function le(t){function e(b){let g=t.appFor(b);if(!g)return null;let a=it(b);if(a)return a._sapDetailRow?{ctxEl:a._sapDetailRow,appRec:g,isRow:!0}:{ctxEl:I(a.parentElement)||g.root,appRec:g,isRow:!1};let A=dt(b);if(A&&A.hasAttribute("item"))return{ctxEl:A,appRec:g,isRow:!0};let S=I(b)||g.root;return{ctxEl:S,appRec:g,isRow:S.hasAttribute("item")}}function n(b){let g=typeof b=="string"?document.querySelector(b):b;if(!g||g.nodeType!==1)return null;let a=e(g);return a?L(a.ctxEl,a.appRec,a.isRow):null}function r(b,g,a){let A=tt(b,a);if(A)return R(A).read();let S=st(b,a);if(S)return O(S).map(m=>L(m,g,!0));let x=un(b,a);if(x)return L(x,g,!1);let $=fe(b,g.root,a);if($)return $.decl.transient?ht($.el,$.decl):G($.el.getAttribute(a),$.decl.type);let M=b._sapScope;return M?M[a]:void 0}function s(b,g,a,A,S){A.transient?Tt(b,A,a):b.setAttribute(g,mt(a,A.type)),t.schedule(S,"set:"+g)}function f(b,g){let a=new Set,A=I(b)||g;for(;A;){for(let S of F(A.getAttribute("state")||""))a.add(S.name);if(A.hasAttribute("sap"))break;A=I(A.parentElement)}return W(b,S=>{let x=S.getAttribute("bind");x&&a.add(x)}),a}function u(b,g,a,A){let S=tt(b,a);if(S){R(S).write(A);return}let x=b;for(;x;){for(let h of x.attributes)if(h.name==="calc:"+a){g.diag.error("E16",x,{attr:"calc:"+a,problem:`"${a}" is a computed field; computed fields are read-only`});return}if(x.hasAttribute("sap"))break;x=x.parentElement}let $=fe(b,g.root,a);if($){s($.el,a,A,$.decl,g);return}let M=f(b,g.root);M.delete(a);let m=a.length>=4?ft(a,[...M]):null;if(m){g.diag.error("E12",b,{key:a,problem:`unknown state key "${a}"`,didYouMean:m});return}if(vt.has(a)||ct.has(a)){g.diag.error("E15",b,{key:a,problem:`cannot write undeclared field "${a}" \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 d=g.root,c=cn(A),o=d.getAttribute("state")||"",i=c==="string"?a:`${a}:${c}`;d.setAttribute("state",o?`${o} ${i}`:i),s(d,a,A,{name:a,type:c,transient:!1},g)}function T(b){let g=a=>{a.id&&(a.id="",Z(a,"row")),a.hasAttribute("sap-error")&&a.removeAttribute("sap-error")};b.id="",Z(b,"row"),b.querySelectorAll("[id]").forEach(g)}function E(b,g,a){let A=at(g.root,b,a);if(!A)return g.diag.error("E17",b,{problem:`cannot resolve a list named "${a}" from here`}),null;let S=pt(A);if(!S)return g.diag.error("E17",A,{problem:`items="${a}" has no [item template] to clone`}),null;let x=S.cloneNode(!0);return x.removeAttribute("template"),T(x),A.appendChild(x),t.schedule(g,"trigger-add:"+a),L(x,g,!0)}function y(b,g){W(b,a=>{if(a.hasAttribute("bind")){let A=R(a),S=a.getAttribute("default");A.kind==="checkbox"||A.kind==="radio"?A.write(S!=null?S===""||S==="true"||a.value===S:a.hasAttribute("checked")):A.write(S??(a.getAttribute("value")||""))}});for(let a of F(b.getAttribute("state")||"")){let A=a.default!=null?a.default:a.type==="num"?"0":a.type==="bool"?"false":"";a.transient?Tt(b,a,G(A,a.type)):b.setAttribute(a.name,A)}t.schedule(g,"trigger-reset")}function l(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,a){if(!b.isConnected)throw new Error("stale row handle: $move() on a removed row");let A=null;if(a&&a.nodeType===1?A=a:typeof a=="string"&&(A=at(g.root,b,a)),!A){g.diag.error("E17",b,{problem:`$move() cannot resolve target "${a}"`});return}t.moveInto(A,b),t.schedule(g,"trigger-move")}function k(b){let g=b.parentElement;return g?O(g).indexOf(b):-1}function L(b,g,a){let A={get $el(){return b},get $key(){return Z(b,a?"row":"scope")},get $index(){return k(b)},$add(x){return E(b,g,x)},$reset(){return y(b,g),S},$remove(){l(b,g)},$move(x){w(b,g,x)},get $appRec(){return g}},S=new Proxy(A,{get(x,$){return typeof $=="symbol"||$[0]==="$"?x[$]:r(b,g,$)},set(x,$,M){return typeof $=="string"&&$[0]==="$"?(x[$]=M,!0):(u(b,g,$,M),!0)},has(x,$){return typeof $=="string"&&$[0]==="$"?$ in x:r(b,g,$)!==void 0}});return S}return{Sap:n,contextElFor:e,readField:r,writeField:u,makeProxy:L}}var fn=["trigger-add","trigger-remove","trigger-reset"];function ln(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:")||fn.includes(n))return!0}return!1}function dn(t,e){let n=t,r=e.parentElement;for(;n&&n!==r;){if(n.nodeType===1&&ln(n)&&!(n.tagName==="FORM"&&n.hasAttribute("trigger-add")))return n;n=n.parentElement}return null}function de(t,e){let{Sap:n}=e;function r(m,d){let c=null,o=it(m);if(o&&o._sapDetailRow)c=o._sapDetailRow._sapScope||null;else{let p=dt(m);p&&p.hasAttribute("item")&&(c=p._sapScope||null)}return{state:(I(m)||d.root)._sapScope||d._state||{},item:c,el:m,root:d._state||{}}}function s(m,d,c){if(!m.hasAttribute("confirm")){c();return}let o=m.getAttribute("confirm"),i=o,h=D(o);if(!h.error)try{let N=H(h,r(m,d));(typeof N=="string"||typeof N=="number")&&(i=String(N))}catch{}let p=Yt();if(!p){window.confirm(i)&&c();return}if(m._sapGatePending)return;m._sapGatePending=!0;let v=()=>{m._sapGatePending=!1};p(i,()=>{v(),c()}).catch(v)}function f(m,d){for(let c of m.attributes){if(!c.name.startsWith("set:"))continue;let o=c.name.slice(4),i=D(c.value);if(i.error){d.diag.error("E08",m,{attr:c.name,expr:c.value,problem:String(i.error.message)});continue}let h;try{h=H(i,r(m,d))}catch(v){d.diag.error("E24",m,{attr:c.name,expr:c.value,problem:String(v.message)});continue}let p=n(m);p&&(p[o]=h)}}function u(m,d){let c=m.closest("[item]");if(!c)return;let o=O(c.parentElement),i=o.indexOf(c);d==="up"&&i>0?t.placeBefore(c,o[i-1]):d==="down"&&i<o.length-1&&t.placeBefore(o[i+1],c)}function T(m,d,c){if(d)return at(c.root,m,d);let o=m;for(;o;){if(o.hasAttribute&&o.hasAttribute("items"))return o;o=o.parentElement}let i=I(m)||c.root,h=[];return W(i,p=>{p.hasAttribute("items")&&h.push(p)}),h[0]||null}function E(m,d){let c=m==null||m==="",o=d==null||d==="";if(c&&o)return 0;if(c)return 1;if(o)return-1;let i=Number(m),h=Number(d);return!Number.isNaN(i)&&!Number.isNaN(h)?i-h:String(m)<String(d)?-1:String(m)>String(d)?1:0}function y(m,d,c,o){let i=T(m,c,o);if(!i){o.diag.error("E17",m,{attr:"sort:"+d,problem:`no items list resolvable for sort:${d}`});return}let h=O(i),p=C=>C._sapScope?C._sapScope[d]:void 0,v=[...h].sort((C,q)=>E(p(C),p(q))),ot=v.every((C,q)=>C===h[q])?[...v].reverse():v;for(let C of ot)t.moveInto(i,C);t.schedule(o,"sort:"+d)}function l(m){if(!m||m.hidden)return;let d=m.querySelector("[bind]:not([type=hidden]), [contenteditable]");d&&typeof d.focus=="function"&&d.focus()}function w(m,d){s(m,d,()=>{let c=n(m);for(let o of[...m.attributes]){let i=o.name;if(i==="trigger-remove")c&&c.$remove();else if(i==="trigger-reset")c&&c.$reset();else if(i==="trigger-add"){let h=c&&c.$add(o.value);h&&l(h.$el)}else i==="move:up"?(u(m,"up"),t.schedule(d,"move:up")):i==="move:down"?(u(m,"down"),t.schedule(d,"move:down")):i.startsWith("move:to")?c&&c.$move(o.value):i.startsWith("sort:")&&y(m,i.slice(5),o.value,d)}[...m.attributes].some(o=>o.name.startsWith("set:"))&&f(m,d)})}function k(m){let d=m.target;if(!d||d.nodeType!==1)return;let c=t.appFor(d);if(!c)return;let o=dn(d,c.root);o&&w(o,c)}function L(m){let d=R(m),c=m.getAttribute("default");d.kind==="checkbox"?d.write(c===""||c==="true"):d.write(c??"")}function b(m,d,c){let o=n(m);if(!o)return;let i=o.$add(c);if(!i)return;let h=[];W(m,p=>{p.hasAttribute("bind")&&h.push(p)});for(let p of h){let v=tt(i.$el,p.getAttribute("bind"));v&&R(v).write(R(p).read())}h.forEach(L),h.length?typeof h[0].focus=="function"&&h[0].focus():l(i.$el)}function g(m){let d=m.target;if(!d||!d.hasAttribute||!d.hasAttribute("trigger-add"))return;let c=t.appFor(d);c&&(m.preventDefault(),s(d,c,()=>b(d,c,d.getAttribute("trigger-add"))))}function a(m){let d=m.target,c=t.appFor(d);c&&setTimeout(()=>{d.querySelectorAll("[bind]").forEach(o=>{o.dispatchEvent(new Event("input",{bubbles:!0})),o.dispatchEvent(new Event("change",{bubbles:!0}))}),t.schedule(c,"reset")},0)}function A(m){let d=t.appFor(m.target);d&&t.schedule(d,"toggle")}function S(m){let d=m.target;if(!d||d.nodeType!==1)return;let c=t.appFor(d);if(!c)return;d.hasAttribute("persist")&&!yt(d)&&et(d);let o=it(d);if(o&&o._sapDetailRow&&d.hasAttribute("bind")){let i=tt(o._sapDetailRow,d.getAttribute("bind"));if(i&&i!==d){R(i).write(R(d).read());return}}t.schedule(c,m.type+" "+(d.id||d.tagName.toLowerCase()))}function x(m){let d=m.detail||{};for(let c of[d.from,d.to,m.target]){if(!c||c.nodeType!==1)continue;let o=t.appFor(c);o&&t.schedule(o,"sorted")}}function $(m){if(m.key!=="ArrowUp"&&m.key!=="ArrowDown")return;let d=m.target;if(!d||d.nodeType!==1||d.tagName!=="INPUT"||!d.hasAttribute("bind")||!d.hasAttribute("step"))return;let c=(d.getAttribute("type")||"text").toLowerCase();if(c!=="text"&&c!=="tel"&&c!=="search"||!t.appFor(d))return;m.preventDefault();let i=P(d.getAttribute("step"))||1,h=m.key==="ArrowUp"?1:-1,p=P(d.value)+i*(m.shiftKey?10:1)*h,v=d.getAttribute("min"),N=d.getAttribute("max");v!==null&&v!==""&&p<P(v)&&(p=P(v)),N!==null&&N!==""&&p>P(N)&&(p=P(N)),R(d).write(String(Number(p.toFixed(2))))}function M(m=document){m.addEventListener("click",k),m.addEventListener("submit",g),m.addEventListener("reset",a),m.addEventListener("toggle",A,!0),m.addEventListener("input",S),m.addEventListener("change",S),m.addEventListener("clay:sorted",x),m.addEventListener("keydown",$)}return{install:M}}var pe=/^(set:|move:|sort:|trigger-add$|trigger-remove$|trigger-reset$)/;function Wt(t){return`${t.tagName.toLowerCase()}[sap]`}function pn(t){let e=0;for(let n of t.querySelectorAll("*"))for(let r of n.attributes)if(pe.test(r.name)){e++;break}for(let n of t.attributes)if(pe.test(n.name)){e++;break}return e}function me(t){let e=[],n=r=>{for(let s of r.attributes){let f=s.name;(f.startsWith("calc:")||f==="text"||f.startsWith("text:")||f==="show"||f.startsWith("attr:")||f.startsWith("class:")||f.startsWith("css:")||f==="effect"||f==="invalid"||f.startsWith("set:")||f==="detail")&&e.push({el:r,attr:f,src:s.value})}};n(t);for(let r of t.querySelectorAll("*"))n(r);return e}function he(t){function e(l){let w=l._stats||{},k=l.root;return{root:Wt(k),fields:w.fields||0,calcs:w.calcs||0,paints:w.paints||0,actions:pn(k),lists:(k.hasAttribute("items")?1:0)+k.querySelectorAll("[items]").length,rows:k.querySelectorAll("[item]:not([template])").length,warnings:l.diag.warnings.length,errors:l.diag.errors.length,mountWrites:l._mountWrites||0,ms:Math.round((l._mountMs||0)*10)/10,passes:l._passes||0,lastPass:l._lastPass||null,ok:l.diag.errors.length===0&&!l.halted}}function n(){let l=t.apps().map(e);return{ok:l.every(w=>w.ok),apps:l}}function r(l){let w=e(l);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 s(){for(let l of t.apps()){let w=r(l);l.diag.errors.length||l.halted?console.error(w):console.log(w)}}function f(){let l=[],w=[];for(let k of t.apps())l.push(...k.diag.errors),w.push(...k.diag.warnings);return{ok:l.length===0,errors:l,warnings:w,counts:{errors:l.length,warnings:w.length}}}function u(l){return l?typeof l=="string"?document.querySelector(l):l.nodeType===1?l:null:null}function T(l,w){let k=u(l);if(!k)return console.warn("sap why: element not found"),null;let L=[`sap why <${k.tagName.toLowerCase()}> \u2014 ${Et(k)}`],b=[...k.attributes].filter(a=>/^(bind|text|show|effect|invalid|detail|calc:|text:|attr:|class:|css:|set:|state|items|scope)/.test(a.name));for(let a of b)L.push(` ${a.name}="${a.value}"`);let g=k;for(;g&&!g._sapScope;)g=g.parentElement;if(g&&g._sapScope){let a=g._sapScope,A=w?[w]:Object.keys(a);L.push(" reads:");for(let S of A){let x=a[S];typeof x!="function"&&L.push(` ${S} = ${JSON.stringify(Array.isArray(x)?`[${x.length} rows]`:x)}`)}}return L.push(" serialization: textContent and value/checked attributes save with the file; reads live from properties"),console.log(L.join(`
5
- `)),null}function E(l){let w=l===void 0?!0:!!l;for(let k of t.apps())k._debug=w;return console.log(`sap debug ${w?"on":"off"} \u2014 per-pass headers will ${w?"":"no longer "}log`),w}function y(){let l=[],w=0;for(let a of t.apps()){let A=a.root,S=Wt(A);w++;let x=new nt(a.name);kt(A,x);for(let c of x.errors)l.push({code:c.code,severity:"error",message:`${S}: ${c.code} ${c.slug} at ${c.el}`});for(let c of x.warnings)l.push({code:c.code,severity:"warn",message:`${S}: ${c.code} ${c.slug} at ${c.el}`});w++,rt(a,{trigger:"doctor-dryrun"});let $=a._stats?a._stats.writes:0;$>0&&l.push({code:"W30",severity:"warn",message:`${S}: dry recompute wrote ${$} cells on a quiet page; an element is stale or non-idempotent`}),w++;let M=me(A).map(c=>c.src).join(" \0 "),m=[];for(let c of[A,...A.querySelectorAll("[state]")])for(let o of F(c.getAttribute("state")||""))m.push(o.name);for(let c of m)new RegExp(`(state|item)\\.${c}\\b`).test(M)||l.push({code:"I33",severity:"info",message:`${S}: field "${c}" is declared but read nowhere (dead state)`});w++;let d=new Map;for(let c of A.querySelectorAll("[id]"))d.set(c.id,(d.get(c.id)||0)+1);for(let[c,o]of d)o>1&&l.push({code:"W32",severity:"warn",message:`${S}: duplicate id "${c}" (${o} elements) \u2014 clone/edit collision`});w++;for(let c of me(A))c.src.length>120&&l.push({code:"I33",severity:"info",message:`${S}: ${c.attr} expression is ${c.src.length} chars; consider a calc: field`});w++;for(let c of A.querySelectorAll("[text], [text\\:num]")){let o=c.textContent||"";/\.\d{5,}/.test(o)&&l.push({code:"I33",severity:"info",message:`${S}: ${Et(c)} paints >4 decimals; consider text:FMT`})}}let k=l.filter(a=>a.severity==="error").length,L=l.filter(a=>a.severity==="warn").length,b=l.filter(a=>a.severity==="info").length;console.log(`sap doctor \xB7 ${t.apps().map(a=>Wt(a.root)).join(", ")} \xB7 errors ${k} \xB7 warnings ${L} \xB7 info ${b} \xB7 ${w} checks \xB7 0ms`);for(let a of l)(a.severity==="error"?console.error:a.severity==="warn"?console.warn:console.info)(` ${a.severity==="error"?"\u2717":a.severity==="warn"?"\u26A0":"\xB7"} ${a.message}`);return l}return{status:n,report:f,why:T,debug:E,doctor:y,greenLine:r,printGreenLines:s,REGISTRY:_t}}var mn="0.2.0",B=new Map,V=[],Ft=Pt(rt);function hn(t){let e=t;for(;e;){if(e.nodeType===1&&e.hasAttribute&&e.hasAttribute("sap"))return B.get(e)||null;e=e.parentNode&&e.parentNode.host?e.parentNode.host:e.parentElement}return null}function bn(){for(let t=V.length-1;t>=0;t--){let e=V[t];e.root.isConnected||(B.delete(e.root),V.splice(t,1))}}function gn(t,e){if(t.moveBefore)try{t.moveBefore(e,null);return}catch{}t.appendChild(e)}function wn(t,e){let n=e.parentElement;if(n){if(n.moveBefore)try{n.moveBefore(t,e);return}catch{}n.insertBefore(t,e)}}var K={apps:()=>V.slice(),appFor:hn,isRegistered:t=>B.has(t),pruneDisconnected:bn,schedule:(t,e)=>Ft.schedule(t,e),runNow:(t,e)=>Ft.runNow(t,e),moveInto:gn,placeBefore:wn,remountIfPresent:()=>lt()},ge=le(K),yn=de(K,ge),U=he(K),be=!1;function we(){be||(be=!0,yn.install(document),Kt(K))}function lt(t=document){we(),Ct(K);let e=t.querySelectorAll("[sap]"),n=[];for(let r of e){if(B.has(r))continue;let s=It(r);B.set(r,s),V.push(s),n.push(s)}for(let r of n){let s=U.greenLine(r);r.diag.errors.length||r.halted?console.error(s):console.log(s)}return n}function ye(t){if(we(),Ct(K),!t)return lt();let e=typeof t=="string"?document.querySelector(t):t;if(!e)return null;if(B.has(e))return B.get(e);let n=It(e);B.set(e,n),V.push(n);let r=U.greenLine(n);return n.diag.errors.length||n.halted?console.error(r):console.log(r),n}var _=ge.Sap;_.version=mn;_.refresh=function(){for(let e of V)e.root.isConnected&&Ft.runNow(e,"refresh")};_.batch=Xt;_.status=U.status;_.report=U.report;_.why=U.why;_.debug=U.debug;_.doctor=U.doctor;_.greenLine=U.greenLine;_.formats=ut;_.serializeControlToAttributes=et;_.finalizeControlForSave=Gt;_.rehydrateControlFromAttributes=wt;_.mount=ye;_.config=function(e={}){return e.formats&&Object.assign(ut,e.formats),_};_._registry=B;_._reset=function(){B.clear(),V.length=0,ee()};function An(){typeof document>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>lt()):lt())}An();typeof window<"u"&&(window.Sap=_);var vn=_;return $e(En);})();
1
+ var Sap=(()=>{var _t=Object.defineProperty;var Se=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var $e=Object.prototype.hasOwnProperty;var ke=(t,e)=>{for(var n in e)_t(t,n,{get:e[n],enumerable:!0})},Ne=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of xe(e))!$e.call(t,s)&&s!==n&&_t(t,s,{get:()=>e[s],enumerable:!(r=Se(e,s))||r.enumerable});return t};var Te=t=>Ne(_t({},"__esModule",{value:!0}),t);var Nn={};ke(Nn,{Sap:()=>_,default:()=>kn,mount:()=>Ee,mountAll:()=>pt,runtime:()=>K});function zt(t){let e=!1,n=new Set,r=[];function s(l){l&&(r.push(l),r.length>8&&r.shift())}function i(l,y){s(y),!l._broken&&(n.add(l),!e&&(e=!0,queueMicrotask(a)))}function a(){e=!1;let l=[...n];n.clear();for(let y of l)k(y)}function k(l){if(!l._broken){if(l._passes=(l._passes||0)+1,l._passes>50){l._broken=!0,l._breakerRing=r.slice(),t(l,{breaker:!0});return}l._resetArmed||(l._resetArmed=!0,setTimeout(()=>{l._passes=0,l._resetArmed=!1},0)),t(l)}}function E(l,y){s(y),k(l)}function w(l){l._broken=!1,l._passes=0}return{schedule:i,runNow:E,rearm:w,ring:r}}var _e=0;function Z(t,e="sap"){return t.id||(t.id=`${e}-${(_e++).toString(36)}`),t.id}function Le(t){return t.hasAttribute("scope")||t.hasAttribute("items")||t.hasAttribute("detail")}function Ce(t){return t.hasAttribute("sap-ignore")||t.hasAttribute("template")}function F(t,e){for(let r of t.children)n(r);function n(r){if(r.nodeType!==1||Ce(r))return;let s=Le(r);if(e(r,s),!s)for(let i of r.children)n(i)}}function I(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 mt(t){let e=t;for(;e;){if(e.hasAttribute("detail")||e.hasAttribute("item"))return e;e=e.parentElement}return null}function at(t){let e=t;for(;e;){if(e.hasAttribute("detail"))return e;e=e.parentElement}return null}function tt(t,e){let n=null;return F(t,r=>{!n&&r.getAttribute("bind")===e&&(n=r)}),n}function it(t,e){let n=null;return F(t,r=>{!n&&r.getAttribute("items")===e&&(n=r)}),n}function O(t){return[...t.children].filter(e=>e.hasAttribute("item")&&!e.hasAttribute("template"))}function ht(t){return[...t.children].find(e=>e.hasAttribute("item")&&e.hasAttribute("template"))||null}function P(t){let e=[];if(!t)return e;for(let n of t.trim().split(/\s+/)){if(!n)continue;let r=n,s,i=r.indexOf("=");i>=0&&(s=r.slice(i+1),r=r.slice(0,i));let a=r.split(":"),k=a[0],E="string",w=!1;for(let l of a.slice(1))l==="num"?E="num":l==="bool"?E="bool":l==="transient"&&(w=!0);e.push({name:k,type:E,default:s,transient:w})}return e}function G(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 bt(t,e){return e==="bool"?t?"true":"false":t==null?"":String(t)}function gt(t,e){let n=t._sapTransient||(t._sapTransient={});if(!(e.name in n)){let r=t.getAttribute(e.name);r==null&&(r=e.default!=null?e.default:e.type==="num"?"0":e.type==="bool"?"false":""),n[e.name]=G(r,e.type)}return t.hasAttribute(e.name)&&t.removeAttribute(e.name),n[e.name]}function Lt(t,e,n){(t._sapTransient||(t._sapTransient={}))[e.name]=n,t.hasAttribute(e.name)&&t.removeAttribute(e.name)}function ut(t,e,n){let r=String(n).split("."),s=r[r.length-1];if(r.length===1){let k=Re(e,s);return k||(t.getAttribute("items")===s?t:t.querySelector(`[items="${s}"]`))}let i=r[r.length-2],a=[...t.querySelectorAll(`[scope="${i}"]`)].find(k=>it(k,s));return a?it(a,s):null}function Re(t,e){let n=I(t);for(;n;){if(n.getAttribute("items")===e)return n;let r=it(n,e);if(r)return r;n=I(n.parentElement)}return null}function B(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 yt(t,e){return Array.isArray(t)?e==null?t:t.map(n=>typeof e=="function"?e(n):n?.[e]):[]}function Ht(t,e){return yt(t,e).reduce((n,r)=>n+B(r),0)}function Me(t,e){return Array.isArray(t)?e==null?t.length:t.reduce((n,r)=>n+(e(r)?1:0),0):0}function De(t,e){let n=yt(t,e);return n.length?Ht(t,e)/n.length:0}function Ie(t,e){let n=yt(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,s)=>String(r)<=String(s)?r:s):0}function We(t,e){let n=yt(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,s)=>String(r)>=String(s)?r:s):0}function Fe(t,e,n){let r=B(t)===1?e:n??e+"s";return`${t} ${r}`}function Pe(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 H(t){return typeof t=="number"?t:Number(t)}var ct={usd:t=>"$"+H(t).toLocaleString("en-US",{maximumFractionDigits:0}),usd2:t=>"$"+H(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),pct:t=>Math.round(H(t))+"%",pct1:t=>H(t).toFixed(1)+"%",int:t=>Math.round(H(t)).toLocaleString("en-US"),num:t=>H(t).toLocaleString("en-US"),num2:t=>H(t).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2}),compact:t=>H(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=H(t),n=Math.floor(e/100),r=n%10,s=Math.floor(n/10)%60;return`${Math.floor(n/600)}:${String(s).padStart(2,"0")}.${r}`}},Oe=new Set(["usd","usd2","pct","pct1","int","num","num2","compact","clock"]);function Ut(t,e){if(!t)return e==null?"":String(e);let n=ct[t];if(typeof n!="function"){let r=new Error(`unknown format "${t}"`);throw r.sapCode="E22",r}if(Oe.has(t)){let r=typeof e=="number"?e:Number(e);if(!Number.isFinite(r)){let s=new Error(`format "${t}" received ${typeof e=="string"?`"${e}"`:e}`);throw s.sapCode="E22",s}}return n(e)}function jt(){return[ct,B,Ht,Me,De,Ie,We,Fe,Pe]}var Be=["state","item","el","root","fmt","num","sum","count","avg","min","max","plural","days"],wt=new Map,Vt=/\bstate\.([a-z][a-z0-9_]*)/g,Yt=/\bitem\.([a-z][a-z0-9_]*)/g;function qe(t){let e=new Set,n=new Set,r;for(Vt.lastIndex=0;r=Vt.exec(t);)e.add(r[1]);for(Yt.lastIndex=0;r=Yt.exec(t);)n.add(r[1]);return{state:e,item:n}}function D(t,e=!1){let n=(e?"!":"")+t,r=wt.get(n);if(r)return r;wt.size>512&&wt.clear();try{let s=e?`"use strict";
2
+ ${t}`:`"use strict"; return (${t});`;r={fn:new Function(...Be,s),src:t,statement:e,deps:qe(t),error:null}}catch(s){r={fn:null,src:t,statement:e,deps:{state:new Set,item:new Set},error:s}}return wt.set(n,r),r}function U(t,e){if(t.error)throw t.error;return t.fn(e.state,e.item,e.el??null,e.root,...jt())}function Gt(t){let e=new Map;for(let a of t)e.set(a.name,a);let n=[],r=new Map,s=[];function i(a){let k=r.get(a.name);if(k!==1){if(k===0){let E=[...s.slice(s.indexOf(a.name)),a.name].join(" -> "),w=new Error(`calc: cycle: ${E}`);throw w.sapCode="E07",w.cycle=E,w}r.set(a.name,0),s.push(a.name);for(let E of a.entry.deps.state){let w=e.get(E);w&&w!==a&&i(w)}for(let E of a.entry.deps.item){let w=e.get(E);w&&w!==a&&i(w)}s.pop(),r.set(a.name,1),n.push(a)}}for(let a of t)i(a);return n}function Xt(t){return(t.getAttribute("type")||"text").toLowerCase()}function et(t){let e=t.tagName;if(e==="INPUT"){let n=Xt(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 Kt(t,e=t){let n=t.tagName;if(n==="INPUT"){let r=Xt(t);r==="checkbox"||r==="radio"?e.checked?t.setAttribute("checked",""):t.removeAttribute("checked"):t.setAttribute("value",e.value);return}if(n==="TEXTAREA"){t.textContent=e.value,t.removeAttribute("data-value");return}if(n==="SELECT"){let r=t.options,s=e.options;for(let i=0;i<r.length;i++)s[i]&&s[i].selected?r[i].setAttribute("selected",""):r[i].removeAttribute("selected")}}function At(t){t.tagName!=="TEXTAREA"||!t.hasAttribute("data-value")||t!==t.ownerDocument.activeElement&&(t.textContent=t.getAttribute("data-value"),t.removeAttribute("data-value"))}function W(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 Ct=["clay:mutation-ready","hyperclay:mutation-ready"],ze=["clay:sync-applied","hyperclay:livesync-applied"],He=["clay:ready","hyperclay:ready"];function ft(t,e,n){let r=null,s=i=>{r!==null&&r!==i.type||(r=i.type,queueMicrotask(()=>{r=null}),n(i))};for(let i of e)t.addEventListener(i,s);return()=>{for(let i of e)t.removeEventListener(i,s)}}function vt(t){let e=W("region");return!e||typeof e.resolveRegionPolicy!="function"||typeof e.skipForPolicy!="function"?!1:e.skipForPolicy(e.resolveRegionPolicy(t),void 0,["no-save","freeze"])}function Jt(){let t=W("consent");return typeof t=="function"?t:null}function Qt(t,e){if(typeof e!="function")throw new Error("Sap.batch(label, fn): fn must be a function");let n=W("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 Zt(t){if(typeof window>"u"||typeof document>"u")return;let e=()=>{let i=!1;for(let a of t.apps())a.root.isConnected?t.runNow(a,"platform"):i=!0;i&&(t.pruneDisconnected(),t.remountIfPresent())};ft(document,ze,e);let n=!1,r=()=>{},s=()=>{if(n)return!0;let i=W("undo");if(!i||typeof i.on!="function")return!1;let a=i.on("undo",e);return typeof a!="function"?!1:typeof i.on("redo",e)!="function"?(a(),!1):(n=!0,r(),!0)};if(!s()){let i=ft(document,Ct,s),a=ft(document,He,s);r=()=>{i(),a()};let k=W("ready");k&&typeof k.then=="function"&&k.then(s,()=>{})}}function Ue(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 je(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 Ve(t,e){switch(e){case"checkbox":return t.checked;case"radio":return t.checked?t.value:void 0;case"number":return je(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 Ye(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 s of t.options)s.selected=r.has(s.value);break}case"leaf":t.textContent=n==null?"":String(n);break;default:t.value=n==null?"":String(n)}}function te(t){if(t.hasAttribute("transient")){t.removeAttribute("value"),t.removeAttribute("checked"),t.removeAttribute("data-value");return}vt(t)||et(t)}function Ge(t){t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function M(t){let e=Ue(t);return{el:t,kind:e,read(){return Ve(t,e)},write(n,r={}){Ye(t,e,n),r.noMirror||te(t),r.silent||Ge(t)},mirror(){te(t)}}}var Rt={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"},W03:{slug:"unknown-colon-attribute",behavior:"WARN"},W04:{slug:"expression-in-when",behavior:"WARN"},W30:{slug:"nonzero-mount-writes",behavior:"WARN"}},Et=["disabled","readonly","required","checked","selected","multiple","open","inert","autofocus","novalidate","hidden"],lt=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"]),St=new Set(["sap","scope","items","item","template","bind","calc","text","show","attr","set","trigger","move","sort","detail","effect","invalid","confirm","transient","default","persist","sortable","editmode"]);function xt(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 s=n.tagName.toLowerCase();if(n.hasAttribute("sap"))s+="[sap]";else if(n.parentElement){let i=[...n.parentElement.children].filter(a=>a.tagName===n.tagName);i.length>1&&(s+=`:nth-of-type(${i.indexOf(n)+1})`)}if(e.unshift(s),n.hasAttribute("sap"))break;n=n.parentElement,r++}return e.join(" > ")}function ee(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 nt=class{constructor(e){this.appName=e,this.errors=[],this.warnings=[],this.halted=!1,this.haltReason=null}block(e,n,r={}){let s=(Rt[e]||{}).slug||"error",i={code:e,slug:s,el:xt(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=[`
3
+ `+(e[0]==="W"?"sap \u26A0 ":"sap \u2717 ")+e+" "+s];return a.push(` at ${i.el}${i.attr?` \u2014 ${i.attr}="${i.expr??""}"`:""}`),i.problem&&a.push(` problem: ${i.problem}`),i.didYouMean&&a.push(` did you mean: ${i.didYouMean}`),i.fix&&a.push(` fix: ${i.fix}`),console.error(a.join(`
4
+ `)),i}error(e,n,r={}){let s=this.block(e,n,r);return this.errors.push(s),s}warn(e,n,r={}){let s=this.block(e,n,r);return this.warnings.push(s),s}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 X(t,e){t&&t.getAttribute("sap-error")!==e&&t.setAttribute("sap-error",e)}function $t(t){t&&t.hasAttribute("sap-error")&&t.removeAttribute("sap-error")}function dt(t,e){let n=null,r=3;for(let s of e){let i=Xe(t,s);i<r&&(r=i,n=s)}return n}function Xe(t,e){let n=t.length,r=e.length,s=Array.from({length:n+1},(i,a)=>[a,...new Array(r).fill(0)]);for(let i=0;i<=r;i++)s[0][i]=i;for(let i=1;i<=n;i++)for(let a=1;a<=r;a++)s[i][a]=Math.min(s[i-1][a]+1,s[i][a-1]+1,s[i-1][a-1]+(t[i-1]===e[a-1]?0:1));return s[n][r]}var j=null,Nt=!1,rt=null;function ne(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 Ke(){let t=null;return{kind:"native",subscribe(e){t=new MutationObserver(r=>e(Je(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=W("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 Je(t){let e=[];for(let n of t)if(n.type==="attributes"){let r=n.target;r&&r.nodeType===1&&!kt(r)&&e.push({type:"attribute",element:r})}else if(n.type==="characterData"){let r=n.target&&n.target.parentElement;r&&!kt(r)&&e.push({type:"characterData",element:r})}else if(n.type==="childList"){for(let r of n.addedNodes)if(!(r.nodeType!==1||kt(r))&&(e.push({type:"add",element:r}),r.querySelectorAll))for(let s of r.querySelectorAll("*"))kt(s)||e.push({type:"add",element:s});for(let r of n.removedNodes)r.nodeType===1&&e.push({type:"remove",element:r,parent:n.target})}return e}function kt(t){return!!(t.closest&&t.closest("[sap-ignore],[template]"))}function Qe(t,e){t.pruneDisconnected();let n=new Set,r=!1;for(let s of e){let i=s.type==="remove"?s.parent:s.element,a=i&&t.appFor(i);a&&n.add(a),s.type==="add"&&s.element&&s.element.nodeType===1&&s.element.hasAttribute&&s.element.hasAttribute("sap")&&!(t.isRegistered&&t.isRegistered(s.element))&&(r=!0)}r&&t.remountIfPresent();for(let s of n)s.root.isConnected&&t.schedule(s,"mutation")}function re(t){if(j)return j.suppress(t);let e=W("undo");if(e&&e.pause&&e.resume){e.pause();try{return t()}finally{e.resume()}}return t()}function Mt(t,e){Nt=!0,j=t,t.subscribe(n=>Qe(e,n))}function Dt(t){if(Nt||typeof window>"u"||typeof document>"u")return;let e=W("Mutation");if(e&&typeof e.onAnyChange=="function"){Mt(ne(e),t);return}typeof MutationObserver=="function"&&(Mt(Ke(),t),rt=ft(document,Ct,function(){let r=W("Mutation");r&&(rt(),rt=null,j&&j.teardown(),Nt=!1,Mt(ne(r),t))}))}function oe(){if(j)try{j.teardown()}catch{}rt&&typeof document<"u"&&rt(),j=null,Nt=!1,rt=null}var ae=new Set(Et);function ot(t,e={}){if(e.breaker){t.diag.error("E26",t.root,{problem:"recompute loop halted after 50 passes; recent triggers: "+(t._breakerRing||[]).join(", ")}),X(t.root,"loop");return}re(()=>Ze(t,e))}function Ze(t,e){let n=t.root,r={},s=[],i=[],a=[],k=[],E=[],w=new Set;t.diag.errors=[];let l={root:r,state:r,item:null,ownerEl:n,projection:!1};function y(o,u){let h=o.getAttribute(u.name);return h==null&&(h=u.default!=null?u.default:u.type==="num"?"0":u.type==="bool"?"false":"",E.push({el:o,name:u.name,value:bt(G(h,u.type),u.type)})),G(h,u.type)}function N(o,u){let h=P(o.getAttribute("state")||"");o._sapStateDecls=h;for(let p of h){if(p.type==="string"&&ae.has(p.name)&&typeof o[p.name]=="boolean"){u[p.name]=o.hasAttribute(p.name);continue}if(p.transient){u[p.name]=gt(o,p);continue}u[p.name]=y(o,p)}}function L(o,u){if(!o.hasAttribute("bind"))return;let h=o.getAttribute("bind"),p=u.item||u.state,v=M(o);v.kind==="radio"?(h in p||(p[h]=""),o.checked&&(p[h]=o.value)):p[h]=v.read(),o.hasAttribute("transient")&&(o.removeAttribute("value"),o.removeAttribute("checked"))}function b(o,u){for(let h of o.attributes){let p=h.name,v=h.value;if(p.startsWith("calc:"))s.push({owner:u.item||u.state,ownerEl:u.ownerEl,name:p.slice(5),entry:D(v),el:o,ctx:u});else if(p==="text"||p.startsWith("text:"))i.push({el:o,kind:"text",fmt:p.includes(":")?p.slice(5):null,entry:D(v),ctx:u});else if(p==="show")i.push({el:o,kind:"show",entry:D(v),ctx:u});else if(p.startsWith("attr:"))i.push({el:o,kind:"attr",arg:p.slice(5),entry:D(v),ctx:u});else if(p.startsWith("class:"))i.push({el:o,kind:"class",arg:p.slice(6),entry:D(v),ctx:u});else if(p.startsWith("css:"))i.push({el:o,kind:"css",arg:p.slice(4),entry:D(v),ctx:u});else if(p==="effect")a.push({el:o,entry:D(v,!0),ctx:u});else if(p==="invalid")k.push({el:o,entry:D(v),ctx:u});else if(p.startsWith("show-when:")||p.startsWith("option:")){let T=p.slice(p.indexOf(":")+1);w.add(T),i.push({el:o,kind:"when",match:"show",field:T,values:v.split("|"),ctx:u})}else if(p.startsWith("hide-when:")){let T=p.slice(p.indexOf(":")+1);w.add(T),i.push({el:o,kind:"when",match:"hide",field:T,values:v.split("|"),ctx:u})}else if(p.startsWith("option-not:")){let T=p.slice(p.indexOf(":")+1);w.add(T),i.push({el:o,kind:"when",match:"show-not",field:T,values:v.split("|"),ctx:u})}}u.projection&&o.hasAttribute("bind")&&i.push({el:o,kind:"projection",field:o.getAttribute("bind"),ctx:u})}function g(o,u,h){Z(u,"row"),Object.defineProperty(o,"$key",{value:u.id,enumerable:!1}),Object.defineProperty(o,"$index",{value:h,enumerable:!1}),Object.defineProperty(o,"$el",{value:u,enumerable:!1})}function c(o,u,h){N(o,u),o._sapScope=u,!h.projection&&o.hasAttribute("bind")&&L(o,h),b(o,h),o.hasAttribute("items")?x(o,u,h):A(o,u,h)}function A(o,u,h){F(o,(p,v)=>{v?p.hasAttribute("scope")?S(p,u,h):p.hasAttribute("items")?(b(p,h),x(p,u,h)):p.hasAttribute("detail")&&R(p,u,h):(h.projection||L(p,h),b(p,h))})}function S(o,u,h){let p=o.getAttribute("scope"),v={};u[p]=v;let T={root:h.root,state:v,item:null,ownerEl:o,projection:h.projection};c(o,v,T)}function x(o,u,h){let p=o.getAttribute("items"),v=[];u[p]=v,o._sapList=v,O(o).forEach((T,st)=>{let C={};g(C,T,st);let z={root:h.root,state:h.state,item:C,ownerEl:T,projection:h.projection};c(T,C,z),v.push(C)})}function $(o,u){let h=String(o).split("."),p=u.state;for(let v of h)p=p?.[v];if(p===void 0){p=u.root;for(let v of h)p=p?.[v]}return p}function R(o,u,h){for(let Q of P(o.getAttribute("state")||""))Q.name in u||(u[Q.name]=y(o,Q));o._sapScope=u;let p=o.getAttribute("detail")||"",v=/^([\w.]+)\s+by\s+(.+)$/.exec(p);if(!v){o.hidden=!0,o._sapDetailRow=null;return}let T=v[1],st=v[2].trim(),C=$(T,h),z;try{z=U(D(st),{state:u,item:h.item,el:o,root:h.root})}catch{z=void 0}let J=Array.isArray(C)?C.find(Q=>Q&&String(Q.$key)===String(z)):null;if(o._sapDetailRow=J?J.$el:null,!J){o.hidden||(o.hidden=!0);return}o.hidden&&(o.hidden=!1);let qt={root:h.root,state:u,item:J,ownerEl:J.$el,projection:!0};b(o,qt),A(o,J,qt)}if(c(n,r,l),E.length&&w.size)for(let o of E)w.has(o.name)&&o.el.getAttribute(o.name)==null&&o.el.setAttribute(o.name,o.value);let m=new Map;for(let o of s){let u=m.get(o.owner);u||(u={ownerEl:o.ownerEl,list:[]},m.set(o.owner,u)),u.list.push(o)}let d=[...m.values()].sort((o,u)=>ie(u.ownerEl)-ie(o.ownerEl));for(let o of d){let u;try{u=Gt(o.list)}catch(h){t.diag.error("E07",o.list[0].el,{problem:h.message}),u=o.list}for(let h of u)try{h.owner[h.name]=U(h.entry,{state:h.ctx.state,item:h.ctx.item,el:h.el,root:h.ctx.root}),$t(h.el)}catch(p){h.owner[h.name]=void 0,t.diag.error("E24",h.el,{attr:"calc:"+h.name,expr:h.entry.src,problem:String(p.message)}),X(h.el,p.sapCode||"E24")}}let f=0;for(let o of i)f+=nn(o,t);for(let o of a)rn(o,t);for(let o of k)on(o);t._state=r,t._stats={fields:Object.keys(r).filter(o=>typeof r[o]!="function").length,calcs:s.length,paints:i.length,lists:m.size,writes:f},t._lastPass={trigger:e.trigger||"refresh",writes:f},t._debug&&console.log(`sap pass \xB7 trigger: ${t._lastPass.trigger} \xB7 writes ${f}/${i.length}`)}function tn(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 It(t,e,n,r){let s=t;for(;s&&s.nodeType===1;){if(s.hasAttribute&&s.hasAttribute(e)){let i=n.includes(s.getAttribute(e));if(r?!i:i)return!0}s=s.parentElement}return!1}function en(t,e){if(t===t.ownerDocument.activeElement)return 0;let n=M(t),r=n.read(),s=e??"";return String(r)!==String(s)?(n.write(s,{silent:!0}),1):0}function nn(t,e){if(t.kind==="projection")return en(t.el,t.ctx.item?t.ctx.item[t.field]:"");if(t.kind==="when")return se(t,null);let n={state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root};try{let r=U(t.entry,n),s=se(t,r);return $t(t.el),s}catch(r){return e.diag.error(r.sapCode==="E22"?"E22":"E24",t.el,{attr:tn(t),expr:t.entry&&t.entry.src,problem:String(r.message)}),X(t.el,r.sapCode||"E24"),0}}function se(t,e){let n=t.el;switch(t.kind){case"text":{let r=t.fmt!=null?Ut(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=W("optionVisibility");if(r&&r._started)return n._sapWhen&&n.hidden?(n.hidden=!1,n._sapWhen=!1,1):0;let s;t.match==="hide"?s=!It(n,t.field,t.values,!1):t.match==="show-not"?s=It(n,t.field,t.values,!0):s=It(n,t.field,t.values,!1),n._sapWhen=!0;let i=!s;return n.hidden!==i?(n.hidden=i,1):0}case"attr":{let r=t.arg;if(ae.has(r)){let i=n.hasAttribute(r);return e&&!i?(n.setAttribute(r,""),1):!e&&i?(n.removeAttribute(r),1):0}let s=typeof e=="boolean"?String(e):e==null?"":String(e);return n.getAttribute(r)!==s?(n.setAttribute(r,s),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 rn(t,e){try{U(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root}),$t(t.el)}catch(n){e.diag.error("E24",t.el,{attr:"effect",expr:t.entry&&t.entry.src,problem:String(n.message)}),X(t.el,"E24")}}function on(t){let e="";try{let n=U(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 ie(t){let e=0,n=t;for(;n&&!(n.hasAttribute&&n.hasAttribute("sap"));)n=n.parentElement,e++;return e}var sn=new Set(Et),ue=new Set(["calc","text","attr","class","css","set","move","sort","option","option-not","show-when","hide-when","editmode"]),an=new Set(["show-when","hide-when","option","option-not"]),un=/\b(?:state|item|root)\.|===|!==|&&|\|\||[()]|^\s*!/,ce=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 cn(t){return t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA"}function Wt(t){return t.hasAttribute("bind")}function fn(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 s of r.children)n(s)}}}function Tt(t,e){let n=!1,r=(a,k,E)=>{e.error(a,k,E),n=!0},s=t.ownerDocument.createTreeWalker(t,4),i;for(;i=s.nextNode();)if(/\{\{.*\}\}/.test(i.nodeValue||"")){r("E02",i.parentElement||t,{problem:"moustaches in text content are not a Sap feature",fix:'move the expression onto the element: text="state.x"'});break}return fn(t,a=>{let k=a.closest&&a.closest("[detail]");for(let E of[...a.attributes]){let w=E.name,l=ee(w);if(l){r("E01",a,{attr:w,expr:E.value,problem:`"${w}" is a foreign-dialect attribute; Sap has no ${w.split(/[:=]/)[0]} directive`,fix:l+" \u2014 or wrap the subtree in sap-ignore if intentional"});continue}if(w.includes(":")){let y=w.slice(0,w.indexOf(":"));if(ue.has(y)){if(an.has(y)&&un.test(E.value)){let N=w.slice(w.indexOf(":")+1);e.warn("W04",a,{attr:w,expr:E.value,problem:`${y}: compares the "${N}" attribute against a literal value, not a JS expression`,fix:`use show="${E.value}" for an expression, or a literal like ${y}:${N}="overview"`})}}else{let N=dt(y,[...ue]);e.warn("W03",a,{attr:w,problem:`unknown "${y}:" attribute`,didYouMean:N?`${N}:`:null})}}else if(!ce.has(w)&&!lt.has(w)&&!sn.has(w)&&!/^(data-|aria-|on)/.test(w)&&!(w in a)){let y=dt(w,[...ce]);y&&e.warn("W03",a,{attr:w,problem:`unknown "${w}" attribute`,didYouMean:y})}w==="attr:hidden"&&e.warn("W03",a,{attr:w,problem:"attr:hidden paints the wrong attribute",fix:'use show="expr"'}),(w==="attr:value"||w==="attr:checked"||w==="attr:selected")&&Wt(a)&&r("E30",a,{attr:w,problem:"attr: on a bound control collides with persist ownership",fix:"remove it; bind owns this attribute"}),w==="effect"&&Wt(a)&&/\b(value|checked)\s*=[^=]/.test(E.value)&&r("E30",a,{attr:w,expr:E.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"}),(w==="text"||w.startsWith("text:")||w==="show")&&cn(a)&&(w==="show"||r("E18",a,{attr:w,problem:"paint belongs on output elements, not form controls",fix:"move the paint to an <output> or <span>"}))}if(a.hasAttribute("state")){let E=P(a.getAttribute("state")),w=new Set;for(let l of E)l.name.includes("-")&&r("E08",a,{attr:"state",problem:`field "${l.name}" is not a valid identifier (the hyphen parses as subtraction)`,fix:`rename to ${l.name.replace(/-/g,"")}`}),w.has(l.name)&&r("E04",a,{attr:"state",problem:`field "${l.name}" is declared twice in one scope`}),w.add(l.name),St.has(l.name)&&r("E05",a,{attr:"state",problem:`"${l.name}" is a reserved Sap word`}),lt.has(l.name)&&r("E06",a,{attr:"state",problem:`"${l.name}" is a global HTML attribute name; pick another field name`}),l.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"})}if(Wt(a)){if(a.hasAttribute("-"),a.tagName==="INPUT"){let E=(a.getAttribute("type")||"text").toLowerCase();E==="file"&&r("E32",a,{attr:"bind",problem:"files never serialize into an HTML file",fix:"use no-save + effect instead of bind"}),E==="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 E=a.getAttribute("contenteditable");!(E!=null&&E!=="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.hasAttribute("item")&&!a.hasAttribute("template")){let E=a.parentElement;(!E||!E.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")&&k&&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 E=t.querySelector(`[trigger-add="${a.getAttribute("items")}"]`);!ht(a)&&O(a).length===0&&E&&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",X(t,e.haltReason)),!n}var fe="sap-styles",le="[item][template]{display:none!important}[hidden]{display:none!important}[sap-error]{outline:2px solid #e5484d;outline-offset:1px}",Ft=new WeakSet;function ln(t){if(Ft.has(t))return;let e=t.defaultView,n=e&&e.CSSStyleSheet;if(n&&"adoptedStyleSheets"in t)try{let r=new n;r.replaceSync(le),t.adoptedStyleSheets=[...t.adoptedStyleSheets,r],Ft.add(t);return}catch{}if(!t.getElementById(fe)){let r=t.createElement("style");r.id=fe,r.textContent=le,(t.head||t.documentElement).appendChild(r)}Ft.add(t)}var dn=0;function de(){return typeof performance<"u"&&performance.now?performance.now():0}function Pt(t){let e=t.id||t.getAttribute("sap")||`app-${dn++}`,n=new nt(e),r={root:t,name:e,diag:n,_state:null,_stats:null,_lastPass:null,_passes:0,_broken:!1,_mountMs:0,_mountWrites:0};if(!Tt(t,n))return r.halted=!0,r;ln(t.ownerDocument);for(let a of t.querySelectorAll("textarea[data-value]"))At(a);let i=de();return ot(r,{trigger:"mount"}),r._mountMs=de()-i,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 pn(t,e){let n=null;return F(t,r=>{!n&&r.getAttribute("scope")===e&&(n=r)}),n}function pe(t,e,n){let r=I(t)||e;for(;r;){for(let s of P(r.getAttribute("state")||""))if(s.name===n)return{el:r,decl:s};if(r.hasAttribute("sap"))break;r=I(r.parentElement)}return null}function mn(t){return typeof t=="number"?"num":typeof t=="boolean"?"bool":"string"}function me(t){function e(b){let g=t.appFor(b);if(!g)return null;let c=at(b);if(c)return c._sapDetailRow?{ctxEl:c._sapDetailRow,appRec:g,isRow:!0}:{ctxEl:I(c.parentElement)||g.root,appRec:g,isRow:!1};let A=mt(b);if(A&&A.hasAttribute("item"))return{ctxEl:A,appRec:g,isRow:!0};let S=I(b)||g.root;return{ctxEl:S,appRec:g,isRow:S.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?L(c.ctxEl,c.appRec,c.isRow):null}function r(b,g,c){let A=tt(b,c);if(A)return M(A).read();let S=it(b,c);if(S)return O(S).map(m=>L(m,g,!0));let x=pn(b,c);if(x)return L(x,g,!1);let $=pe(b,g.root,c);if($)return $.decl.transient?gt($.el,$.decl):G($.el.getAttribute(c),$.decl.type);let R=b._sapScope;return R?R[c]:void 0}function s(b,g,c,A,S){A.transient?Lt(b,A,c):b.setAttribute(g,bt(c,A.type)),t.schedule(S,"set:"+g)}function i(b,g){let c=new Set,A=I(b)||g;for(;A;){for(let S of P(A.getAttribute("state")||""))c.add(S.name);if(A.hasAttribute("sap"))break;A=I(A.parentElement)}return F(b,S=>{let x=S.getAttribute("bind");x&&c.add(x)}),c}function a(b,g,c,A){let S=tt(b,c);if(S){M(S).write(A);return}let x=b;for(;x;){for(let h of x.attributes)if(h.name==="calc:"+c){g.diag.error("E16",x,{attr:"calc:"+c,problem:`"${c}" is a computed field; computed fields are read-only`});return}if(x.hasAttribute("sap"))break;x=x.parentElement}let $=pe(b,g.root,c);if($){s($.el,c,A,$.decl,g);return}let R=i(b,g.root);R.delete(c);let m=c.length>=4?dt(c,[...R]):null;if(m){g.diag.error("E12",b,{key:c,problem:`unknown state key "${c}"`,didYouMean:m});return}if(St.has(c)||lt.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 d=g.root,f=mn(A),o=d.getAttribute("state")||"",u=f==="string"?c:`${c}:${f}`;d.setAttribute("state",o?`${o} ${u}`:u),s(d,c,A,{name:c,type:f,transient:!1},g)}function k(b){let g=c=>{c.id&&(c.id="",Z(c,"row")),c.hasAttribute("sap-error")&&c.removeAttribute("sap-error")};b.id="",Z(b,"row"),b.querySelectorAll("[id]").forEach(g)}function E(b,g,c){let A=ut(g.root,b,c);if(!A)return g.diag.error("E17",b,{problem:`cannot resolve a list named "${c}" from here`}),null;let S=ht(A);if(!S)return g.diag.error("E17",A,{problem:`items="${c}" has no [item template] to clone`}),null;let x=S.cloneNode(!0);return x.removeAttribute("template"),k(x),A.appendChild(x),t.schedule(g,"trigger-add:"+c),L(x,g,!0)}function w(b,g){F(b,c=>{if(c.hasAttribute("bind")){let A=M(c),S=c.getAttribute("default");A.kind==="checkbox"||A.kind==="radio"?A.write(S!=null?S===""||S==="true"||c.value===S:c.hasAttribute("checked")):A.write(S??(c.getAttribute("value")||""))}});for(let c of P(b.getAttribute("state")||"")){let A=c.default!=null?c.default:c.type==="num"?"0":c.type==="bool"?"false":"";c.transient?Lt(b,c,G(A,c.type)):b.setAttribute(c.name,A)}t.schedule(g,"trigger-reset")}function l(b,g){if(!b.isConnected)throw new Error("stale row handle: $remove() on a removed row");b.remove(),t.schedule(g,"trigger-remove")}function y(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=ut(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?O(g).indexOf(b):-1}function L(b,g,c){let A={get $el(){return b},get $key(){return Z(b,c?"row":"scope")},get $index(){return N(b)},$add(x){return E(b,g,x)},$reset(){return w(b,g),S},$remove(){l(b,g)},$move(x){y(b,g,x)},get $appRec(){return g}},S=new Proxy(A,{get(x,$){return typeof $=="symbol"||$[0]==="$"?x[$]:r(b,g,$)},set(x,$,R){return typeof $=="string"&&$[0]==="$"?(x[$]=R,!0):(a(b,g,$,R),!0)},has(x,$){return typeof $=="string"&&$[0]==="$"?$ in x:r(b,g,$)!==void 0}});return S}return{Sap:n,contextElFor:e,readField:r,writeField:a,makeProxy:L}}var hn=["trigger-add","trigger-remove","trigger-reset"];function bn(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:")||hn.includes(n))return!0}return!1}function gn(t,e){let n=t,r=e.parentElement;for(;n&&n!==r;){if(n.nodeType===1&&bn(n)&&!(n.tagName==="FORM"&&n.hasAttribute("trigger-add")))return n;n=n.parentElement}return null}function he(t,e){let{Sap:n}=e;function r(m,d){let f=null,o=at(m);if(o&&o._sapDetailRow)f=o._sapDetailRow._sapScope||null;else{let p=mt(m);p&&p.hasAttribute("item")&&(f=p._sapScope||null)}return{state:(I(m)||d.root)._sapScope||d._state||{},item:f,el:m,root:d._state||{}}}function s(m,d,f){if(!m.hasAttribute("confirm")){f();return}let o=m.getAttribute("confirm"),u=o,h=D(o);if(!h.error)try{let T=U(h,r(m,d));(typeof T=="string"||typeof T=="number")&&(u=String(T))}catch{}let p=Jt();if(!p){window.confirm(u)&&f();return}if(m._sapGatePending)return;m._sapGatePending=!0;let v=()=>{m._sapGatePending=!1};p(u,()=>{v(),f()}).catch(v)}function i(m,d){for(let f of m.attributes){if(!f.name.startsWith("set:"))continue;let o=f.name.slice(4),u=D(f.value);if(u.error){d.diag.error("E08",m,{attr:f.name,expr:f.value,problem:String(u.error.message)});continue}let h;try{h=U(u,r(m,d))}catch(v){d.diag.error("E24",m,{attr:f.name,expr:f.value,problem:String(v.message)});continue}let p=n(m);p&&(p[o]=h)}}function a(m,d){let f=m.closest("[item]");if(!f)return;let o=O(f.parentElement),u=o.indexOf(f);d==="up"&&u>0?t.placeBefore(f,o[u-1]):d==="down"&&u<o.length-1&&t.placeBefore(o[u+1],f)}function k(m,d,f){if(d)return ut(f.root,m,d);let o=m;for(;o;){if(o.hasAttribute&&o.hasAttribute("items"))return o;o=o.parentElement}let u=I(m)||f.root,h=[];return F(u,p=>{p.hasAttribute("items")&&h.push(p)}),h[0]||null}function E(m,d){let f=m==null||m==="",o=d==null||d==="";if(f&&o)return 0;if(f)return 1;if(o)return-1;let u=Number(m),h=Number(d);return!Number.isNaN(u)&&!Number.isNaN(h)?u-h:String(m)<String(d)?-1:String(m)>String(d)?1:0}function w(m,d,f,o){let u=k(m,f,o);if(!u){o.diag.error("E17",m,{attr:"sort:"+d,problem:`no items list resolvable for sort:${d}`});return}let h=O(u),p=C=>C._sapScope?C._sapScope[d]:void 0,v=[...h].sort((C,z)=>E(p(C),p(z))),st=v.every((C,z)=>C===h[z])?[...v].reverse():v;for(let C of st)t.moveInto(u,C);t.schedule(o,"sort:"+d)}function l(m){if(!m||m.hidden)return;let d=m.querySelector("[bind]:not([type=hidden]), [contenteditable]");d&&typeof d.focus=="function"&&d.focus()}function y(m,d){s(m,d,()=>{let f=n(m);for(let o of[...m.attributes]){let u=o.name;if(u==="trigger-remove")f&&f.$remove();else if(u==="trigger-reset")f&&f.$reset();else if(u==="trigger-add"){let h=f&&f.$add(o.value);h&&l(h.$el)}else u==="move:up"?(a(m,"up"),t.schedule(d,"move:up")):u==="move:down"?(a(m,"down"),t.schedule(d,"move:down")):u.startsWith("move:to")?f&&f.$move(o.value):u.startsWith("sort:")&&w(m,u.slice(5),o.value,d)}[...m.attributes].some(o=>o.name.startsWith("set:"))&&i(m,d)})}function N(m){let d=m.target;if(!d||d.nodeType!==1)return;let f=t.appFor(d);if(!f)return;let o=gn(d,f.root);o&&y(o,f)}function L(m){let d=M(m),f=m.getAttribute("default");d.kind==="checkbox"?d.write(f===""||f==="true"):d.write(f??"")}function b(m,d,f){let o=n(m);if(!o)return;let u=o.$add(f);if(!u)return;let h=[];F(m,p=>{p.hasAttribute("bind")&&h.push(p)});for(let p of h){let v=tt(u.$el,p.getAttribute("bind"));v&&M(v).write(M(p).read())}h.forEach(L),h.length?typeof h[0].focus=="function"&&h[0].focus():l(u.$el)}function g(m){let d=m.target;if(!d||!d.hasAttribute||!d.hasAttribute("trigger-add"))return;let f=t.appFor(d);f&&(m.preventDefault(),s(d,f,()=>b(d,f,d.getAttribute("trigger-add"))))}function c(m){let d=m.target,f=t.appFor(d);f&&setTimeout(()=>{d.querySelectorAll("[bind]").forEach(o=>{o.dispatchEvent(new Event("input",{bubbles:!0})),o.dispatchEvent(new Event("change",{bubbles:!0}))}),t.schedule(f,"reset")},0)}function A(m){let d=t.appFor(m.target);d&&t.schedule(d,"toggle")}function S(m){let d=m.target;if(!d||d.nodeType!==1)return;let f=t.appFor(d);if(!f)return;d.hasAttribute("persist")&&!vt(d)&&et(d);let o=at(d);if(o&&o._sapDetailRow&&d.hasAttribute("bind")){let u=tt(o._sapDetailRow,d.getAttribute("bind"));if(u&&u!==d){M(u).write(M(d).read());return}}t.schedule(f,m.type+" "+(d.id||d.tagName.toLowerCase()))}function x(m){let d=m.detail||{};for(let f of[d.from,d.to,m.target]){if(!f||f.nodeType!==1)continue;let o=t.appFor(f);o&&t.schedule(o,"sorted")}}function $(m){if(m.key!=="ArrowUp"&&m.key!=="ArrowDown")return;let d=m.target;if(!d||d.nodeType!==1||d.tagName!=="INPUT"||!d.hasAttribute("bind")||!d.hasAttribute("step"))return;let f=(d.getAttribute("type")||"text").toLowerCase();if(f!=="text"&&f!=="tel"&&f!=="search"||!t.appFor(d))return;m.preventDefault();let u=B(d.getAttribute("step"))||1,h=m.key==="ArrowUp"?1:-1,p=B(d.value)+u*(m.shiftKey?10:1)*h,v=d.getAttribute("min"),T=d.getAttribute("max");v!==null&&v!==""&&p<B(v)&&(p=B(v)),T!==null&&T!==""&&p>B(T)&&(p=B(T)),M(d).write(String(Number(p.toFixed(2))))}function R(m=document){m.addEventListener("click",N),m.addEventListener("submit",g),m.addEventListener("reset",c),m.addEventListener("toggle",A,!0),m.addEventListener("input",S),m.addEventListener("change",S),m.addEventListener("clay:sorted",x),m.addEventListener("keydown",$)}return{install:R}}var be=/^(set:|move:|sort:|trigger-add$|trigger-remove$|trigger-reset$)/;function Ot(t){return`${t.tagName.toLowerCase()}[sap]`}function yn(t){let e=0;for(let n of t.querySelectorAll("*"))for(let r of n.attributes)if(be.test(r.name)){e++;break}for(let n of t.attributes)if(be.test(n.name)){e++;break}return e}function ge(t){let e=[],n=r=>{for(let s of r.attributes){let i=s.name;(i.startsWith("calc:")||i==="text"||i.startsWith("text:")||i==="show"||i.startsWith("attr:")||i.startsWith("class:")||i.startsWith("css:")||i==="effect"||i==="invalid"||i.startsWith("set:")||i==="detail")&&e.push({el:r,attr:i,src:s.value})}};n(t);for(let r of t.querySelectorAll("*"))n(r);return e}function ye(t){function e(l){let y=l._stats||{},N=l.root;return{root:Ot(N),fields:y.fields||0,calcs:y.calcs||0,paints:y.paints||0,actions:yn(N),lists:(N.hasAttribute("items")?1:0)+N.querySelectorAll("[items]").length,rows:N.querySelectorAll("[item]:not([template])").length,warnings:l.diag.warnings.length,errors:l.diag.errors.length,mountWrites:l._mountWrites||0,ms:Math.round((l._mountMs||0)*10)/10,passes:l._passes||0,lastPass:l._lastPass||null,ok:l.diag.errors.length===0&&!l.halted}}function n(){let l=t.apps().map(e);return{ok:l.every(y=>y.ok),apps:l}}function r(l){let y=e(l);return y.ok?`sap \u2713 ${y.root} \xB7 fields ${y.fields} \xB7 calcs ${y.calcs} \xB7 paints ${y.paints} \xB7 actions ${y.actions} \xB7 lists ${y.lists} \xB7 rows ${y.rows} \xB7 warnings ${y.warnings} \xB7 mount writes ${y.mountWrites} \xB7 ${y.ms}ms`:`sap \u2717 ${y.root} \xB7 errors ${y.errors} \xB7 warnings ${y.warnings} \xB7 ${y.ms}ms`}function s(){for(let l of t.apps()){let y=r(l);l.diag.errors.length||l.halted?console.error(y):console.log(y)}}function i(){let l=[],y=[];for(let N of t.apps())l.push(...N.diag.errors),y.push(...N.diag.warnings);return{ok:l.length===0,errors:l,warnings:y,counts:{errors:l.length,warnings:y.length}}}function a(l){return l?typeof l=="string"?document.querySelector(l):l.nodeType===1?l:null:null}function k(l,y){let N=a(l);if(!N)return console.warn("sap why: element not found"),null;let L=[`sap why <${N.tagName.toLowerCase()}> \u2014 ${xt(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)L.push(` ${c.name}="${c.value}"`);let g=N;for(;g&&!g._sapScope;)g=g.parentElement;if(g&&g._sapScope){let c=g._sapScope,A=y?[y]:Object.keys(c);L.push(" reads:");for(let S of A){let x=c[S];typeof x!="function"&&L.push(` ${S} = ${JSON.stringify(Array.isArray(x)?`[${x.length} rows]`:x)}`)}}return L.push(" serialization: textContent and value/checked attributes save with the file; reads live from properties"),console.log(L.join(`
5
+ `)),null}function E(l){let y=l===void 0?!0:!!l;for(let N of t.apps())N._debug=y;return console.log(`sap debug ${y?"on":"off"} \u2014 per-pass headers will ${y?"":"no longer "}log`),y}function w(){let l=[],y=0;for(let c of t.apps()){let A=c.root,S=Ot(A);y++;let x=new nt(c.name);Tt(A,x);for(let f of x.errors)l.push({code:f.code,severity:"error",message:`${S}: ${f.code} ${f.slug} at ${f.el}`});for(let f of x.warnings)l.push({code:f.code,severity:"warn",message:`${S}: ${f.code} ${f.slug} at ${f.el}`});y++,ot(c,{trigger:"doctor-dryrun"});let $=c._stats?c._stats.writes:0;$>0&&l.push({code:"W30",severity:"warn",message:`${S}: dry recompute wrote ${$} cells on a quiet page; an element is stale or non-idempotent`}),y++;let R=ge(A).map(f=>f.src).join(" \0 "),m=[];for(let f of[A,...A.querySelectorAll("[state]")])for(let o of P(f.getAttribute("state")||""))m.push(o.name);for(let f of m)new RegExp(`(state|item)\\.${f}\\b`).test(R)||l.push({code:"I33",severity:"info",message:`${S}: field "${f}" is declared but read nowhere (dead state)`});y++;let d=new Map;for(let f of A.querySelectorAll("[id]"))d.set(f.id,(d.get(f.id)||0)+1);for(let[f,o]of d)o>1&&l.push({code:"W32",severity:"warn",message:`${S}: duplicate id "${f}" (${o} elements) \u2014 clone/edit collision`});y++;for(let f of ge(A))f.src.length>120&&l.push({code:"I33",severity:"info",message:`${S}: ${f.attr} expression is ${f.src.length} chars; consider a calc: field`});y++;for(let f of A.querySelectorAll("[text], [text\\:num]")){let o=f.textContent||"";/\.\d{5,}/.test(o)&&l.push({code:"I33",severity:"info",message:`${S}: ${xt(f)} paints >4 decimals; consider text:FMT`})}}let N=l.filter(c=>c.severity==="error").length,L=l.filter(c=>c.severity==="warn").length,b=l.filter(c=>c.severity==="info").length;console.log(`sap doctor \xB7 ${t.apps().map(c=>Ot(c.root)).join(", ")} \xB7 errors ${N} \xB7 warnings ${L} \xB7 info ${b} \xB7 ${y} checks \xB7 0ms`);for(let c of l)(c.severity==="error"?console.error:c.severity==="warn"?console.warn:console.info)(` ${c.severity==="error"?"\u2717":c.severity==="warn"?"\u26A0":"\xB7"} ${c.message}`);return l}return{status:n,report:i,why:k,debug:E,doctor:w,greenLine:r,printGreenLines:s,REGISTRY:Rt}}var wn="0.2.0",q=new Map,V=[],Bt=zt(ot);function An(t){let e=t;for(;e;){if(e.nodeType===1&&e.hasAttribute&&e.hasAttribute("sap"))return q.get(e)||null;e=e.parentNode&&e.parentNode.host?e.parentNode.host:e.parentElement}return null}function vn(){for(let t=V.length-1;t>=0;t--){let e=V[t];e.root.isConnected||(q.delete(e.root),V.splice(t,1))}}function En(t,e){if(t.moveBefore)try{t.moveBefore(e,null);return}catch{}t.appendChild(e)}function Sn(t,e){let n=e.parentElement;if(n){if(n.moveBefore)try{n.moveBefore(t,e);return}catch{}n.insertBefore(t,e)}}var K={apps:()=>V.slice(),appFor:An,isRegistered:t=>q.has(t),pruneDisconnected:vn,schedule:(t,e)=>Bt.schedule(t,e),runNow:(t,e)=>Bt.runNow(t,e),moveInto:En,placeBefore:Sn,remountIfPresent:()=>pt()},Ae=me(K),xn=he(K,Ae),Y=ye(K),we=!1;function ve(){we||(we=!0,xn.install(document),Zt(K))}function pt(t=document){ve(),Dt(K);let e=t.querySelectorAll("[sap]"),n=[];for(let r of e){if(q.has(r))continue;let s=Pt(r);q.set(r,s),V.push(s),n.push(s)}for(let r of n){let s=Y.greenLine(r);r.diag.errors.length||r.halted?console.error(s):console.log(s)}return n}function Ee(t){if(ve(),Dt(K),!t)return pt();let e=typeof t=="string"?document.querySelector(t):t;if(!e)return null;if(q.has(e))return q.get(e);let n=Pt(e);q.set(e,n),V.push(n);let r=Y.greenLine(n);return n.diag.errors.length||n.halted?console.error(r):console.log(r),n}var _=Ae.Sap;_.version=wn;_.refresh=function(){for(let e of V)e.root.isConnected&&Bt.runNow(e,"refresh")};_.batch=Qt;_.status=Y.status;_.report=Y.report;_.why=Y.why;_.debug=Y.debug;_.doctor=Y.doctor;_.greenLine=Y.greenLine;_.formats=ct;_.serializeControlToAttributes=et;_.finalizeControlForSave=Kt;_.rehydrateControlFromAttributes=At;_.mount=Ee;_.config=function(e={}){return e.formats&&Object.assign(ct,e.formats),_};_._registry=q;_._reset=function(){q.clear(),V.length=0,oe()};function $n(){typeof document>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>pt()):pt())}$n();typeof window<"u"&&(window.Sap=_);var kn=_;return Te(Nn);})();
6
6
  if (typeof window !== 'undefined' && Sap && Sap.default) window.Sap = Sap.default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panphora/sapjs",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "A reactive HTML library where the DOM is the only state store. Structure-first, one write path, transient rebuild. An Alpine alternative built for malleable, self-saving HTML.",
5
5
  "type": "module",
6
6
  "main": "src/sap.js",
@@ -16,8 +16,9 @@
16
16
  "scripts": {
17
17
  "build": "node build/bundle.mjs",
18
18
  "build:docs": "node scripts/build-doc.mjs",
19
- "copy-to-hyperclayjs": "npm run build && node scripts/copy-to-hyperclayjs.js",
20
- "copy-to-clayjs": "npm run build && node scripts/copy-to-clayjs.js",
19
+ "propagate": "npm run build && node scripts/propagate.js",
20
+ "copy-to-hyperclayjs": "npm run build && node scripts/propagate.js --only hyperclayjs",
21
+ "copy-to-clayjs": "npm run build && node scripts/propagate.js --only clayjs",
21
22
  "test": "jest",
22
23
  "test:watch": "jest --watch",
23
24
  "serve": "node build/bundle.mjs && python3 -m http.server 8123"
@@ -48,5 +49,10 @@
48
49
  "esbuild": "^0.21.0",
49
50
  "jest": "^29.7.0",
50
51
  "jest-environment-jsdom": "^29.7.0"
52
+ },
53
+ "hyper": {
54
+ "kind": "lib",
55
+ "status": "active",
56
+ "url": "https://saphtml.com"
51
57
  }
52
58
  }
@@ -2,8 +2,8 @@
2
2
  // means, not just its own delegated events. Two interchangeable backends sit behind
3
3
  // one MutationSource seam:
4
4
  //
5
- // - hubSource: when window.hyperclay.Mutation is present, ride the platform's
6
- // central, pause-gated observer. The hub already coordinates the
5
+ // - hubSource: when the platform's Mutation hub is present, ride its central,
6
+ // pause-gated observer. The hub already coordinates the
7
7
  // live-sync / undo pause windows, so we inherit them for free.
8
8
  // - nativeSource: standalone, a sapjs-owned MutationObserver on document.body.
9
9
  //
@@ -18,6 +18,8 @@
18
18
  // late (teardown + re-subscribe), so the two never observe at once. Degrades to a
19
19
  // plain no-op when neither a hub nor a MutationObserver is present.
20
20
 
21
+ import { capability, MUTATION_READY, onPlatformEvent } from "./platform.js";
22
+
21
23
  let activeSource = null;
22
24
  let installed = false;
23
25
  let lateHubListener = null;
@@ -55,7 +57,7 @@ function nativeSource() {
55
57
  suppress(fn) {
56
58
  // No hub to gate us: drop our own pass's records before the browser delivers them.
57
59
  // Pause undo too if it somehow exists hub-less (presence-guarded; normally it does not).
58
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
60
+ const u = capability("undo");
59
61
  if (u && u.pause) u.pause();
60
62
  try {
61
63
  return fn();
@@ -130,7 +132,7 @@ function scheduleAffectedApps(runtime, changes) {
130
132
  // historical undo-pause-if-present behavior so derived writes still stay off the undo stack.
131
133
  export function withDomMutationPaused(fn) {
132
134
  if (activeSource) return activeSource.suppress(fn);
133
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
135
+ const u = capability("undo");
134
136
  if (u && u.pause && u.resume) {
135
137
  u.pause();
136
138
  try { return fn(); } finally { u.resume(); }
@@ -148,8 +150,7 @@ function activate(source, runtime) {
148
150
  export function installMutationBridge(runtime) {
149
151
  if (installed) return;
150
152
  if (typeof window === "undefined" || typeof document === "undefined") return;
151
- const w = window;
152
- const M = w.hyperclay && w.hyperclay.Mutation;
153
+ const M = capability("Mutation");
153
154
 
154
155
  if (M && typeof M.onAnyChange === "function") { activate(hubSource(M), runtime); return; }
155
156
 
@@ -157,22 +158,23 @@ export function installMutationBridge(runtime) {
157
158
  // a hub is coming: another library may merely own that namespace (e.g. a consent shim)
158
159
  // and never publish a Mutation hub, which would strand us in a permanent wait with dead
159
160
  // reactivity. So observe natively now and CEDE to a real hub if one arrives later
160
- // (teardown + re-subscribe on the document-dispatched hyperclay:mutation-ready — a
161
+ // (teardown + re-subscribe on the document-dispatched mutation-ready — a
161
162
  // window-dispatched event is ignored, matching the hub's own target). The handoff is
162
163
  // safe: passes are idempotent, so the brief pre-hub native window costs at most a little
163
164
  // redundant work, never correctness, and the two never observe simultaneously.
164
165
  if (typeof MutationObserver === "function") {
165
166
  activate(nativeSource(), runtime);
166
- lateHubListener = function onLateHub() {
167
- const M2 = w.hyperclay && w.hyperclay.Mutation;
167
+ // lateHubListener holds the disposer, which unregisters BOTH spellings: dropping
168
+ // only the one that fired would leak the other under whichever client is loaded.
169
+ lateHubListener = onPlatformEvent(document, MUTATION_READY, function onLateHub() {
170
+ const M2 = capability("Mutation");
168
171
  if (!M2) return;
169
- document.removeEventListener("hyperclay:mutation-ready", lateHubListener);
172
+ lateHubListener();
170
173
  lateHubListener = null;
171
174
  if (activeSource) activeSource.teardown();
172
175
  installed = false;
173
176
  activate(hubSource(M2), runtime);
174
- };
175
- document.addEventListener("hyperclay:mutation-ready", lateHubListener);
177
+ });
176
178
  }
177
179
  // else: no DOM observer (SSR / ancient) -> event-only, exactly as before.
178
180
  }
@@ -182,7 +184,7 @@ export function installMutationBridge(runtime) {
182
184
  export function resetMutationBridge() {
183
185
  if (activeSource) { try { activeSource.teardown(); } catch { /* ignore */ } }
184
186
  if (lateHubListener && typeof document !== "undefined") {
185
- document.removeEventListener("hyperclay:mutation-ready", lateHubListener);
187
+ lateHubListener();
186
188
  }
187
189
  activeSource = null;
188
190
  installed = false;
package/src/pass.js CHANGED
@@ -10,6 +10,7 @@ import { carrierFor } from "./carrier.js";
10
10
  import { applyFormat } from "./helpers.js";
11
11
  import { NATIVE_BOOLEANS, setBeacon, clearBeacon } from "./errors.js";
12
12
  import { withDomMutationPaused } from "./mutation-bridge.js";
13
+ import { capability } from "./platform.js";
13
14
 
14
15
  const NATIVE_BOOLEAN_SET = new Set(NATIVE_BOOLEANS);
15
16
 
@@ -379,7 +380,7 @@ function applyPaint(p, value) {
379
380
  return 0;
380
381
  }
381
382
  case "when": {
382
- const ov = typeof window !== "undefined" && window.hyperclay && window.hyperclay.optionVisibility;
383
+ const ov = capability("optionVisibility");
383
384
  if (ov && ov._started) {
384
385
  // The CSS floor owns visibility now; clear any hidden we set pre-floor.
385
386
  if (el._sapWhen && el.hidden) { el.hidden = false; el._sapWhen = false; return 1; }
package/src/platform.js CHANGED
@@ -1,7 +1,42 @@
1
- // Optional Hyperclay integration. Everything here degrades to a no-op when
2
- // window.hyperclay is absent, so Sap runs standalone in any HTML file. When the
1
+ // Optional Hyperclay integration. Everything here degrades to a no-op when no
2
+ // platform client is present, so Sap runs standalone in any HTML file. When the
3
3
  // platform is present, Sap rides its live-sync, undo, and autosave for free.
4
4
 
5
+ // Two clients provide this API and they spell one of these capabilities
6
+ // differently: hyperclayjs owns window.hyperclay and calls the dialog consent();
7
+ // clayjs owns window.clay and calls it confirm(). Resolving `clay ?? hyperclay` as
8
+ // one namespace would land on clay and then find no consent, so a confirm-gated
9
+ // action would silently drop back to the native window.confirm box. Hence per
10
+ // capability rather than per namespace.
11
+ export function capability(name) {
12
+ if (typeof window === "undefined") return null;
13
+ const clay = window.clay, hyperclay = window.hyperclay;
14
+ if (name === "consent") return clay?.confirm || hyperclay?.consent || null;
15
+ return clay?.[name] || hyperclay?.[name] || null;
16
+ }
17
+
18
+ // Both clients dispatch the same moment under different names, and clayjs fires its
19
+ // pair back to back in one tick. A plain listener on each name would run the handler
20
+ // twice per occurrence.
21
+ export const MUTATION_READY = ["clay:mutation-ready", "hyperclay:mutation-ready"];
22
+ export const LIVESYNC_APPLIED = ["clay:sync-applied", "hyperclay:livesync-applied"];
23
+ export const PLATFORM_READY = ["clay:ready", "hyperclay:ready"];
24
+
25
+ // The first name to arrive claims the tick, and only a DIFFERENT name is suppressed
26
+ // while it holds the claim. Guarding on "have I run at all this tick" would collapse
27
+ // two genuine occurrences into one.
28
+ export function onPlatformEvent(target, names, handler) {
29
+ let claimedBy = null;
30
+ const wrapped = (event) => {
31
+ if (claimedBy !== null && claimedBy !== event.type) return;
32
+ claimedBy = event.type;
33
+ queueMicrotask(() => { claimedBy = null; });
34
+ handler(event);
35
+ };
36
+ for (const name of names) target.addEventListener(name, wrapped);
37
+ return () => { for (const name of names) target.removeEventListener(name, wrapped); };
38
+ }
39
+
5
40
  // Region-aware save guard. When the platform's region model is present, a control
6
41
  // inside a no-save (or frozen) region must not write save-bytes the platform would
7
42
  // strip anyway. The control stays fully live and reactive; only the serialization
@@ -9,7 +44,7 @@
9
44
  // before — same "use the platform feature if present, degrade otherwise" pattern
10
45
  // as the undo and optionVisibility handshakes.
11
46
  export function regionSkipsSave(el) {
12
- const region = typeof window !== "undefined" && window.hyperclay && window.hyperclay.region;
47
+ const region = capability("region");
13
48
  if (!region || typeof region.resolveRegionPolicy !== "function" || typeof region.skipForPolicy !== "function") {
14
49
  return false;
15
50
  }
@@ -23,13 +58,13 @@ export function regionSkipsSave(el) {
23
58
  // as the callback and never goes async. Returns null standalone, so Sap falls back
24
59
  // to window.confirm — same degrade-otherwise pattern as the region/undo handshakes.
25
60
  export function platformConsent() {
26
- const h = typeof window !== "undefined" && window.hyperclay;
27
- return h && typeof h.consent === "function" ? h.consent : null;
61
+ const fn = capability("consent");
62
+ return typeof fn === "function" ? fn : null;
28
63
  }
29
64
 
30
65
  export function batch(label, fn) {
31
66
  if (typeof fn !== "function") throw new Error("Sap.batch(label, fn): fn must be a function");
32
- const u = typeof window !== "undefined" && window.hyperclay && window.hyperclay.undo;
67
+ const u = capability("undo");
33
68
  if (u && u.flush) u.flush();
34
69
  const r = fn();
35
70
  if (r && typeof r.then === "function") throw new Error("Sap.batch fn must be synchronous (it returned a promise)");
@@ -57,22 +92,38 @@ export function installBridges(runtime) {
57
92
  };
58
93
 
59
94
  // M2: livesync-applied must refresh synchronously inside the pause window.
60
- document.addEventListener("hyperclay:livesync-applied", refreshConnected);
95
+ onPlatformEvent(document, LIVESYNC_APPLIED, refreshConnected);
96
+
97
+ // Undo/redo replay attributes with no events; re-derive after. Mutation readiness
98
+ // is only an early compatibility retry: it truthfully announces the Mutation hub
99
+ // and nothing else. Full platform readiness is the point at which optional plugins
100
+ // such as undo are guaranteed to have been published.
101
+ let undoBound = false;
102
+ let stopWaiting = () => {};
103
+
104
+ const bindUndo = () => {
105
+ if (undoBound) return true;
106
+ const undo = capability("undo");
107
+ if (!undo || typeof undo.on !== "function") return false;
108
+ // hyper-undo's delegator (src/index.js:142) returns undefined and silently drops
109
+ // the subscription when on() is called before start(). A real subscription returns
110
+ // its own unsubscribe function, so that return value is the only reliable proof the
111
+ // handler actually attached. Stay unbound otherwise so a later signal retries.
112
+ const offUndo = undo.on("undo", refreshConnected);
113
+ if (typeof offUndo !== "function") return false;
114
+ const offRedo = undo.on("redo", refreshConnected);
115
+ if (typeof offRedo !== "function") { offUndo(); return false; }
116
+ undoBound = true;
117
+ stopWaiting();
118
+ return true;
119
+ };
120
+
121
+ if (!bindUndo()) {
122
+ const offMutationReady = onPlatformEvent(document, MUTATION_READY, bindUndo);
123
+ const offPlatformReady = onPlatformEvent(document, PLATFORM_READY, bindUndo);
124
+ stopWaiting = () => { offMutationReady(); offPlatformReady(); };
61
125
 
62
- // Undo/redo replay attributes with no events; re-derive after.
63
- const undo = window.hyperclay && window.hyperclay.undo;
64
- if (undo && typeof undo.on === "function") {
65
- undo.on("undo", refreshConnected);
66
- undo.on("redo", refreshConnected);
67
- } else {
68
- // Lazy handshake: the platform may load after us. The hub dispatches
69
- // hyperclay:mutation-ready non-bubbling on `document`, so listen there (not window).
70
- document.addEventListener("hyperclay:mutation-ready", () => {
71
- const u = window.hyperclay && window.hyperclay.undo;
72
- if (u && typeof u.on === "function") {
73
- u.on("undo", refreshConnected);
74
- u.on("redo", refreshConnected);
75
- }
76
- });
126
+ const ready = capability("ready");
127
+ if (ready && typeof ready.then === "function") ready.then(bindUndo, () => {});
77
128
  }
78
129
  }