@panphora/clayjs 0.2.0 → 0.4.0

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.
Files changed (43) hide show
  1. package/README.md +99 -7
  2. package/clay-internals.js +19 -0
  3. package/clay.js +18 -2
  4. package/package.json +19 -3
  5. package/sap.js +5 -5
  6. package/src/attrs/onaftersave.js +12 -1
  7. package/src/attrs/refetch-on-save.js +4 -4
  8. package/src/attrs/save-freeze.js +47 -19
  9. package/src/core/admin-contenteditable.js +2 -2
  10. package/src/core/admin-inputs.js +2 -2
  11. package/src/core/admin-onclick.js +2 -2
  12. package/src/core/admin-resources.js +23 -14
  13. package/src/core/autosave.js +11 -1
  14. package/src/core/edit-mode.js +2 -2
  15. package/src/core/host-attrs.js +46 -0
  16. package/src/core/is-edit-mode.js +14 -6
  17. package/src/core/persist.js +8 -1
  18. package/src/core/save-core.js +199 -290
  19. package/src/core/save.js +124 -84
  20. package/src/core/snapshot.js +99 -43
  21. package/src/core/unsaved-warning.js +8 -2
  22. package/src/dom/all.js +4 -29
  23. package/src/dom/form-data.js +1 -1
  24. package/src/dom/nearest.js +11 -9
  25. package/src/internals/index.js +64 -0
  26. package/src/lib/cache-bust.js +10 -0
  27. package/src/lib/cookie.js +50 -15
  28. package/src/lib/extension-noise.js +5 -1
  29. package/src/lib/mutation.js +65 -18
  30. package/src/lib/region-policy.js +17 -2
  31. package/src/lib/root-attrs.js +45 -0
  32. package/src/lib/throttle.js +25 -13
  33. package/src/loader.js +18 -24
  34. package/src/options/options.js +1 -3
  35. package/src/plugins/demo.js +7 -1
  36. package/src/sync/live-sync.js +121 -89
  37. package/src/ui/dialogs.js +10 -1
  38. package/src/ui/index.js +2 -11
  39. package/src/ui/toast.js +8 -2
  40. package/src/utils/debounce.js +24 -7
  41. package/src/vendor/hyper-undo.vendor.js +1 -1
  42. package/src/vendor/hypercms.vendor.js +29 -16
  43. package/src/vendor/richclay.vendor.js +29 -22
package/README.md CHANGED
@@ -21,7 +21,24 @@ query params on the script URL:
21
21
 
22
22
  - `?plugins=` — add optional plugins: `sync`, `cms` (richclay, indicator, sortable, undo load by default in edit mode).
23
23
  - `?exclude=` — drop a default plugin.
24
- - `?editmode=false` — force view mode (URL param wins over cookies/globals).
24
+ - `?editmode=false` — force view mode (URL param wins over everything below).
25
+
26
+ ## Host attributes
27
+
28
+ A host can put these on `<html>` in the response it serves. They are ephemeral:
29
+ the host injects them and strips them back out of whatever gets saved, so they
30
+ never reach the file on disk.
31
+
32
+ - `savetoken="…"` — the per-document save credential. clayjs posts to
33
+ `/_/save/{token}` and sends no cookies, because the token is the credential.
34
+ A token also implies edit mode, which is the only such signal a sandboxed
35
+ document can see. `htmlclaytoken` is the older spelling of the same thing.
36
+ - `clay-save-transport="desktop-json-v1"` — send the save as
37
+ `{content, snapshotHtml, userDriven}` JSON instead of plain text. Only declare
38
+ it on a host whose save lane reads that envelope.
39
+
40
+ Edit mode is decided in this order: the `?editmode` param, then
41
+ `window.clayEditMode`, then a save token, then the platform's owner cookie.
25
42
 
26
43
  ## Readiness
27
44
 
@@ -33,11 +50,60 @@ await clay.ready; // or: document.addEventListener("clay:ready", ...)
33
50
  clay.save();
34
51
  ```
35
52
 
36
- Edit mode exposes `clay.save()` (+ `clay.save.force()`), `clay.getHTML()`, `clay.beforeSave(fn)`,
53
+ Edit mode exposes `clay.save()` (+ `clay.save.force()`), `clay.getHTML()`, `clay.addDocumentTransform(fn)`,
37
54
  `clay.onSnapshot(fn)`, `clay.toggleEditMode()`, `clay.isEditMode`, `clay.isOwner`, `clay.Mutation`,
38
- `clay.cacheBust(el)`, plus `clay.undo` / `clay.cms` / `clay.morph` when those plugins load. View
39
- mode keeps only the always-available members (`toggleEditMode`, `isEditMode`, `isOwner`,
40
- `Mutation`, `ready`); edit-only members are simply absent.
55
+ `clay.region`, `clay.cacheBust(el)`, plus `clay.undo` / `clay.cms` / `clay.morph` / `clay.RichClay`
56
+ when those plugins load. View mode keeps only the always-available members (`toggleEditMode`, `isEditMode`, `isOwner`,
57
+ `Mutation`, `region`, `ready`); edit-only members are simply absent.
58
+
59
+ ## API
60
+
61
+ Three tiers. The first two are a promise; the third is not.
62
+
63
+ | Tier | What it is | Promise |
64
+ |---|---|---|
65
+ | `clay.*` from `clay.js` | the everyday surface | stable |
66
+ | `clay.*` from a satellite (`clay-ui`, `clay-utils`, `clay-dom`, `clay-events`, `clay-options`, `clay-internals`) | opt-in, one script tag each | stable |
67
+ | anything else under `src/` | reachable by direct import, because `src/` ships | **may change in any release** |
68
+
69
+ The contract starts at **0.3.0**: no name below changes without a major version.
70
+
71
+ **`clay.js`** — `ready`, `save()`, `save.force()`, `getHTML()`, `addDocumentTransform(fn)`, `onSnapshot(fn)`,
72
+ `toggleEditMode()`, `isEditMode`, `isOwner`, `Mutation`, `region`, `cacheBust(el)`, plus `undo` / `cms` / `morph` /
73
+ `RichClay` when those plugins load. View mode keeps only the always-available members, as above.
74
+
75
+ `addDocumentTransform(fn)` runs your callback over a detached clone whenever the page
76
+ prepares to save AND whenever it checks whether anything changed. Keep it pure and
77
+ repeatable: it is a transform, not a "a save is happening" event.
78
+
79
+ `region` is the region-policy model (`resolveRegionPolicy`, `skipForPolicy`, and the token
80
+ constants), the same shape `clay.internals.region` exposes.
81
+
82
+ **Satellites** — one script tag each, and each resolves its own `clay.loaded.*` promise. `clay-ui` adds
83
+ `toast`, `toastPersistent`, `ask`, `confirm`, `tell`, `snippet`, `modal`; `clay-utils` adds `clay.utils`
84
+ (`throttle`, `debounce`, `cookie`, `slugify`, `copyToClipboard`); `clay-internals` adds `clay.internals`,
85
+ below. `clay-events`, `clay-dom`, `clay-options` and `all.js` add HTML attributes and DOM helpers rather
86
+ than members on `clay`.
87
+
88
+ **`clay.internals`** — the pieces the library builds itself out of, for code that needs to sit inside the
89
+ save lifecycle rather than call it. Lower level than `clay.*` deliberately: it assumes you know the
90
+ lifecycle.
91
+
92
+ ```html
93
+ <script src="https://clayjs.com/clay-internals.js"></script>
94
+ ```
95
+
96
+ - `captureSnapshot()`, `captureForSave()` — the snapshot pipeline, read side.
97
+ `captureSnapshot` gives you the clone before any stripping; `captureForSave` gives you the
98
+ bytes a save would send. Register your own transform with `clay.addDocumentTransform(fn)`
99
+ from core.
100
+ - `region.addRegionToken(el, token)`, `region.resolveRegionPolicy(node)`, `region.isInert(node)`,
101
+ `region.isSnapshotRemoved(el)`, `region.PERSIST`, `region.REGION_ATTRS`, and
102
+ `region.selectors.stripFromSave` / `.stripFromComparison` / `.snapshotRemove` / `.freeze` — write your
103
+ own attribute without hardcoding our selectors.
104
+ - `save.saveHtml(html, cb, opts)`, `save.replacePageWith(url, cb)`, `save.isSaveInProgress()` — the save
105
+ lane under `clay.save`. **`saveHtml` writes the bytes you hand it straight to the file**, bypassing the
106
+ snapshot pipeline entirely; check `isSaveInProgress()` first.
41
107
 
42
108
  ## Regions
43
109
 
@@ -54,6 +120,32 @@ Add `autosave` to `<html>` to save automatically on change.
54
120
  ## Develop
55
121
 
56
122
  ```bash
57
- npm test # jest unit suite
58
- npm run dev # stub save server on :4601 for the tests/fixtures pages
123
+ npm test # jest unit suite
124
+ npm run test:conformance # byte-for-byte fixture gate, in a real browser
125
+ npm run dev # stub save server on :4601 for the tests/fixtures pages
59
126
  ```
127
+
128
+ ## Deploy
129
+
130
+ `public/` is what wrangler serves to clayjs.com. It is a build output: gitignored,
131
+ disposable, and rebuilt from scratch every time.
132
+
133
+ ```bash
134
+ npm run build # rebuild public/ from source
135
+ npm run deploy # rebuild, then wrangler deploy
136
+ ```
137
+
138
+ Never edit `public/` by hand, and never copy a file into it. Its contents are
139
+ **derived**:
140
+
141
+ ```
142
+ public/ = package.json "files" (minus NOTICE, which nothing requests)
143
+ + website/* (flattened to the root, so /docs.html works)
144
+ ```
145
+
146
+ That derivation is the point. `files` is the list npm publishes, so it is already
147
+ the line you edit to ship a new satellite, and deriving from it means a file cannot
148
+ reach npm and miss the site. Before this script existed the mirror was hand-copied,
149
+ and it drifted exactly that way: `src/core/host-attrs.js` never made it across, and
150
+ since `loader.js` imports `is-edit-mode.js`, which imports it, the deployed
151
+ `clay.js` could not boot at all.
@@ -0,0 +1,19 @@
1
+ /* clay-internals.js — clayjs satellite: clay.internals = the supported low-level surface (snapshot, region policy, save lane). https://clayjs.com */
2
+ (function () {
3
+ var clay = window.clay = window.clay || {};
4
+ clay.loaded = clay.loaded || {};
5
+
6
+ var script = document.currentScript;
7
+ if (!script || !script.src) {
8
+ console.error("clay-internals: could not determine my own URL (load me with a classic <script src=...>, not type=\"module\")");
9
+ return;
10
+ }
11
+ var url = new URL(script.src, location.href);
12
+ var base = url.href.slice(0, url.href.lastIndexOf("/"));
13
+
14
+ // No DOM gate: nothing here touches document.body at import time, unlike clay-ui.
15
+ clay.loaded.internals = import(base + "/src/internals/index.js")
16
+ .catch(function (err) { console.error("clay-internals failed to load:", err); throw err; });
17
+ // Mark handled: a blocked satellite must not emit an unhandled rejection.
18
+ clay.loaded.internals.catch(function () {});
19
+ })();
package/clay.js CHANGED
@@ -11,10 +11,18 @@
11
11
  // resolves the ORIGINAL `ready` promise via the stashed resolver.
12
12
  if (clay.__booted) return;
13
13
 
14
- if (!clay.ready) {
15
- clay.ready = new Promise(function (r) { clay.__readyResolve = r; });
14
+ function mintReady() {
15
+ clay.ready = new Promise(function (res, rej) {
16
+ clay.__readyResolve = res;
17
+ clay.__readyReject = rej;
18
+ });
19
+ // Nobody may be awaiting a failed boot's promise, and an unhandled rejection
20
+ // in the console is noise on top of the error we already logged.
21
+ clay.ready.catch(function () {});
16
22
  }
17
23
 
24
+ if (!clay.ready) mintReady();
25
+
18
26
  var script = document.currentScript;
19
27
  if (!script || !script.src) {
20
28
  console.error("clayjs: could not determine my own URL (load me with a classic <script src=...>, not type=\"module\")");
@@ -29,5 +37,13 @@
29
37
  .catch(function (err) {
30
38
  clay.__booted = false;
31
39
  console.error("clayjs failed to load:", err);
40
+ // Settle the promise so `await clay.ready` fails loudly instead of hanging
41
+ // forever with nothing to catch. Then mint a fresh one: a promise settles
42
+ // once, so without this the corrected retry tag would call __readyResolve on
43
+ // an already-rejected promise and every later await would keep throwing even
44
+ // though the retry succeeded.
45
+ var reject = clay.__readyReject;
46
+ mintReady();
47
+ if (reject) reject(err);
32
48
  });
33
49
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panphora/clayjs",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "clayjs: malleable HTML files. Save lifecycle for self-saving HTML.",
6
6
  "license": "MIT",
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "clay.js",
14
14
  "clay-ui.js",
15
+ "clay-internals.js",
15
16
  "clay-events.js",
16
17
  "clay-options.js",
17
18
  "clay-dom.js",
@@ -28,10 +29,25 @@
28
29
  },
29
30
  "scripts": {
30
31
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
31
- "dev": "node tests/stub-server.mjs"
32
+ "test:conformance": "UPDATE_GOLDENS=0 web-test-runner",
33
+ "conformance:update": "UPDATE_GOLDENS=1 web-test-runner",
34
+ "prepublishOnly": "npm test && npm run test:conformance",
35
+ "dev": "node tests/stub-server.mjs",
36
+ "build": "node build.js",
37
+ "deploy": "node build.js && wrangler deploy"
32
38
  },
33
39
  "devDependencies": {
40
+ "@esm-bundle/chai": "^4.3.4-fix.0",
41
+ "@web/test-runner": "^0.20.2",
42
+ "@web/test-runner-commands": "^0.9.0",
43
+ "@web/test-runner-playwright": "^0.11.1",
34
44
  "jest": "^29.7.0",
35
- "jest-environment-jsdom": "^29.7.0"
45
+ "jest-environment-jsdom": "^29.7.0",
46
+ "playwright": "1.56.1"
47
+ },
48
+ "hyper": {
49
+ "kind": "lib",
50
+ "status": "active",
51
+ "url": "https://clayjs.com"
36
52
  }
37
53
  }
package/sap.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // GENERATED — do not edit. Vendored from sapjs/dist/sap.min.js via sapjs
2
2
  // `npm run copy-to-clayjs`. Edit the sapjs source and re-run.
3
3
  (function () {
4
- var Sap=(()=>{var 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";
5
- ${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=[`
6
- `+(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(`
7
- `)),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(`
8
- `)),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);})();
4
+ 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 kn={};ke(kn,{Sap:()=>_,default:()=>$n,mount:()=>Ee,mountAll:()=>dt,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 u(l,w){s(w),!l._broken&&(n.add(l),!e&&(e=!0,queueMicrotask(c)))}function c(){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:u,runNow:E,rearm:y,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 u of r.children)n(u)}}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 pt(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 mt(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,u=r.indexOf("=");u>=0&&(s=r.slice(u+1),r=r.slice(0,u));let c=r.split(":"),T=c[0],E="string",y=!1;for(let l of c.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 ht(t,e){return e==="bool"?t?"true":"false":t==null?"":String(t)}function bt(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 T=Me(e,s);return T||(t.getAttribute("items")===s?t:t.querySelector(`[items="${s}"]`))}let u=r[r.length-2],c=[...t.querySelectorAll(`[scope="${u}"]`)].find(T=>it(T,s));return c?it(c,s):null}function Me(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 gt(t,e){return Array.isArray(t)?e==null?t:t.map(n=>typeof e=="function"?e(n):n?.[e]):[]}function Ht(t,e){return gt(t,e).reduce((n,r)=>n+B(r),0)}function De(t,e){return Array.isArray(t)?e==null?t.length:t.reduce((n,r)=>n+(e(r)?1:0),0):0}function Re(t,e){let n=gt(t,e);return n.length?Ht(t,e)/n.length:0}function Ie(t,e){let n=gt(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=gt(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 jt(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 Ut(){return[ct,B,Ht,De,Re,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 R(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";
5
+ ${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 j(t,e){if(t.error)throw t.error;return t.fn(e.state,e.item,e.el??null,e.root,...Ut())}function Gt(t){let e=new Map;for(let c of t)e.set(c.name,c);let n=[],r=new Map,s=[];function u(c){let T=r.get(c.name);if(T!==1){if(T===0){let E=[...s.slice(s.indexOf(c.name)),c.name].join(" -> "),y=new Error(`calc: cycle: ${E}`);throw y.sapCode="E07",y.cycle=E,y}r.set(c.name,0),s.push(c.name);for(let E of c.entry.deps.state){let y=e.get(E);y&&y!==c&&u(y)}for(let E of c.entry.deps.item){let y=e.get(E);y&&y!==c&&u(y)}s.pop(),r.set(c.name,1),n.push(c)}}for(let c of t)u(c);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 u=0;u<r.length;u++)s[u]&&s[u].selected?r[u].setAttribute("selected",""):r[u].removeAttribute("selected")}}function yt(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"];function At(t,e,n){let r=null,s=u=>{r!==null&&r!==u.type||(r=u.type,queueMicrotask(()=>{r=null}),n(u))};for(let u of e)t.addEventListener(u,s);return()=>{for(let u of e)t.removeEventListener(u,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 r=!1;for(let s of t.apps())s.root.isConnected?t.runNow(s,"platform"):r=!0;r&&(t.pruneDisconnected(),t.remountIfPresent())};At(document,ze,e);let n=W("undo");n&&typeof n.on=="function"?(n.on("undo",e),n.on("redo",e)):At(document,Ct,()=>{let r=W("undo");r&&typeof r.on=="function"&&(r.on("undo",e),r.on("redo",e))})}function He(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 Ue(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 Ve(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 Ye(t){t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0}))}function D(t){let e=He(t);return{el:t,kind:e,read(){return Ue(t,e)},write(n,r={}){Ve(t,e,n),r.noMirror||te(t),r.silent||Ye(t)},mirror(){te(t)}}}var Mt={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"],ft=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 u=[...n.parentElement.children].filter(c=>c.tagName===n.tagName);u.length>1&&(s+=`:nth-of-type(${u.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=(Mt[e]||{}).slug||"error",u={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"},c=[`
6
+ `+(e[0]==="W"?"sap \u26A0 ":"sap \u2717 ")+e+" "+s];return c.push(` at ${u.el}${u.attr?` \u2014 ${u.attr}="${u.expr??""}"`:""}`),u.problem&&c.push(` problem: ${u.problem}`),u.didYouMean&&c.push(` did you mean: ${u.didYouMean}`),u.fix&&c.push(` fix: ${u.fix}`),console.error(c.join(`
7
+ `)),u}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 lt(t,e){let n=null,r=3;for(let s of e){let u=Ge(t,s);u<r&&(r=u,n=s)}return n}function Ge(t,e){let n=t.length,r=e.length,s=Array.from({length:n+1},(u,c)=>[c,...new Array(r).fill(0)]);for(let u=0;u<=r;u++)s[0][u]=u;for(let u=1;u<=n;u++)for(let c=1;c<=r;c++)s[u][c]=Math.min(s[u-1][c]+1,s[u][c-1]+1,s[u-1][c-1]+(t[u-1]===e[c-1]?0:1));return s[n][r]}var U=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 Xe(){let t=null;return{kind:"native",subscribe(e){t=new MutationObserver(r=>e(Ke(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 Ke(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 Je(t,e){t.pruneDisconnected();let n=new Set,r=!1;for(let s of e){let u=s.type==="remove"?s.parent:s.element,c=u&&t.appFor(u);c&&n.add(c),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(U)return U.suppress(t);let e=W("undo");if(e&&e.pause&&e.resume){e.pause();try{return t()}finally{e.resume()}}return t()}function Dt(t,e){Nt=!0,U=t,t.subscribe(n=>Je(e,n))}function Rt(t){if(Nt||typeof window>"u"||typeof document>"u")return;let e=W("Mutation");if(e&&typeof e.onAnyChange=="function"){Dt(ne(e),t);return}typeof MutationObserver=="function"&&(Dt(Xe(),t),rt=At(document,Ct,function(){let r=W("Mutation");r&&(rt(),rt=null,U&&U.teardown(),Nt=!1,Dt(ne(r),t))}))}function oe(){if(U)try{U.teardown()}catch{}rt&&typeof document<"u"&&rt(),U=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(()=>Qe(t,e))}function Qe(t,e){let n=t.root,r={},s=[],u=[],c=[],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:ht(G(h,i.type),i.type)})),G(h,i.type)}function k(o,i){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"){i[p.name]=o.hasAttribute(p.name);continue}if(p.transient){i[p.name]=bt(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=D(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:R(v),el:o,ctx:i});else if(p==="text"||p.startsWith("text:"))u.push({el:o,kind:"text",fmt:p.includes(":")?p.slice(5):null,entry:R(v),ctx:i});else if(p==="show")u.push({el:o,kind:"show",entry:R(v),ctx:i});else if(p.startsWith("attr:"))u.push({el:o,kind:"attr",arg:p.slice(5),entry:R(v),ctx:i});else if(p.startsWith("class:"))u.push({el:o,kind:"class",arg:p.slice(6),entry:R(v),ctx:i});else if(p.startsWith("css:"))u.push({el:o,kind:"css",arg:p.slice(4),entry:R(v),ctx:i});else if(p==="effect")c.push({el:o,entry:R(v,!0),ctx:i});else if(p==="invalid")T.push({el:o,entry:R(v),ctx:i});else if(p.startsWith("show-when:")||p.startsWith("option:")){let N=p.slice(p.indexOf(":")+1);y.add(N),u.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),u.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),u.push({el:o,kind:"when",match:"show-not",field:N,values:v.split("|"),ctx:i})}}i.projection&&o.hasAttribute("bind")&&u.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){F(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,st)=>{let C={};g(C,N,st);let z={root:h.root,state:h.state,item:C,ownerEl:N,projection:h.projection};a(N,C,z),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 P(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],st=v[2].trim(),C=$(N,h),z;try{z=j(R(st),{state:i,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:i,item:J,ownerEl:J.$el,projection:!0};b(o,qt),A(o,J,qt)}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)=>ie(i.ownerEl)-ie(o.ownerEl));for(let o of d){let i;try{i=Gt(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]=j(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 u)f+=en(o,t);for(let o of c)nn(o,t);for(let o of T)rn(o);t._state=r,t._stats={fields:Object.keys(r).filter(o=>typeof r[o]!="function").length,calcs:s.length,paints:u.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}/${u.length}`)}function Ze(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 u=n.includes(s.getAttribute(e));if(r?!u:u)return!0}s=s.parentElement}return!1}function tn(t,e){if(t===t.ownerDocument.activeElement)return 0;let n=D(t),r=n.read(),s=e??"";return String(r)!==String(s)?(n.write(s,{silent:!0}),1):0}function en(t,e){if(t.kind==="projection")return tn(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=j(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:Ze(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?jt(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 u=!s;return n.hidden!==u?(n.hidden=u,1):0}case"attr":{let r=t.arg;if(ae.has(r)){let u=n.hasAttribute(r);return e&&!u?(n.setAttribute(r,""),1):!e&&u?(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 nn(t,e){try{j(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 rn(t){let e="";try{let n=j(t.entry,{state:t.ctx.state,item:t.ctx.item,el:t.el,root:t.ctx.root});e=typeof n=="string"?n:""}catch{e=""}typeof t.el.setCustomValidity=="function"&&t.el.setCustomValidity(e)}function ie(t){let e=0,n=t;for(;n&&!(n.hasAttribute&&n.hasAttribute("sap"));)n=n.parentElement,e++;return e}var on=new Set(Et),ue=new Set(["calc","text","attr","class","css","set","move","sort","option","option-not","show-when","hide-when","editmode"]),sn=new Set(["show-when","hide-when","option","option-not"]),an=/\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 un(t){return t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA"}function Wt(t){return t.hasAttribute("bind")}function cn(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=(c,T,E)=>{e.error(c,T,E),n=!0},s=t.ownerDocument.createTreeWalker(t,4),u;for(;u=s.nextNode();)if(/\{\{.*\}\}/.test(u.nodeValue||"")){r("E02",u.parentElement||t,{problem:"moustaches in text content are not a Sap feature",fix:'move the expression onto the element: text="state.x"'});break}return cn(t,c=>{let T=c.closest&&c.closest("[detail]");for(let E of[...c.attributes]){let y=E.name,l=ee(y);if(l){r("E01",c,{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(ue.has(w)){if(sn.has(w)&&an.test(E.value)){let k=y.slice(y.indexOf(":")+1);e.warn("W04",c,{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=lt(w,[...ue]);e.warn("W03",c,{attr:y,problem:`unknown "${w}:" attribute`,didYouMean:k?`${k}:`:null})}}else if(!ce.has(y)&&!ft.has(y)&&!on.has(y)&&!/^(data-|aria-|on)/.test(y)&&!(y in c)){let w=lt(y,[...ce]);w&&e.warn("W03",c,{attr:y,problem:`unknown "${y}" attribute`,didYouMean:w})}y==="attr:hidden"&&e.warn("W03",c,{attr:y,problem:"attr:hidden paints the wrong attribute",fix:'use show="expr"'}),(y==="attr:value"||y==="attr:checked"||y==="attr:selected")&&Wt(c)&&r("E30",c,{attr:y,problem:"attr: on a bound control collides with persist ownership",fix:"remove it; bind owns this attribute"}),y==="effect"&&Wt(c)&&/\b(value|checked)\s*=[^=]/.test(E.value)&&r("E30",c,{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")&&un(c)&&(y==="show"||r("E18",c,{attr:y,problem:"paint belongs on output elements, not form controls",fix:"move the paint to an <output> or <span>"}))}if(c.hasAttribute("state")){let E=P(c.getAttribute("state")),y=new Set;for(let l of E)l.name.includes("-")&&r("E08",c,{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",c,{attr:"state",problem:`field "${l.name}" is declared twice in one scope`}),y.add(l.name),St.has(l.name)&&r("E05",c,{attr:"state",problem:`"${l.name}" is a reserved Sap word`}),ft.has(l.name)&&r("E06",c,{attr:"state",problem:`"${l.name}" is a global HTML attribute name; pick another field name`}),l.name==="open"&&c.tagName==="DIALOG"&&r("E33",c,{attr:"state",problem:"dialog open is transient",fix:"use showModal() \u2014 declare state= only on <details> or popovers"})}if(Wt(c)){if(c.hasAttribute("-"),c.tagName==="INPUT"){let E=(c.getAttribute("type")||"text").toLowerCase();E==="file"&&r("E32",c,{attr:"bind",problem:"files never serialize into an HTML file",fix:"use no-save + effect instead of bind"}),E==="password"&&!c.hasAttribute("transient")&&r("E31",c,{attr:"bind",problem:"a password must never serialize into a world-readable file",fix:"add transient to the password input"})}else if(c.tagName!=="SELECT"&&c.tagName!=="TEXTAREA"){let E=c.getAttribute("contenteditable");!(E!=null&&E!=="false")&&c.children.length>0&&r("E20",c,{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(c.hasAttribute("transient")&&c.hasAttribute("persist")&&r("E34",c,{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"}),c.hasAttribute("item")&&!c.hasAttribute("template")){let E=c.parentElement;(!E||!E.hasAttribute("items"))&&r("E10",c,{problem:"an [item] must be a direct child of an [items] list",fix:'wrap it in a container with items="name"'})}if(c.hasAttribute("items")&&T&&r("E17",c,{attr:"items",problem:"nested items inside a detail panel is a v1 mount error (nested collections ship in v1.1)"}),c.hasAttribute("items")){let E=t.querySelector(`[trigger-add="${c.getAttribute("items")}"]`);!mt(c)&&O(c).length===0&&E&&r("E17",c,{attr:"items",problem:`trigger-add targets items="${c.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 fn(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 ln=0;function de(){return typeof performance<"u"&&performance.now?performance.now():0}function Pt(t){let e=t.id||t.getAttribute("sap")||`app-${ln++}`,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;fn(t.ownerDocument);for(let c of t.querySelectorAll("textarea[data-value]"))yt(c);let u=de();return ot(r,{trigger:"mount"}),r._mountMs=de()-u,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 dn(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 pn(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 a=at(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=pt(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 D(A).read();let S=it(b,a);if(S)return O(S).map(m=>L(m,g,!0));let x=dn(b,a);if(x)return L(x,g,!1);let $=pe(b,g.root,a);if($)return $.decl.transient?bt($.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?Lt(b,A,a):b.setAttribute(g,ht(a,A.type)),t.schedule(S,"set:"+g)}function u(b,g){let a=new Set,A=I(b)||g;for(;A;){for(let S of P(A.getAttribute("state")||""))a.add(S.name);if(A.hasAttribute("sap"))break;A=I(A.parentElement)}return F(b,S=>{let x=S.getAttribute("bind");x&&a.add(x)}),a}function c(b,g,a,A){let S=tt(b,a);if(S){D(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 $=pe(b,g.root,a);if($){s($.el,a,A,$.decl,g);return}let M=u(b,g.root);M.delete(a);let m=a.length>=4?lt(a,[...M]):null;if(m){g.diag.error("E12",b,{key:a,problem:`unknown state key "${a}"`,didYouMean:m});return}if(St.has(a)||ft.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,f=pn(A),o=d.getAttribute("state")||"",i=f==="string"?a:`${a}:${f}`;d.setAttribute("state",o?`${o} ${i}`:i),s(d,a,A,{name:a,type:f,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=ut(g.root,b,a);if(!A)return g.diag.error("E17",b,{problem:`cannot resolve a list named "${a}" from here`}),null;let S=mt(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){F(b,a=>{if(a.hasAttribute("bind")){let A=D(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 P(b.getAttribute("state")||"")){let A=a.default!=null?a.default:a.type==="num"?"0":a.type==="bool"?"false":"";a.transient?Lt(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=ut(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):(c(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:c,makeProxy:L}}var mn=["trigger-add","trigger-remove","trigger-reset"];function hn(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:")||mn.includes(n))return!0}return!1}function bn(t,e){let n=t,r=e.parentElement;for(;n&&n!==r;){if(n.nodeType===1&&hn(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=pt(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"),i=o,h=R(o);if(!h.error)try{let N=j(h,r(m,d));(typeof N=="string"||typeof N=="number")&&(i=String(N))}catch{}let p=Jt();if(!p){window.confirm(i)&&f();return}if(m._sapGatePending)return;m._sapGatePending=!0;let v=()=>{m._sapGatePending=!1};p(i,()=>{v(),f()}).catch(v)}function u(m,d){for(let f of m.attributes){if(!f.name.startsWith("set:"))continue;let o=f.name.slice(4),i=R(f.value);if(i.error){d.diag.error("E08",m,{attr:f.name,expr:f.value,problem:String(i.error.message)});continue}let h;try{h=j(i,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 c(m,d){let f=m.closest("[item]");if(!f)return;let o=O(f.parentElement),i=o.indexOf(f);d==="up"&&i>0?t.placeBefore(f,o[i-1]):d==="down"&&i<o.length-1&&t.placeBefore(o[i+1],f)}function T(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 i=I(m)||f.root,h=[];return F(i,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 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,f,o){let i=T(m,f,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,z)=>E(p(C),p(z))),st=v.every((C,z)=>C===h[z])?[...v].reverse():v;for(let C of st)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 f=n(m);for(let o of[...m.attributes]){let i=o.name;if(i==="trigger-remove")f&&f.$remove();else if(i==="trigger-reset")f&&f.$reset();else if(i==="trigger-add"){let h=f&&f.$add(o.value);h&&l(h.$el)}else i==="move:up"?(c(m,"up"),t.schedule(d,"move:up")):i==="move:down"?(c(m,"down"),t.schedule(d,"move:down")):i.startsWith("move:to")?f&&f.$move(o.value):i.startsWith("sort:")&&y(m,i.slice(5),o.value,d)}[...m.attributes].some(o=>o.name.startsWith("set:"))&&u(m,d)})}function k(m){let d=m.target;if(!d||d.nodeType!==1)return;let f=t.appFor(d);if(!f)return;let o=bn(d,f.root);o&&w(o,f)}function L(m){let d=D(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 i=o.$add(f);if(!i)return;let h=[];F(m,p=>{p.hasAttribute("bind")&&h.push(p)});for(let p of h){let v=tt(i.$el,p.getAttribute("bind"));v&&D(v).write(D(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 f=t.appFor(d);f&&(m.preventDefault(),s(d,f,()=>b(d,f,d.getAttribute("trigger-add"))))}function a(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 i=tt(o._sapDetailRow,d.getAttribute("bind"));if(i&&i!==d){D(i).write(D(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 i=B(d.getAttribute("step"))||1,h=m.key==="ArrowUp"?1:-1,p=B(d.value)+i*(m.shiftKey?10:1)*h,v=d.getAttribute("min"),N=d.getAttribute("max");v!==null&&v!==""&&p<B(v)&&(p=B(v)),N!==null&&N!==""&&p>B(N)&&(p=B(N)),D(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 be=/^(set:|move:|sort:|trigger-add$|trigger-remove$|trigger-reset$)/;function Ot(t){return`${t.tagName.toLowerCase()}[sap]`}function gn(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 u=s.name;(u.startsWith("calc:")||u==="text"||u.startsWith("text:")||u==="show"||u.startsWith("attr:")||u.startsWith("class:")||u.startsWith("css:")||u==="effect"||u==="invalid"||u.startsWith("set:")||u==="detail")&&e.push({el:r,attr:u,src:s.value})}};n(t);for(let r of t.querySelectorAll("*"))n(r);return e}function we(t){function e(l){let w=l._stats||{},k=l.root;return{root:Ot(k),fields:w.fields||0,calcs:w.calcs||0,paints:w.paints||0,actions:gn(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 u(){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 c(l){return l?typeof l=="string"?document.querySelector(l):l.nodeType===1?l:null:null}function T(l,w){let k=c(l);if(!k)return console.warn("sap why: element not found"),null;let L=[`sap why <${k.tagName.toLowerCase()}> \u2014 ${xt(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(`
8
+ `)),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=Ot(A);w++;let x=new nt(a.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}`});w++,ot(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=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(M)||l.push({code:"I33",severity:"info",message:`${S}: field "${f}" is declared but read nowhere (dead state)`});w++;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`});w++;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`});w++;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 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=>Ot(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:u,why:T,debug:E,doctor:y,greenLine:r,printGreenLines:s,REGISTRY:Mt}}var wn="0.2.0",q=new Map,V=[],Bt=zt(ot);function yn(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 An(){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 vn(t,e){if(t.moveBefore)try{t.moveBefore(e,null);return}catch{}t.appendChild(e)}function En(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:yn,isRegistered:t=>q.has(t),pruneDisconnected:An,schedule:(t,e)=>Bt.schedule(t,e),runNow:(t,e)=>Bt.runNow(t,e),moveInto:vn,placeBefore:En,remountIfPresent:()=>dt()},Ae=me(K),Sn=he(K,Ae),Y=we(K),ye=!1;function ve(){ye||(ye=!0,Sn.install(document),Zt(K))}function dt(t=document){ve(),Rt(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(),Rt(K),!t)return dt();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=yt;_.mount=Ee;_.config=function(e={}){return e.formats&&Object.assign(ct,e.formats),_};_._registry=q;_._reset=function(){q.clear(),V.length=0,oe()};function xn(){typeof document>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>dt()):dt())}xn();typeof window<"u"&&(window.Sap=_);var $n=_;return Te(kn);})();
9
9
  if (typeof window !== 'undefined' && Sap && Sap.default) window.Sap = Sap.default;
10
10
  var sapDefault = Sap.default;
11
11
  window.clay = window.clay || {};
@@ -5,9 +5,20 @@
5
5
  * Only fires on 'clay:save-saved' events (not on error/offline).
6
6
  *
7
7
  * Usage:
8
- * <span onaftersave="this.innerText = event.detail.msg"></span>
8
+ * <span clay="no-trigger-autosave" onaftersave="this.innerText = event.detail.msg"></span>
9
9
  * <link href="styles.css" onaftersave="cacheBust(this)">
10
10
  *
11
+ * MARK WHAT YOU MUTATE `no-trigger-autosave`.
12
+ * These handlers run after the save baseline has been taken, so anything they write
13
+ * to the live DOM reads as a change the user made and leaves the page permanently
14
+ * dirty: autosave loops, and the close-tab warning never clears. The token strips
15
+ * the element from every comparison capture, which is what stops that.
16
+ * `cacheBust()` marks its own target, so the second example needs nothing. A handler
17
+ * that mutates some OTHER element has to mark that element itself.
18
+ *
19
+ * (The alternative — re-reading the whole live DOM after handlers run — is what
20
+ * clayjs used to do, and it silently discarded anything typed during a save.)
21
+ *
11
22
  * The event.detail object contains:
12
23
  * - status: 'saved'
13
24
  * - msg: string (e.g., 'Saved')
@@ -1,3 +1,5 @@
1
+ import { addRegionToken } from '../lib/region-policy.js';
2
+
1
3
  function swapElement(el) {
2
4
  const attr = el.hasAttribute('href') ? 'href' : el.hasAttribute('src') ? 'src' : null;
3
5
  if (!attr) return;
@@ -12,10 +14,8 @@ function swapElement(el) {
12
14
  newEl.setAttribute(name, value);
13
15
  }
14
16
  newEl.setAttribute(attr, isSameOrigin ? url.pathname + url.search : url.href);
15
- const tokens = new Set((newEl.getAttribute("clay") || "").trim().split(/\s+/).filter(Boolean));
16
- tokens.add("no-trigger-autosave");
17
- tokens.add("no-undo");
18
- newEl.setAttribute("clay", Array.from(tokens).join(" "));
17
+ addRegionToken(newEl, "no-trigger-autosave");
18
+ addRegionToken(newEl, "no-undo");
19
19
 
20
20
  el.insertAdjacentElement('afterend', newEl);
21
21