mlola-ui 1.11.0 → 1.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8471,8 +8471,8 @@ body{min-height:0;padding:var(--ml-space-2)}#status{margin:var(--ml-space-2)}</s
8471
8471
  <body>
8472
8472
  <main id="surfaces"></main>
8473
8473
  <p id="status" class="ml-fine-print" role="status" hidden></p>
8474
- <script>"use strict";(()=>{function gt(e,t){let n=(String(t).split(".")[1]??"").length;return Number(e.toFixed(Math.min(n,10)))}function he(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,l=Number.isFinite(i)&&i>0?i:1,c=Number.isFinite(e)?e:o,s=Math.min(r,Math.max(o,c)),a=o+Math.round((s-o)/l)*l;return gt(Math.min(r,Math.max(o,a)),l)}function Ge(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,l=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0;return he(o+l*(r-o),{min:o,max:r,step:i})}function _e(e,{min:t=0,max:n=100}={}){let i=Number.isFinite(t)?t:0,o=Number.isFinite(n)&&n>i?n:i+100;return o===i?0:(Math.min(o,Math.max(i,e))-i)/(o-i)*100}function Ue(e,t,{min:n=0,max:i=100,step:o=1}={}){let r=Number.isFinite(n)?n:0,l=Number.isFinite(i)&&i>r?i:r+100,c=Number.isFinite(o)&&o>0?o:1,s=Math.max(c,(l-r)/10),a={ArrowLeft:-c,ArrowDown:-c,ArrowRight:c,ArrowUp:c,PageDown:-s,PageUp:s};if(e==="Home")return he(r,{min:r,max:l,step:c});if(e==="End")return he(l,{min:r,max:l,step:c});let d=a[e];if(d!==void 0)return he(t+d,{min:r,max:l,step:c})}var Qt=Object.freeze({delay:250,slop:8});function Je(e,t,n=6){return Math.abs(e)>=n&&Math.abs(e)>=Math.abs(t)}function Ve(e,t,n,{horizontal:i=!0,wrap:o=!0,enabled:r=()=>!0}={}){if(e<=0)return-1;let l=(h,v)=>{let x=h;for(let I=0;I<e;I+=1){if(r(x))return x;x+=v,x<0&&(x=e-1),x>=e&&(x=0)}return-1};if(n==="Home")return l(0,1);if(n==="End")return l(e-1,-1);let a=n===(i?"ArrowRight":"ArrowDown")?1:n===(i?"ArrowLeft":"ArrowUp")?-1:0;if(!a)return-1;let d=t;for(let h=0;h<e;h+=1){if(d+=a,d<0){if(!o)return-1;d=e-1}if(d>=e){if(!o)return-1;d=0}if(r(d))return d}return-1}function Ke(e,t,n){return e<=0?-1:n&&t<=0?e-1:!n&&t===e-1?0:-1}var He={top:"bottom",bottom:"top",left:"right",right:"left"};function $e(e,t,n,{side:i="bottom",align:o="center",offset:r=8,padding:l=8}={}){let c={top:e.y-l,bottom:n.height-(e.y+e.height)-l,left:e.x-l,right:n.width-(e.x+e.width)-l},s=x=>(x==="top"||x==="bottom"?t.height:t.width)+r,a=i;c[i]<s(i)&&c[He[i]]>c[i]&&(a=He[i]);let d=a==="top"||a==="bottom",h,v;return d?(v=a==="bottom"?e.y+e.height+r:e.y-t.height-r,h=o==="start"?e.x:o==="end"?e.x+e.width-t.width:e.x+e.width/2-t.width/2):(h=a==="right"?e.x+e.width+r:e.x-t.width-r,v=o==="start"?e.y:o==="end"?e.y+e.height-t.height:e.y+e.height/2-t.height/2),h=Math.min(Math.max(h,l),Math.max(l,n.width-t.width-l)),v=Math.min(Math.max(v,l),Math.max(l,n.height-t.height-l)),{x:Math.round(h),y:Math.round(v),side:a}}function Ye(e,t,n,{side:i="top",offset:o=8,padding:r=8}={}){let l=i==="left"||i==="right",c=Math.max(e.x,n.width-e.x-e.width)-r,s=l&&t.width+o>c?"top":i,a=$e(e,t,n,{side:s,align:"center",offset:o,padding:r}),d=a.side==="top"||a.side==="bottom",h=d?e.x+e.width/2-t.width/2:e.y+e.height/2-t.height/2;return{...a,shift:Math.round((d?a.x:a.y)-h)}}var Xe=Symbol.for("mlola.scrollLock");function Ze(e=globalThis.document){if(!e?.documentElement)return()=>{};let t=e.documentElement,n=t[Xe]??(t[Xe]={count:0,saved:null});if(n.count===0){let o=e.defaultView,r=t.clientWidth;n.saved={overflow:t.style.overflow,scrollbarGutter:t.style.scrollbarGutter,paddingInlineEnd:t.style.paddingInlineEnd},t.style.scrollbarGutter="stable",t.style.overflow="hidden";let l=t.clientWidth-r,c=0;if(l>0&&o){t.style.scrollbarGutter=n.saved.scrollbarGutter;let s=Number.parseFloat(o.getComputedStyle(t).paddingInlineEnd)||0;t.style.paddingInlineEnd=`${s+l}px`,c=l}t.style.setProperty("--ml-scroll-lock-offset",`${c}px`),t.setAttribute("data-ml-scroll-locked","")}n.count+=1;let i=!1;return()=>{i||(i=!0,n.count=Math.max(0,n.count-1),!(n.count>0||!n.saved)&&(t.style.overflow=n.saved.overflow,t.style.scrollbarGutter=n.saved.scrollbarGutter,t.style.paddingInlineEnd=n.saved.paddingInlineEnd,t.style.removeProperty("--ml-scroll-lock-offset"),t.removeAttribute("data-ml-scroll-locked"),n.saved=null))}}var Ae="__mlolaEnhanced",Se=(e,t)=>e.dispatchEvent(new CustomEvent("ml-change",{detail:{value:t},bubbles:!0})),bt=["a[href]","button:not([disabled])","input:not([disabled]):not([type='hidden'])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])"].join(",");function Qe(e){return[...e.querySelectorAll(bt)].filter(t=>t.offsetWidth>0||t.offsetHeight>0||t===document.activeElement)}function j(e,t,n,i){return e.addEventListener(t,n,i),()=>e.removeEventListener(t,n,i)}function Te(e,t,n,i=$e){let o=typeof e.showPopover=="function";o&&!e.hasAttribute("popover")&&e.setAttribute("popover","manual");let r=!1,l=0,c=()=>{let a=t.getBoundingClientRect(),{minWidth:d,...h}=n();d&&(e.style.minWidth=`${d}px`);let v=i({x:a.left,y:a.top,width:a.width,height:a.height},{width:e.offsetWidth,height:e.offsetHeight},{width:window.innerWidth,height:window.innerHeight},h);e.style.left=`${v.x}px`,e.style.top=`${v.y}px`,v.shift!==void 0&&e.style.setProperty("--ml-floating-shift",`${v.shift}px`),e.dataset.side=v.side},s=()=>{cancelAnimationFrame(l),l=requestAnimationFrame(()=>{r&&c()})};return{show(){r=!0,e.hidden=!1,o&&e.isConnected&&!e.matches(":popover-open")&&e.showPopover(),c()},hide(){r=!1,o&&e.matches(":popover-open")&&e.hidePopover(),e.hidden=!0},cleanups:[j(window,"scroll",s,!0),j(window,"resize",s),()=>cancelAnimationFrame(l)]}}function ye(e,t,n,i={}){return Ve(e.length,t,n,{...i,enabled:o=>!e[o].disabled&&e[o].getAttribute("aria-disabled")!=="true"})}var Le={accordion(e){let t=e.dataset.mlMultiple==="true",n=e.dataset.mlCollapsible!=="false",i=()=>[...e.querySelectorAll(".ml-accordion-item")],o=()=>[...e.querySelectorAll(".ml-accordion-trigger")],r=(c,s)=>{let a=c.querySelector(".ml-accordion-trigger"),d=c.querySelector(".ml-accordion-panel"),h=s?"open":"closed";c.dataset.state=h,a&&(a.dataset.state=h,a.setAttribute("aria-expanded",String(s))),d&&(d.dataset.state=h,d.hidden=!s)},l=c=>{let s=c.dataset.state==="open";if(!(s&&!n)){if(!t&&!s)for(let a of i())a!==c&&r(a,!1);r(c,!s)}};return[j(e,"click",c=>{let s=c.target.closest(".ml-accordion-trigger");s&&e.contains(s)&&l(s.closest(".ml-accordion-item"))}),j(e,"keydown",c=>{let s=c.target.closest(".ml-accordion-trigger");if(!s)return;let a=o(),d=a.indexOf(s),h=ye(a,d,c.key,{horizontal:!1});h>=0&&(c.preventDefault(),a[h].focus())})]},tabs(e){let t=e.dataset.orientation!=="vertical",n=()=>[...e.querySelectorAll(".ml-tabs-trigger")],i=o=>{for(let r of n()){let l=r===o;r.dataset.state=l?"active":"inactive",r.setAttribute("aria-selected",String(l)),r.tabIndex=l?0:-1;let c=document.getElementById(r.getAttribute("aria-controls")??"");c&&(c.dataset.state=l?"active":"inactive",c.hidden=!l)}};return[j(e,"click",o=>{let r=o.target.closest(".ml-tabs-trigger");r&&e.contains(r)&&!r.disabled&&i(r)}),j(e,"keydown",o=>{let r=o.target.closest(".ml-tabs-trigger");if(!r)return;let l=n(),c=ye(l,l.indexOf(r),o.key,{horizontal:t});c<0||(o.preventDefault(),l[c].focus(),i(l[c]))})]},"dropdown-menu":e=>{let t=e.querySelector(".ml-dropdown-trigger"),n=e.querySelector(".ml-dropdown-menu");if(!t||!n)return[];let i=()=>[...n.querySelectorAll(".ml-dropdown-item")].filter(s=>!s.disabled&&s.getAttribute("aria-disabled")!=="true"),o=Te(n,t,()=>({side:"bottom",align:n.dataset.align==="end"?"end":"start",offset:6})),r=s=>{if(e.dataset.state=s?"open":"closed",n.dataset.state=s?"open":"closed",s?o.show():o.hide(),t.setAttribute("aria-expanded",String(s)),!s)for(let a of i())delete a.dataset.highlighted},l=()=>e.dataset.state==="open",c=s=>{for(let a of i())delete a.dataset.highlighted;s&&(s.dataset.highlighted="",s.focus())};return r(!1),[j(t,"click",()=>{if(l()){r(!1);return}r(!0),c(i()[0])}),j(e,"keydown",s=>{let a=i();if(s.key==="Escape"){if(!l())return;s.preventDefault(),r(!1),t.focus();return}if(s.key==="Tab"){r(!1);return}if(s.key==="ArrowDown"||s.key==="ArrowUp"){if(s.preventDefault(),!l()){r(!0),c(a[s.key==="ArrowDown"?0:a.length-1]);return}let d=a.findIndex(v=>"highlighted"in v.dataset),h=ye(a,d,s.key,{horizontal:!1});h>=0&&c(a[h])}}),j(n,"pointermove",s=>{let a=s.target.closest(".ml-dropdown-item");a&&i().includes(a)&&c(a)}),j(document,"pointerdown",s=>{l()&&!e.contains(s.target)&&r(!1)}),...o.cleanups]},switch:e=>{let t=i=>{e.setAttribute("aria-checked",String(i)),e.dataset.state=i?"checked":"unchecked"},n=()=>{let i=e.getAttribute("aria-checked")!=="true";t(i),Se(e,i)};return e.hasAttribute("aria-checked")||t(!1),[j(e,"click",n),j(e,"keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),n())})]},modal(e){let t=e.dataset.mlEscape!=="false",n=e.dataset.mlOverlay!=="false",i=null,o=()=>{},r=()=>document.querySelector(`.ml-modal-overlay[data-ml-for="${e.id}"], .ml-sheet-overlay[data-ml-for="${e.id}"]`),l=()=>{e.dataset.state="closed",e.hidden=!0;let s=r();s&&(s.hidden=!0),o(),o=()=>{},i&&document.contains(i)&&i.focus()},c=s=>{i=s??document.activeElement,e.dataset.state="open",e.hidden=!1;let a=r();a&&(a.hidden=!1),o(),o=Ze(),(Qe(e)[0]??e).focus()};return e.mlolaDialog={open:c,close:l},[j(document,"click",s=>{let a=s.target.closest(`[data-ml-opens="${e.id}"]`);if(a){s.preventDefault(),c(a);return}let d=s.target.closest(".ml-modal-close, .ml-sheet-close, [data-ml-close]");d&&e.contains(d)&&l(),n&&s.target===r()&&l()}),j(document,"keydown",s=>{if(e.hidden)return;if(s.key==="Escape"&&t&&!s.defaultPrevented){s.preventDefault(),l();return}if(s.key!=="Tab")return;let a=Qe(e),d=Ke(a.length,a.indexOf(document.activeElement),s.shiftKey);d<0||(s.preventDefault(),a[d].focus())})]},select(e){let t=e.querySelector(".ml-select"),n=e.querySelector(".ml-select-popover"),i=e.querySelector(".ml-select-list");if(!t||!n||!i)return[];let o=i.getAttribute("aria-multiselectable")==="true",r=()=>[...i.querySelectorAll(".ml-select-option")].filter(h=>h.getAttribute("aria-disabled")!=="true"),l=Te(n,t,()=>({side:"bottom",align:"start",offset:6,minWidth:t.offsetWidth})),c=h=>{if(t.dataset.state=h?"open":"closed",h?l.show():l.hide(),t.setAttribute("aria-expanded",String(h)),!h){for(let v of r())delete v.dataset.highlighted;t.removeAttribute("aria-activedescendant")}},s=()=>t.dataset.state==="open",a=h=>{for(let v of r())delete v.dataset.highlighted;h&&(h.dataset.highlighted="",h.id&&t.setAttribute("aria-activedescendant",h.id))},d=h=>{if(!h)return;let v=h.getAttribute("aria-selected")==="true";if(!o)for(let E of r())E.setAttribute("aria-selected","false"),E.dataset.state="unchecked";let x=o?!v:!0;h.setAttribute("aria-selected",String(x)),h.dataset.state=x?"checked":"unchecked";let I=e.querySelector(".ml-select-value"),N=E=>E.dataset.value??E.textContent.trim();I&&!o&&(I.textContent=h.textContent.trim(),delete I.dataset.placeholder),Se(e,o?r().filter(E=>E.dataset.state==="checked").map(N):N(h)),o||(c(!1),t.focus())};return c(!1),[j(t,"click",()=>c(!s())),j(i,"click",h=>d(h.target.closest(".ml-select-option"))),j(i,"pointermove",h=>{let v=h.target.closest(".ml-select-option");v&&r().includes(v)&&a(v)}),j(e,"keydown",h=>{let v=r();if(h.key==="Escape"){if(!s())return;h.preventDefault(),c(!1),t.focus();return}if(h.key==="Tab"){c(!1);return}if(h.key==="ArrowDown"||h.key==="ArrowUp"){if(h.preventDefault(),!s()){c(!0),a(v[h.key==="ArrowDown"?0:v.length-1]);return}let x=v.findIndex(N=>"highlighted"in N.dataset),I=ye(v,x,h.key,{horizontal:!1});I>=0&&a(v[I]);return}if(h.key==="Home"||h.key==="End"){if(!s())return;h.preventDefault(),a(h.key==="Home"?v[0]:v[v.length-1]);return}if(h.key==="Enter"||h.key===" "&&h.target!==e.querySelector(".ml-select-search")){if(h.preventDefault(),!s()){c(!0);return}d(v.find(x=>"highlighted"in x.dataset))}}),j(document,"pointerdown",h=>{s()&&!e.contains(h.target)&&c(!1)}),...l.cleanups]},slider(e){let t=e.querySelector(".ml-slider-track"),n=e.querySelector(".ml-slider-range"),i=e.querySelector(".ml-slider-thumb"),o=e.querySelector('[role="slider"]');if(!t||!o)return[];let r=()=>({min:Number(o.getAttribute("aria-valuemin")??0),max:Number(o.getAttribute("aria-valuemax")??100),step:Number(e.dataset.mlStep??1)}),l=e.dataset.disabled!==void 0||o.getAttribute("aria-disabled")==="true",c=e.querySelector(".ml-slider-output"),s=()=>Number(o.getAttribute("aria-valuenow")??r().min),a=x=>{let I=r(),N=he(x,I);o.setAttribute("aria-valuenow",String(N));let E=_e(N,I);n&&(n.style.width=`${E}%`),i&&(i.style.left=`${E}%`),c&&(c.textContent=String(N)),Se(e,N)},d=x=>{let I=t.getBoundingClientRect();return I.width?Ge((x.clientX-I.left)/I.width,r()):s()},h=e.querySelector(".ml-slider")??t,v=null;return[j(h,"pointerdown",x=>{if(l||x.button!==0)return;let I=x.pointerType==="touch";v={id:x.pointerId,touch:I,x:x.clientX,y:x.clientY,active:!I},I||(h.setPointerCapture?.(x.pointerId),a(d(x))),o.focus()}),j(h,"pointermove",x=>{if(!(l||!v||v.id!==x.pointerId)){if(!v.active){if(!Je(x.clientX-v.x,x.clientY-v.y))return;v.active=!0,h.setPointerCapture?.(x.pointerId)}a(d(x))}}),j(h,"pointerup",x=>{let I=v;v=null,h.releasePointerCapture?.(x.pointerId),!l&&I?.touch&&!I.active&&a(d(x))}),j(h,"pointercancel",()=>{v=null}),j(o,"keydown",x=>{if(l)return;let I=Ue(x.key,s(),r());I!==void 0&&(x.preventDefault(),a(I))})]},tooltip(e){let t=e.querySelector(".ml-tooltip"),n=e.firstElementChild;if(!t||!n)return[];let i=Number(e.dataset.mlDelay??200),o=t.dataset.side||"top",r=Te(t,n,()=>({side:o}),Ye),l=null,c=()=>{clearTimeout(l),l=setTimeout(()=>{t.dataset.state="open",r.show(),t.id&&n.setAttribute("aria-describedby",t.id)},Math.max(0,i))},s=()=>{clearTimeout(l),r.hide(),delete t.dataset.state,n.removeAttribute("aria-describedby")};return s(),[...r.cleanups,j(e,"pointerenter",c),j(e,"pointerleave",s),j(e,"focusin",c),j(e,"focusout",s),j(document,"keydown",a=>{a.key!=="Escape"||t.hidden||a.defaultPrevented||(a.preventDefault(),s())},!0)]},toast(e){let t=new Map,n=s=>Number(s.dataset.mlDuration??e.dataset.mlDuration??5e3),i=s=>{let a=t.get(s);a&&clearTimeout(a),t.delete(s),s.remove(),e.querySelector(".ml-toast")||e.dispatchEvent(new CustomEvent("ml-empty",{bubbles:!0}))},o=s=>{if("mlPaused"in s.dataset)return;let a=n(s),d=t.get(s);d&&clearTimeout(d),a>0&&t.set(s,setTimeout(()=>i(s),a))},r=s=>{s.dataset.mlEnhanced===void 0&&(s.dataset.mlEnhanced="",o(s))},l=()=>[...e.querySelectorAll(".ml-toast")];e.hasAttribute("role")||e.setAttribute("role","region"),e.showPopover&&(e.popover="manual",e.showPopover());for(let s of l())r(s);let c=new MutationObserver(s=>{for(let a of s)for(let d of a.addedNodes){if(d.nodeType!==1)continue;let h=d.matches?.(".ml-toast")?[d,...d.querySelectorAll(".ml-toast")]:[...d.querySelectorAll(".ml-toast")];for(let v of h)r(v)}});return c.observe(e,{childList:!0,subtree:!0}),[j(e,"click",s=>{let a=s.target.closest(".ml-toast");!a||!e.contains(a)||s.target.closest(".ml-toast-close")&&(s.preventDefault(),i(a))}),j(e,"pointerenter",s=>{let a=s.target.closest(".ml-toast");a&&(a.dataset.mlPaused="",o(a))},!0),j(e,"pointerleave",s=>{let a=s.target.closest(".ml-toast");a&&(delete a.dataset.mlPaused,o(a))},!0),j(e,"focusin",s=>{let a=s.target.closest(".ml-toast");a&&(a.dataset.mlPaused="",o(a))}),j(e,"focusout",s=>{let a=s.target.closest(".ml-toast");a&&(delete a.dataset.mlPaused,o(a))}),()=>{c.disconnect();for(let s of t.values())clearTimeout(s)}]}};Le.sheet=Le.modal;function et(e=document){let t=[...e.matches?.("[data-ml]")?[e]:[],...e.querySelectorAll("[data-ml]")],n=0;for(let i of t){if(i[Ae])continue;let o=Le[i.dataset.ml];if(!o)continue;let r=o(i)??[];i[Ae]=()=>{for(let l of r)l();delete i[Ae]},n+=1}return n}var me=["createSurface","updateComponents","updateDataModel","deleteSurface"],yt=new Set(["id","component","accessibility"]),kt=new Set(["style","className","class","css","color","background","backgroundColor","theme","sx","tw"]),Ce=new Set(["__proto__","prototype","constructor"]),vt=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/,wt=/^[A-Za-z0-9_-]{1,64}$/,xt=/^(\d{4})-(\d{2})-(\d{2})$/,ie=e=>{let t=typeof e=="string"?xt.exec(e):null;if(!t)return!1;let[n,i,o]=t.slice(1).map(Number),r=new Date(Date.UTC(n,i-1,o));return r.getUTCFullYear()===n&&r.getUTCMonth()===i-1&&r.getUTCDate()===o};var D=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),ce=(e,t)=>Object.hasOwn(e,t)?e[t]:void 0,Z=e=>e===null?"null":Array.isArray(e)?"an array":typeof e=="object"?"an object":`a ${typeof e}`,y=e=>e!==null&&typeof e=="object"?Z(e):typeof e=="string"&&e.length>80?JSON.stringify(`${e.slice(0,77)}\u2026`):String(JSON.stringify(e)),$t=e=>String(e).replaceAll("~","~0").replaceAll("/","~1"),k=(e,...t)=>t.reduce((n,i)=>`${n}/${$t(i)}`,e),ne=e=>e.map(t=>y(t)).join(", ");function tt(e,t){if(typeof e!="string")return{messages:e,error:null};if(t&&e.length>t.inputBytes)return{messages:null,error:`The input is ${e.length} characters; at most ${t.inputBytes} are checked at a time. Send fewer messages per call.`};let n=e.trim();if(!n)return{messages:null,error:"The input is empty. Pass A2UI messages: one object, an array, or one object per line."};try{return{messages:JSON.parse(n),error:null}}catch(i){let o=n.split(`
8475
- `).map(r=>r.trim()).filter(Boolean);if(o.length>1){let r=[];for(let[l,c]of o.entries())try{r.push(JSON.parse(c))}catch(s){return{messages:null,error:`Line ${l+1} is not JSON: ${s.message}`}}return{messages:r,error:null}}return{messages:null,error:`The input is not JSON: ${i.message}`}}}function qe(e){return{rules:e,surfaces:new Map}}function nt(e,t){let n={errors:[],advice:[]},i=D(t),o=i?[t]:t;if(!Array.isArray(o))return n.errors.push(m("","",`Expected A2UI messages: an object with "version" and one of ${me.join(", ")}, or an array of them. Got ${Z(t)}.`)),n;let{limits:r}=e.rules;if(o.length||n.errors.push(m("","","There are no messages. Start with createSurface, then updateComponents.")),o.length>r.messages)return n.errors.push(m("","",`At most ${r.messages} messages are checked at a time; this is ${o.length}. Check the rest in another call.`)),n;for(let[l,c]of o.entries())At(e,c,i?"":`/${l}`,n);return n}function ot(e,t){let n={errors:[],advice:[]},i=e.surfaces.get(t);if(!i||i.deleted)return n;n.errors.push(...i.problems);for(let o of i.components.values())rt(e.rules,i.id,o.props,o.at,n);return i.components.size&&Ht(e.rules,i,n),n}function m(e,t,n){return{code:"VALIDATION_FAILED",surfaceId:e??"",path:t,message:n}}function Me(e,t,n){return{code:"ADVICE",surfaceId:e??"",path:t,message:n}}function At(e,t,n,i){let{rules:o}=e;if(!D(t)){i.errors.push(m("",n,`A message is an object with "version" and one of ${me.join(", ")}; this one is ${Z(t)}.`));return}let r=me.filter(h=>h in t),l=r.length===1&&D(t[r[0]])&&typeof t[r[0]].surfaceId=="string"?t[r[0]].surfaceId:"";if(o.protocolVersions.includes(t.version)||i.errors.push(m(l,k(n,"version"),t.version===void 0?`Add "version": ${y(o.protocolVersions.at(-1))} to every message.`:`Version ${y(t.version)} is not supported; use ${ne(o.protocolVersions)}.`)),r.length!==1){i.errors.push(m(l,n,r.length?`A message carries one of ${me.join(", ")}; this one has ${r.join(" and ")}. Send them as separate messages.`:`A message carries one of ${me.join(", ")}; this one has none.`));return}for(let h of Object.keys(t))h!=="version"&&h!==r[0]&&i.errors.push(m(l,k(n,h),`A message holds only "version" and ${y(r[0])}; remove ${y(h)}.`));let c=r[0],s=t[c],a=k(n,c);if(!D(s)){i.errors.push(m("",a,`${c} is an object; got ${Z(s)}.`));return}let d=s.surfaceId;if(typeof d!="string"||!d.trim()||d.length>o.limits.idLength){i.errors.push(m("",k(a,"surfaceId"),`${c} needs a "surfaceId": a string of 1 to ${o.limits.idLength} characters that names the surface.`));return}if(c==="createSurface")St(e,s,a,i);else{let h=e.surfaces.get(d);if(!h||h.deleted){i.errors.push(m(d,k(a,"surfaceId"),h?.deleted?`Surface ${y(d)} was deleted; send createSurface again before ${c}.`:`No surface is called ${y(d)}. Send createSurface for it first, in the same messages.`));return}c==="updateComponents"?Lt(o,h,s,a,i):c==="updateDataModel"?Mt(o,h,s,a,i):Tt(e,h,s,a,i)}}function oe(e,t,n,i,o,r){for(let l of Object.keys(e))t.includes(l)||o.errors.push(m(i,k(n,l),`${r} does not take ${y(l)}. It takes ${ne(t)}.`))}function St(e,t,n,i){let{rules:o}=e,{surfaceId:r}=t,l=i.errors.length;oe(t,["surfaceId","catalogId","theme","sendDataModel"],n,r,i,"createSurface"),t.catalogId!==o.catalogId&&i.errors.push(m(r,k(n,"catalogId"),`Set "catalogId" to ${y(o.catalogId)}: this renderer draws the Mlola catalog${typeof t.catalogId=="string"?`, not ${y(t.catalogId)}`:""}.`)),t.sendDataModel!==void 0&&typeof t.sendDataModel!="boolean"&&i.errors.push(m(r,k(n,"sendDataModel"),'"sendDataModel" is true or false.'));let c={name:o.defaultTheme,mode:"system"};if(t.theme!==void 0){let d=k(n,"theme");if(!D(t.theme))i.errors.push(m(r,d,`"theme" is an object like {"name": ${y(o.defaultTheme)}, "mode": "system"}.`));else{for(let h of Object.keys(t.theme))h==="name"||h==="mode"||i.errors.push(m(r,k(d,h),/color|font|radius|spacing|icon/i.test(h)?`Colors, type and shape come from the theme; pick one by name instead of setting ${y(h)}: ${ne(o.themes)}.`:`"theme" takes "name" and "mode"; remove ${y(h)}.`));t.theme.name!==void 0&&(o.themes.includes(t.theme.name)?c.name=t.theme.name:i.errors.push(m(r,k(d,"name"),`Theme ${y(t.theme.name)} does not exist; use ${ne(o.themes)}.`))),t.theme.mode!==void 0&&(o.modes.includes(t.theme.mode)?c.mode=t.theme.mode:i.errors.push(m(r,k(d,"mode"),`Mode ${y(t.theme.mode)} does not exist; use ${ne(o.modes)} (system follows the reader's setting).`)))}}let s=e.surfaces.get(r);if(s&&!s.deleted){i.errors.push(m(r,k(n,"surfaceId"),`Surface ${y(r)} already exists. Use another surfaceId, or send deleteSurface first.`));return}let a=0;for(let d of e.surfaces.values())d.deleted||(a+=1);if(a>=o.limits.surfaces){i.errors.push(m(r,n,`At most ${o.limits.surfaces} surfaces are open at once; send deleteSurface for one that is done.`));return}e.surfaces.delete(r),e.surfaces.set(r,{id:r,theme:c,sendDataModel:t.sendDataModel===!0,deleted:!1,components:new Map,data:{},dataBytes:0,at:n,problems:i.errors.slice(l)})}function Tt(e,t,n,i,o){oe(n,["surfaceId"],i,t.id,o,"deleteSurface"),t.deleted=!0,t.components=new Map,t.data={},t.dataBytes=0;let r=[...e.surfaces.values()].filter(l=>l.deleted);for(let l of r.slice(0,Math.max(0,r.length-e.rules.limits.surfaces)))e.surfaces.delete(l.id)}function Lt(e,t,n,i,o){oe(n,["surfaceId","components"],i,t.id,o,"updateComponents");let r=k(i,"components");if(!Array.isArray(n.components)||!n.components.length){o.errors.push(m(t.id,r,'"components" is a non-empty array of components, each with an "id" and a "component".'));return}if(n.components.length>e.limits.components){o.errors.push(m(t.id,r,`This message sends ${n.components.length} components; a surface holds at most ${e.limits.components}. Split it into more surfaces.`));return}let l=new Set;for(let[c,s]of n.components.entries()){let a=k(r,c);if(!D(s)){o.errors.push(m(t.id,a,`A component is an object with "id" and "component"; got ${Z(s)}.`));continue}let{id:d}=s;if(typeof d!="string"||!d.trim()||d.length>e.limits.idLength){o.errors.push(m(t.id,k(a,"id"),`Every component needs an "id": a string of 1 to ${e.limits.idLength} characters, unique on the surface.`));continue}if(l.has(d)){o.errors.push(m(t.id,k(a,"id"),`Two components in this message have the id ${y(d)}; give each its own.`));continue}if(l.add(d),!t.components.has(d)&&t.components.size>=e.limits.components){o.errors.push(m(t.id,a,`A surface holds at most ${e.limits.components} components; split it into more surfaces.`));break}let h=rt(e,t.id,s,a,o);t.components.set(d,{id:d,type:s.component,props:s,definition:h,at:a})}}function Mt(e,t,n,i,o){oe(n,["surfaceId","path","value"],i,t.id,o,"updateDataModel");let r=n.path??"/",l=k(i,"path");if(typeof r!="string"||r!==""&&!Ee(r,{absolute:!0,rules:e})){o.errors.push(m(t.id,l,'"path" is a JSON Pointer like "/form/email", or "/" for the whole data model.'));return}let c=0,s;try{let d=n.value===void 0?void 0:JSON.stringify(n.value);s=d===void 0?void 0:JSON.parse(d),c=t.dataBytes-Ct(ge(t.data,r))+(d?.length??0)}catch{o.errors.push(m(t.id,k(i,"value"),"This value is nested too deeply to read; flatten it."));return}if(c>e.limits.dataBytes){o.errors.push(m(t.id,k(i,"value"),`A surface's data model holds at most ${e.limits.dataBytes} bytes of JSON; send less, or page through it.`));return}let a=je(t.data,r,s);if(a.error){o.errors.push(m(t.id,l,a.error));return}t.data=a.root,t.dataBytes=c}var Ct=e=>e===void 0?0:JSON.stringify(e)?.length??0;function rt(e,t,n,i,o){let r=n.component,l=k(i,"component");if(typeof r!="string"||!r)return o.errors.push(m(t,l,'Every component names its type in "component", for example "Stack", "Text" or "Button".')),null;let c=ce(e.components,r);if(!c)return o.errors.push(m(t,l,Ot(e,r))),null;for(let[s,a]of Object.entries(n)){if(yt.has(s))continue;let d=ce(c.props,s),h=k(i,s);if(!d){o.errors.push(m(t,h,It(e,r,c,s)));continue}Dt(e,t,r,s,d,a,h,o)}for(let[s,a]of Object.entries(c.props))a.required&&n[s]===void 0&&o.errors.push(m(t,i,`${r} needs ${y(s)}${a.description?`: ${qt(a.description)}`:"."}`));return n.accessibility!==void 0&&jt(e,t,n.accessibility,k(i,"accessibility"),o),Wt(e,t,r,c,n,i,o),c}var qt=e=>e.charAt(0).toLowerCase()+e.slice(1);function Ot(e,t){let n=ce(e.aliases,t)??Object.keys(e.components).find(o=>o.toLowerCase()===t.toLowerCase());if(n)return`${y(t)} is not in the Mlola catalog; use ${y(n)}.`;let i=ce(e.borrowed.components,t);return i?`${y(t)} is not in the Mlola catalog. ${i}`:`${y(t)} is not in the Mlola catalog. It has: ${Et(e).map(([o,r])=>`${o} (${r.join(", ")})`).join("; ")}.`}function Et(e){return Object.entries(e.groups).map(([t,n])=>[n,Object.keys(e.components).filter(i=>e.components[i].group===t)])}function It(e,t,n,i){let o=Object.keys(n.props),r=ce(e.borrowed.props,`${t}.${i}`)??ce(e.borrowed.props,i);return r?`${t} does not take ${y(i)}. ${r}`:kt.has(i)?`${t} takes no ${y(i)}: Mlola Render draws with the surface's theme. Choose a named value instead (${o.filter(l=>n.props[l].kind==="enum").join(", ")||"none on this component"}).`:i==="child"&&o.includes("children")?`${t} takes "children", an array of ids, not "child".`:i==="checks"?'Client-side checks are not in the Mlola catalog yet; use "required" on the field, and check the values when the action arrives.':/^on[A-Z]/.test(i)?`${t} does not take ${y(i)}. A Button's "action" sends an event to the agent; inputs bind their value with {"path": \u2026}.`:`${t} does not take ${y(i)}. It takes: ${o.join(", ")}.`}function jt(e,t,n,i,o){if(!D(n)){o.errors.push(m(t,i,'"accessibility" is an object with "label" and "description".'));return}for(let[r,l]of Object.entries(n)){if(r!=="label"&&r!=="description"){o.errors.push(m(t,k(i,r),`"accessibility" takes "label" and "description"; remove ${y(r)}.`));continue}Oe(e,t,l,k(i,r),{maxLength:e.limits.labelLength},!1,o)}}function Dt(e,t,n,i,o,r,l,c){switch(o.kind){case"text":return Oe(e,t,r,l,o,o.required,c,`${n} ${y(i)}`);case"boolean":return typeof r=="boolean"||!o.literal&&le(e,t,r,l,c)?void 0:c.errors.push(m(t,l,`${n} ${y(i)} is true or false${o.literal?"":', or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"number":return typeof r=="number"&&Number.isFinite(r)||!o.literal&&le(e,t,r,l,c)?void 0:c.errors.push(m(t,l,`${n} ${y(i)} is a number${o.literal?"":' or {"path": "/\u2026"}'}; got ${Z(r)}.`));case"integer":return Number.isInteger(r)&&r>=o.minimum&&r<=o.maximum?void 0:c.errors.push(m(t,l,`${n} ${y(i)} is a whole number from ${o.minimum} to ${o.maximum}; got ${y(r)}.`));case"date":return ie(r)||!o.literal&&le(e,t,r,l,c)?void 0:c.errors.push(m(t,l,`${n} ${y(i)} is a day written as an ISO date, like "2026-10-12"${o.literal?"":', or {"path": "/\u2026"}'}; got ${y(r)}.`));case"enum":return typeof r=="string"&&o.values.includes(r)?void 0:c.errors.push(m(t,l,Pt(e,n,i,o,r)));case"children":return Nt(e,t,n,i,o,r,l,c);case"action":return Bt(e,t,r,l,c);case"options":return zt(e,t,n,o,r,l,c);case"columns":return Rt(e,t,o,r,l,c);case"rows":return Ft(e,t,r,l,c);default:return c.errors.push(m(t,l,`${n} ${y(i)} has a kind this validator does not know (${o.kind}).`))}}function Pt(e,t,n,i,o){if(typeof o=="string"){let r=i.values.find(c=>c.toLowerCase()===o.toLowerCase());if(r)return`${t} ${y(n)} is ${y(r)}, not ${y(o)}: values are case-sensitive.`;let l=ce(e.borrowed.props,`${t}.${n}=${o}`);if(l)return`${t} ${y(n)} ${y(o)} is not in the catalog. ${l}`;if(i.excluded?.includes(o))return`${t} ${y(n)} ${y(o)} is not in the catalog: ${i.description??"it needs content the catalog does not offer."} Use ${ne(i.values)}.`}return`${t} ${y(n)} ${typeof o=="string"?`${y(o)} does not exist`:`is a name, not ${Z(o)}`}; use ${ne(i.values)}.`}function Oe(e,t,n,i,o,r,l,c="This text"){if(typeof n=="string"){let s=o.maxLength??e.limits.textLength;n.length>s?l.errors.push(m(t,i,`${c} is ${n.length} characters; keep it to ${s}.`)):r&&!n.trim()&&l.errors.push(m(t,i,`${c} is empty. It is what a person sees and a screen reader reads; write the words.`));return}if(!le(e,t,n,i,l)){if(D(n)&&"call"in n){l.errors.push(m(t,i,'Functions are not in the Mlola catalog yet; use a literal string or {"path": "/\u2026"}.'));return}l.errors.push(m(t,i,`${c} is a string or {"path": "/\u2026"}; got ${Z(n)}.`))}}function le(e,t,n,i,o){if(!D(n)||!("path"in n))return!1;let r=Object.keys(n).filter(l=>l!=="path");return r.length&&o.errors.push(m(t,i,`A binding holds only "path"; remove ${ne(r)}.`)),(typeof n.path!="string"||!Ee(n.path,{rules:e}))&&o.errors.push(m(t,k(i,"path"),`${y(n.path)} is not a data path. Write a JSON Pointer like "/form/email" (or "name" inside a template), at most ${e.limits.pathLength} characters.`)),!0}function Ee(e,{absolute:t=!1,rules:n}){if(!e||e.length>n.limits.pathLength)return!1;if(t&&e==="/")return!0;if(t&&!e.startsWith("/"))return!1;let i=(e.startsWith("/")?e.slice(1):e).split("/");for(let o of i)if(/~(?![01])/.test(o)||Ce.has(Ie(o)))return!1;return!0}var Ie=e=>e.replaceAll("~1","/").replaceAll("~0","~");function Nt(e,t,n,i,o,r,l,c){if(Array.isArray(r)){r.length<(o.minItems??0)&&c.errors.push(m(t,l,`${n} needs at least ${o.minItems} ${o.minItems===1?"child":"children"}.`)),r.length>e.limits.components&&c.errors.push(m(t,l,`${n} lists ${r.length} children; a surface holds at most ${e.limits.components} components.`));let s=new Set;for(let[a,d]of r.entries())typeof d!="string"||!d?c.errors.push(m(t,k(l,a),`A child is a component id (a string); got ${Z(d)}.`)):s.has(d)?c.errors.push(m(t,k(l,a),`${y(d)} is listed twice in ${n}'s children; a component appears in one place.`)):s.add(d);return}if(D(r)&&("componentId"in r||"path"in r)){oe(r,["componentId","path"],l,t,c,"A template"),(typeof r.componentId!="string"||!r.componentId)&&c.errors.push(m(t,k(l,"componentId"),'A template names the component to repeat in "componentId".')),(typeof r.path!="string"||!Ee(r.path,{rules:e}))&&c.errors.push(m(t,k(l,"path"),`A template's "path" points at an array in the data model, like "/items".`));return}c.errors.push(m(t,l,`${n} ${y(i)} is an array of component ids, or a template {"componentId", "path"}; got ${Z(r)}.`))}function Bt(e,t,n,i,o){if(!D(n)){o.errors.push(m(t,i,`"action" is {"event": {"name": "\u2026", "context": {\u2026}}}; got ${Z(n)}.`));return}if("functionCall"in n){o.errors.push(m(t,k(i,"functionCall"),'Client-side functions are not in the Mlola catalog yet; send an event and handle it in the agent: {"event": {"name": "\u2026"}}.'));return}oe(n,["event"],i,t,o,"An action");let r=n.event,l=k(i,"event");if(!D(r)){o.errors.push(m(t,l,'An action sends an event: {"name": "\u2026", "context": {\u2026}}.'));return}if(oe(r,["name","context"],l,t,o,"An event"),(typeof r.name!="string"||!vt.test(r.name))&&o.errors.push(m(t,k(l,"name"),`An event's "name" starts with a letter and uses letters, digits, _ . : or - (at most 64), like "create_workspace".`)),r.context===void 0)return;let c=k(l,"context");if(!D(r.context)){o.errors.push(m(t,c,`An event's "context" is an object of values or {"path": \u2026} bindings.`));return}let s=Object.keys(r.context);s.length>e.limits.contextKeys&&o.errors.push(m(t,c,`An event's context holds at most ${e.limits.contextKeys} values; bind a whole object with {"path": "/form"} instead.`));for(let a of s.slice(0,e.limits.contextKeys)){let d=r.context[a],h=k(c,a);Ce.has(a)?o.errors.push(m(t,h,`${y(a)} cannot be a context key.`)):D(d)&&!le(e,t,d,h,o)?o.errors.push(m(t,h,'A context value is a string, number, boolean, array or {"path": \u2026}; an object needs a binding.')):Array.isArray(d)&&d.some(v=>v!==null&&typeof v=="object")?o.errors.push(m(t,h,'An array in the context holds strings, numbers and true or false; for a list from the data model use {"path": "/\u2026"}.')):typeof d=="string"&&d.length>e.limits.textLength&&o.errors.push(m(t,h,`This value is ${d.length} characters; keep it to ${e.limits.textLength}.`))}}function zt(e,t,n,i,o,r,l){if(le(e,t,o,r,l))return;if(!Array.isArray(o)){l.errors.push(m(t,r,`${n} "options" is an array of {"label", "value"}, or {"path": "/\u2026"}; got ${Z(o)}.`));return}if(o.length<(i.minItems??1)&&l.errors.push(m(t,r,`${n} needs at least ${i.minItems} options${n==="RadioGroup"?"; for one yes or no choice use a Checkbox":""}.`)),o.length>e.limits.options){l.errors.push(m(t,r,`${n} lists ${o.length} options; keep it to ${e.limits.options}.`));return}let c=new Set;for(let[s,a]of o.entries()){let d=k(r,s);if(!D(a)){l.errors.push(m(t,d,`An option is {"label": "\u2026", "value": "\u2026"}; got ${Z(a)}.`));continue}oe(a,["label","value"],d,t,l,"An option"),(typeof a.label!="string"||!a.label.trim()||a.label.length>e.limits.labelLength)&&l.errors.push(m(t,k(d,"label"),`An option's "label" is the words a person picks, 1 to ${e.limits.labelLength} characters.`)),typeof a.value!="string"||!a.value||a.value.length>e.limits.labelLength?l.errors.push(m(t,k(d,"value"),`An option's "value" is the string sent back, 1 to ${e.limits.labelLength} characters.`)):c.has(a.value)?l.errors.push(m(t,k(d,"value"),`Two options have the value ${y(a.value)}; give each its own.`)):c.add(a.value)}}function Rt(e,t,n,i,o,r){if(!Array.isArray(i)||i.length<(n.minItems??1)){r.errors.push(m(t,o,'"columns" is a non-empty array of {"key", "label", "align"?}.'));return}if(i.length>e.limits.columns){r.errors.push(m(t,o,`A table shows at most ${e.limits.columns} columns; more cannot be read on a phone.`));return}let l=new Set;for(let[c,s]of i.entries()){let a=k(o,c);if(!D(s)){r.errors.push(m(t,a,`A column is {"key": "\u2026", "label": "\u2026"}; got ${Z(s)}.`));continue}oe(s,["key","label","align"],a,t,r,"A column"),typeof s.key!="string"||!wt.test(s.key)||Ce.has(s.key)?r.errors.push(m(t,k(a,"key"),`A column's "key" names the row field it shows: letters, digits, _ or -, like "order".`)):l.has(s.key)?r.errors.push(m(t,k(a,"key"),`Two columns have the key ${y(s.key)}.`)):l.add(s.key),Oe(e,t,s.label,k(a,"label"),{maxLength:e.limits.labelLength},!0,r,`The column's "label"`),s.align!==void 0&&!n.align.values.includes(s.align)&&r.errors.push(m(t,k(a,"align"),`"align" is ${ne(n.align.values)}.`))}}function Ft(e,t,n,i,o){if(!le(e,t,n,i,o)){if(!Array.isArray(n)){o.errors.push(m(t,i,`"rows" is an array of objects, or {"path": "/\u2026"} to one in the data model; got ${Z(n)}.`));return}if(n.length>e.limits.rows){o.errors.push(m(t,i,`A table holds at most ${e.limits.rows} rows; page through the rest.`));return}for(let[r,l]of n.entries()){let c=k(i,r);if(!D(l)){o.errors.push(m(t,c,`A row is an object keyed by column key; got ${Z(l)}.`));continue}for(let[s,a]of Object.entries(l))a===null||typeof a=="number"||typeof a=="boolean"||typeof a=="string"&&a.length<=e.limits.textLength||o.errors.push(m(t,k(c,s),typeof a=="string"?`A cell holds at most ${e.limits.textLength} characters.`:`A cell holds text, a number or true/false; got ${Z(a)}.`))}}}function Wt(e,t,n,i,o,r,l){let c=s=>typeof o[s]=="number"?o[s]:i.props[s]?.default;if(n==="Slider"){let s=c("min"),a=c("max"),d=c("step");typeof s=="number"&&typeof a=="number"&&s>=a&&l.errors.push(m(t,k(r,"max"),`Slider "max" (${a}) must be greater than "min" (${s}).`)),typeof d=="number"&&(d<=0||d>a-s)&&l.errors.push(m(t,k(r,"step"),'Slider "step" is greater than 0 and at most max minus min.')),typeof o.value=="number"&&(o.value<s||o.value>a)&&l.errors.push(m(t,k(r,"value"),`Slider "value" ${o.value} is outside ${s} to ${a}.`))}if(n==="Progress"){let s=c("max");typeof s=="number"&&s<=0&&l.errors.push(m(t,k(r,"max"),'Progress "max" is greater than 0.')),typeof o.value=="number"&&(o.value<0||o.value>s)&&l.errors.push(m(t,k(r,"value"),`Progress "value" ${o.value} is outside 0 to ${s}.`))}if(n==="DatePicker"){let{min:s,max:a,value:d}=o;ie(s)&&ie(a)&&s>a?l.errors.push(m(t,k(r,"max"),`DatePicker "max" (${a}) comes before "min" (${s}); make it the later day.`)):ie(d)&&(ie(s)&&d<s||ie(a)&&d>a)&&l.errors.push(m(t,k(r,"value"),`DatePicker "value" ${d} is outside ${ie(s)?s:"any day"} to ${ie(a)?a:"any day"}.`))}if((n==="Select"||n==="RadioGroup")&&typeof o.value=="string"&&Array.isArray(o.options)){let s=o.options.filter(D).map(a=>a.value);s.includes(o.value)||l.errors.push(m(t,k(r,"value"),`${n} "value" ${y(o.value)} is not one of its options (${ne(s)}).`))}}function fe(e){let t=e.props.children;return Array.isArray(t)?{ids:t.filter(n=>typeof n=="string"),template:null}:D(t)&&typeof t.componentId=="string"?{ids:[t.componentId],template:t}:{ids:[],template:null}}function Ht(e,t,n){let{components:i}=t,o=i.get("root");if(!o){n.errors.push(m(t.id,t.at,'No component has the id "root". One component is the root of the tree; give it "id": "root".'));return}let r=new Map;for(let d of i.values()){let{ids:h,template:v}=fe(d),x=k(d.at,"children");for(let[I,N]of h.entries()){let E=v?k(x,"componentId"):k(x,I),w=i.get(N);if(!w){n.errors.push(m(t.id,E,`No component has the id ${y(N)}. Add it, or remove it from ${d.type}'s children.`));continue}if(N===d.id){n.errors.push(m(t.id,E,`${y(N)} lists itself as a child: the children form a loop. A component cannot be inside its own tree.`));continue}if(N==="root"){n.errors.push(m(t.id,E,'"root" is the top of the tree and cannot be a child.'));continue}let M=r.get(N);if(M&&M!==d.id){n.errors.push(m(t.id,E,`${y(N)} is already a child of ${y(M)}. A component appears in one place; give the second one its own id.`));continue}r.set(N,d.id),w.definition?.parents&&d.definition&&!w.definition.parents.includes(d.type)&&n.errors.push(m(t.id,E,`${w.type} goes directly inside ${w.definition.parents.join(" or ")}, not inside ${d.type}.`)),d.definition?.accepts&&w.definition&&!d.definition.accepts.includes(w.type)&&n.errors.push(m(t.id,E,`${d.type} holds only ${d.definition.accepts.join(" and ")} components; ${y(N)} is a ${w.type}.`))}}for(let d of i.values())d.definition?.parents&&d.id!=="root"&&!r.has(d.id)&&n.errors.push(m(t.id,d.at,`${d.type} goes directly inside ${d.definition.parents.join(" or ")}; list ${y(d.id)} in one's children.`));let l=new Set(["root"]),c=new Set,s=[],a=[{node:o,depth:1,templated:!1}];for(;a.length;){let{node:d,depth:h,templated:v}=a.pop();if(s.push(d),v&&c.add(d.id),h>e.limits.depth){n.errors.push(m(t.id,d.at,`The tree is more than ${e.limits.depth} levels deep at ${y(d.id)}; flatten it.`));continue}let{ids:x,template:I}=fe(d);for(let N=x.length-1;N>=0;N-=1){let E=i.get(x[N]);if(!(!E||r.get(E.id)!==d.id)){if(l.has(E.id)){n.errors.push(m(t.id,k(d.at,"children"),`${y(E.id)} contains itself: the children form a loop. A component cannot be inside its own tree.`));continue}l.add(E.id),a.push({node:E,depth:h+1,templated:v||!!I})}}}for(let d of i.values())!l.has(d.id)&&!(d.definition?.parents&&!r.has(d.id))&&n.advice.push(Me(t.id,d.at,`${y(d.id)} is not inside "root", so it will not show. List it in a parent's children, or remove it.`));Gt(e,t,s,c,n),_t(t,s,n)}function Gt(e,t,n,i,o){let r=c=>D(c)&&typeof c.path=="string"&&!c.path.startsWith("/"),l=(c,s)=>o.errors.push(m(t.id,k(s,"path"),`${y(c.path)} is relative, which only works inside a template; write it from the top of the data model, like "/${c.path}".`));for(let c of n)if(!(i.has(c.id)||!c.definition))for(let[s,a]of Object.entries(c.props)){let d=k(c.at,s);if(s==="children")r(a)&&o.errors.push(m(t.id,k(d,"path"),`A template's "path" points at an array from the top of the data model, like "/${a.path}"; a relative path works only inside another template.`));else if(s==="accessibility"&&D(a))for(let h of["label","description"])r(a[h])&&l(a[h],k(d,h));else if(s==="action"&&D(a)&&D(a.event)&&D(a.event.context))for(let[h,v]of Object.entries(a.event.context))r(v)&&l(v,k(d,"event","context",h));else r(a)&&l(a,d)}}function _t(e,t,n){let i=0,o=null,r=new Map,l=(c,s)=>c.props[s]??c.definition?.props[s]?.default;for(let c of t){if(c.type==="Heading"&&Number.isInteger(l(c,"level"))){let a=l(c,"level");i&&a>i+1&&n.errors.push(m(e.id,k(c.at,"level"),`This heading jumps from level ${i} to ${a}; use ${i+1}. A screen reader uses the levels to move through the surface.`)),i=a}c.type==="Button"&&l(c,"variant")==="primary"&&(o?n.advice.push(Me(e.id,k(c.at,"variant"),`${y(o)} is already the primary action; keep one primary Button per surface and make this one "secondary".`)):o=c.id);let s=typeof c.props.label=="string"?c.props.label.trim().toLowerCase():null;s&&c.definition?.group==="form"&&(r.has(s)?n.advice.push(Me(e.id,k(c.at,"label"),`${y(r.get(s))} has the same label; give each field its own so they can be told apart.`)):r.set(s,c.id))}}var it=/^(0|[1-9][0-9]{0,5})$/;function ge(e,t){if(t===""||t==="/")return e;let n=e;for(let i of t.slice(1).split("/").map(Ie)){if(!D(n)&&!Array.isArray(n)||Array.isArray(n)&&!it.test(i))return;n=Object.hasOwn(n,i)?n[i]:void 0}return n}function je(e,t,n){if(t===""||t==="/")return{root:n===void 0?{}:n};let i=t.slice(1).split("/").map(Ie),o=D(e)||Array.isArray(e)?e:{},r=o;for(let[c,s]of i.entries()){if(Array.isArray(r)&&!it.test(s))return{error:`${y(i.slice(0,c).join("/")||"/")} holds an array, so the next segment is an index like 0, not ${y(s)}.`};if(Array.isArray(r)&&Number(s)>r.length)return{error:`${y(i.slice(0,c).join("/")||"/")} holds ${r.length} ${r.length===1?"item":"items"}, so the next index is at most ${r.length}, not ${s}.`};if(c===i.length-1)break;!D(r[s])&&!Array.isArray(r[s])&&(r[s]={}),r=r[s]}let l=i.at(-1);return n===void 0?delete r[l]:r[l]=n,{root:o}}var Ut=["createSurface","updateComponents","updateDataModel","deleteSurface"],Jt=/^(?:\/\d+)?\/(?:createSurface|updateComponents|updateDataModel|deleteSurface)(\/.*)?$/,Vt=new Set(["EmptyState","Accordion"]),J=e=>D(e)&&typeof e.path=="string",De=e=>e!==null&&typeof e=="object"?JSON.parse(JSON.stringify(e)):e;function be(e,t=""){return e.startsWith("/")?e:e?`${t}/${e}`:t||"/"}function st(e,t="v0.9.1"){let n=Jt.exec(e.path);return{version:t,error:{code:e.code,surfaceId:e.surfaceId,path:n?n[1]||"/":e.path||"/",message:e.message}}}function at(e,t={}){let n=t,i=qe(e),o=n.version??e.protocolVersions.at(-1),r=n.now??(()=>new Date),l=new Map,c=new Set,s=new Set,a=0,d=[],h=b=>{n.onError?n.onError(b):d.push(...b)},v=0,x=()=>{a+=1;for(let b of[...c])b()};function I(b){let u=new Map,T=b.get("root");if(!T)return u;let W=new Set(["root"]),L=[T],S=1;for(;L.length;){let A=L.pop();A.type==="Heading"?S=Number.isInteger(A.props.level)?A.props.level:A.definition?.props.level?.default??2:Vt.has(A.type)&&u.set(A.id,Math.min(6,S+1));let{ids:G}=fe(A);for(let K=G.length-1;K>=0;K-=1){let Y=b.get(G[K]);Y&&!W.has(Y.id)&&(W.add(Y.id),L.push(Y))}}return u}function N(b,{streaming:u=!1}={}){let T=tt(b,e.limits);if(T.error){let S={errors:[{code:"VALIDATION_FAILED",surfaceId:"",path:"",message:T.error}],advice:[]};return h(S.errors.map(A=>st(A,o))),S}let L=Array.isArray(T.messages)&&!T.messages.length?{errors:[],advice:[]}:nt(i,T.messages);for(let S of Array.isArray(T.messages)?T.messages:[T.messages])if(D(S))for(let A of Ut)D(S[A])&&typeof S[A].surfaceId=="string"&&s.add(S[A].surfaceId);for(let S of[...l.keys()]){let A=i.surfaces.get(S);(!A||A.deleted)&&l.delete(S)}if(!u){let S=new Set(L.errors.map(A=>`${A.path}\0${A.message}`));for(let A of s){let G=i.surfaces.get(A);if(!G||G.deleted||!G.components.size)continue;let K=ot(i,A);if(K.errors.length){for(let Q of K.errors){let ee=`${Q.path}\0${Q.message}`;S.has(ee)||L.errors.push(Q),S.add(ee)}continue}L.advice.push(...K.advice);let Y=new Map(G.components);v+=1,l.set(A,{components:Y,theme:G.theme,levels:I(Y),missing:l.get(A)?.missing??new Set,structure:v})}s.clear()}return L.errors.length&&h(L.errors.map(S=>st(S,o))),x(),L}let E=b=>l.get(b)??null,w=b=>i.surfaces.get(b)?.data;function M(b,u,T=""){return J(u)?ge(w(b),be(u.path,T)):u}function C(b,u,T=""){let W=E(b),L=W?.components.get(u);if(!L)return[];let{ids:S,template:A}=fe(L);if(!A)return S.filter(Q=>W.components.has(Q)).map(Q=>({id:Q,scope:T,key:`${Q}@${T}`}));if(!W.components.has(A.componentId))return[];let G=be(A.path,T),K=ge(w(b),G);if(!Array.isArray(K))return[];let Y=G==="/"?"":G;return K.slice(0,e.limits.components).map((Q,ee)=>({id:A.componentId,scope:`${Y}/${ee}`,key:`${A.componentId}@${Y}/${ee}`}))}function O(b,u,T,W=""){let L=i.surfaces.get(b);if(!L||L.deleted||!J(u))return!1;let S=be(u.path,W),A=je(L.data,S,T);if(A.error)return!1;L.data=A.root;let G=E(b);if(G?.missing.size)for(let K of[...G.missing])K.endsWith(`|${S}`)&&G.missing.delete(K);return x(),!0}function*B(b,u="root",T="",W=0){let L=E(b)?.components.get(u);if(!(!L||W>e.limits.depth)){yield{node:L,scope:T};for(let S of C(b,u,T))yield*B(b,S.id,S.scope,W+1)}}let V=b=>b==null||b===!1||typeof b=="string"&&!b.trim();function se(b,u,T=""){let W=E(b),S=W?.components.get(u)?.props.action?.event;if(!W||!D(S))return{sent:null,missing:[]};let A=D(S.context)?S.context:{},G=Object.values(A).filter(J).map(_=>be(_.path,T)),K=_=>G.some(U=>U==="/"||U===_||_.startsWith(`${U}/`)),Y=[];for(let _ of B(b)){let{props:U,definition:ae}=_.node;if(ae?.group!=="form"||M(b,U.required,_.scope)!==!0)continue;let re=J(U.value)?U.value:J(U.checked)?U.checked:null;if(!re)continue;let ue=be(re.path,_.scope);K(ue)&&V(ge(w(b),ue))&&Y.push({id:_.node.id,scope:_.scope,key:`${_.node.id}@${_.scope}`,path:ue,label:M(b,U.label,_.scope)})}if((Y.length||G.length)&&(W.missing=new Set(Y.map(_=>`${_.key}|${_.path}`))),Y.length)return x(),{sent:null,missing:Y};let Q={version:o,action:{name:S.name,surfaceId:b,sourceComponentId:u,timestamp:r().toISOString(),context:Object.fromEntries(Object.entries(A).map(([_,U])=>[_,De(M(b,U,T))??null]))}},ee=i.surfaces.get(b);return n.onAction?.(Q,ee?.sendDataModel?{dataModel:De(ee.data)}:{}),x(),{sent:Q,missing:[]}}return{rules:e,receive:N,surfaces:()=>[...l.keys()],surface:b=>l.has(b)?{id:b,theme:l.get(b).theme}:null,component:(b,u)=>E(b)?.components.get(u)??null,children:C,read:M,write:O,press:se,missing:(b,u,T="")=>{let W=E(b);if(!W?.missing.size)return!1;let L=`${u}@${T}|`;for(let S of W.missing)if(S.startsWith(L))return!0;return!1},structure:b=>E(b)?.structure??0,headingLevel:(b,u)=>E(b)?.levels.get(u)??2,configure:b=>{if(n={...n,...b},n.onError&&d.length){let u=d;d=[],n.onError(u)}},reset:()=>{i=qe(e),l.clear(),s.clear(),x()},dataModel:b=>De(w(b)),subscribe:b=>(c.add(b),()=>c.delete(b)),revision:()=>a}}var lt={info:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="M12 11v6M12 7h.01" pathLength="1"></path></svg>',success:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m7.5 12 3 3 6-6" pathLength="1"></path></svg>',warning:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m10.3 3.8-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3.2l-8-14a2 2 0 0 0-3.4 0Z" pathLength="1"></path><path d="M12 9v4M12 17h.01" pathLength="1"></path></svg>',danger:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m9 9 6 6M15 9l-6 6" pathLength="1"></path></svg>',check:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="20 6 9 17 4 12" pathLength="1"></polyline></svg>',chevron:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="6 9 12 15 18 9" pathLength="1"></polyline></svg>'};var Kt={required:"Fill in this field.",missing:e=>`Fill in ${e.join(", ")} first.`,yes:"Yes",no:"No"},X=e=>e==null?"":String(e),ct=e=>e!=null&&e!=="",pe=(e,t)=>`${e}-${Array.from(t,n=>/[A-Za-z0-9_-]/.test(n)?n:`_${n.codePointAt(0)?.toString(16)}`).join("")}`,Yt=0;function f(e,t={},...n){let i=document.createElement(e);for(let[o,r]of Object.entries(t))r==null||r===!1||i.setAttribute(o,r===!0?"":String(r));for(let o of n.flat())o!=null&&o!==!1&&i.append(o);return i}function ke(e,t){let n=document.createElement("span");n.innerHTML=lt[e];let i=n.firstElementChild;return t&&i.classList.add(t),i}function dt(e,t={}){let n=t.host??at(t.rules,{onAction:t.onAction,onError:t.onError}),i={...Kt,...t.labels},o=`ml-render-${Yt+=1}`,r=f("div",{class:"ml-render"}),l=f("p",{role:"status",class:"ml-visually-hidden"});r.append(l),e.append(r);let c=new Map,s=w=>w.mode==="system"&&t.systemMode?t.systemMode:w.mode;function a(){let w=t.surfaceId?n.surface(t.surfaceId)?[t.surfaceId]:[]:n.surfaces();for(let[C,O]of c)w.includes(C)||(O.node.remove(),c.delete(C));t.streaming?r.setAttribute("aria-busy","true"):r.removeAttribute("aria-busy");for(let C of w){let O=c.get(C);if(O&&O.structure===n.structure(C)&&O.lists.every(V=>V.count()===V.length)){for(let V of O.updaters)V();continue}let B=v(C,O);O?O.node.replaceWith(B.node):r.insertBefore(B.node,l),c.set(C,B),et(B.node),h(B.node,B.kept)}let M=l;for(let C of[...w].reverse()){let O=c.get(C).node;O.nextSibling!==M&&r.insertBefore(O,M),M=O}}function d(w){let M=w.contains(document.activeElement)?document.activeElement:null;return{focus:M?.id??null,selection:M&&"selectionStart"in M?[M.selectionStart,M.selectionEnd]:null,tabs:[...w.querySelectorAll('.ml-tabs-trigger[aria-selected="true"]')].map(C=>C.id),open:[...w.querySelectorAll('.ml-accordion-item[data-state="open"] .ml-accordion-trigger')].map(C=>C.id)}}function h(w,M){if(!M)return;for(let O of M.tabs)document.getElementById(O)?.click();for(let O of w.querySelectorAll(".ml-accordion-trigger"))M.open.includes(O.id)!==(O.getAttribute("aria-expanded")==="true")&&O.click();let C=M.focus?document.getElementById(M.focus):null;if(C&&(C.focus(),M.selection&&"setSelectionRange"in C))try{C.setSelectionRange(...M.selection)}catch{}}function v(w,M){let C=M?d(M.node):null,O=n.surface(w),B=t.theme==="inherit"?null:O.theme,V=f("div",{class:"ml-render-surface","data-surface":w,"data-theme":B?.name,"data-mode":B?s(B):null,"data-themed":B?!0:null}),se={surfaceId:w,base:`${o}-${w}`,updaters:[],lists:[]};return V.append(...N(se,{id:"root",scope:"",key:"root@"})),{node:V,structure:n.structure(w),lists:se.lists,updaters:se.updaters,kept:C}}function x(w,M,C){let O=n.component(w.surfaceId,M),B=n.children(w.surfaceId,M,C);return O&&!Array.isArray(O.props.children)&&O.props.children&&w.lists.push({length:B.length,count:()=>n.children(w.surfaceId,M,C).length}),B}function I(w,M,C){let{missing:O}=n.press(w,M,C);if(l.textContent=O.length?i.missing(O.map(V=>X(V.label))):"",!O.length)return;let B=document.getElementById(pe(`${o}-${w}`,O[0].key));(B?.matches("input, textarea, button, [tabindex]")?B:B?.querySelector("input, textarea, button, [tabindex]"))?.focus()}function N(w,M){let{surfaceId:C,updaters:O}=w,{id:B,scope:V,key:se}=M,b=n.component(C,B);if(!b)return[];let u=b.props,T=p=>n.read(C,p,V),W=(p,g)=>n.write(C,p,g,V),L=pe(w.base,se),S=p=>{p(),O.push(p)},A=(p,g)=>(S(()=>{p.textContent=X(T(g))}),p),G=()=>x(w,B,V).flatMap(p=>N(w,p)),K=u.accessibility??{},Y=p=>(S(()=>{let g=X(T(K.label)),$=X(T(K.description));g?p.setAttribute("aria-label",g):p.removeAttribute("aria-label"),$?p.setAttribute("aria-description",$):p.removeAttribute("aria-description")}),p),Q=p=>K.label===void 0?p:(p.setAttribute("role","group"),Y(p)),ee=()=>Array.isArray(T(u.options))?T(u.options).filter(p=>typeof p?.label=="string"&&typeof p?.value=="string"&&p.value):[],_=()=>{if(!J(u.options))return;let p=()=>JSON.stringify(ee());w.lists.push({length:p(),count:p})},U=()=>T(u.disabled)===!0,ae=()=>T(u.required)===!0,re=(p,g)=>{let $=f("p",{id:`${L}-error`,role:"alert",class:"ml-input-error",hidden:!0});return S(()=>{let q=n.missing(C,B,V);$.hidden=!q,$.textContent=q?i.required:"",p.toggleAttribute("data-invalid",q),q?g.setAttribute("aria-invalid","true"):g.removeAttribute("aria-invalid");let z=[ct(u.hint)?`${L}-hint`:null,q?`${L}-error`:null].filter(Boolean).join(" ");z?g.setAttribute("aria-describedby",z):g.removeAttribute("aria-describedby")}),$},ue=p=>{let g=f("label",{id:`${p}-label`,for:p,class:"ml-input-label"}),$=document.createTextNode(""),q=f("span",{"aria-hidden":"true",class:"ml-required-mark"},"*");return g.append($),S(()=>{$.textContent=X(T(u.label)),ae()?g.append(q):q.remove()}),g},Re=()=>ct(u.hint)?A(f("p",{id:`${L}-hint`,class:"ml-input-hint"}),u.hint):null,Fe=p=>(J(u.value)?(S(()=>{let g=X(T(u.value));p.value!==g&&(p.value=g)}),p.addEventListener("input",()=>W(u.value,p.value))):p.value=X(u.value),S(()=>{p.disabled=U(),p.required=ae()}),p);switch(b.type){case"Stack":return[Q(f("div",{class:"ml-stack"},G()))];case"Row":return[Q(f("div",{class:"ml-cluster"},G()))];case"Grid":return[Q(f("div",{class:"ml-grid","data-columns":u.columns},G()))];case"Heading":return[A(f(`h${u.level??2}`),u.text)];case"Text":return[A(f("p",{class:"ml-render-text"}),u.text)];case"Card":return[Q(f("div",{class:"ml-card","data-variant":u.variant??"default"},f("div",{class:"ml-card-content ml-stack"},G())))];case"Alert":{let p=u.tone??"neutral";return[f("div",{class:"ml-alert",role:p==="danger"||p==="warning"?"alert":"status","data-tone":p,"data-variant":u.variant??"card","data-state":"open"},f("span",{"aria-hidden":"true",class:"ml-alert-icon"},ke(p==="neutral"?"info":p)),f("div",{class:"ml-alert-content"},u.title!==void 0?A(f("p",{class:"ml-alert-title"}),u.title):null,A(f("div",{class:"ml-alert-description"}),u.text)))]}case"EmptyState":{let p=u.children!==void 0?G():[];return[f("section",{class:"ml-empty","data-size":u.size??"inline"},A(f(`h${n.headingLevel(C,B)}`,{class:"ml-empty-title"}),u.title),u.description!==void 0?A(f("p",{class:"ml-empty-description"}),u.description):null,p.length?f("div",{class:"ml-empty-actions"},p):null)]}case"Tabs":{let p=x(w,B,V);if(!p.length)return[];let g=f("div",{class:"ml-tabs-list",role:"tablist","aria-orientation":"horizontal"});S(()=>g.setAttribute("aria-label",X(T(u.label))));let $=[];for(let[q,z]of p.entries()){let P=pe(w.base,`${z.key}-tab`),H=pe(w.base,`${z.key}-panel`),R=q===0,F=f("button",{class:"ml-tabs-trigger",id:P,type:"button",role:"tab","aria-selected":String(R),"aria-controls":H,tabindex:R?"0":"-1","data-state":R?"active":"inactive"});S(()=>{F.textContent=X(n.read(C,n.component(C,z.id)?.props.label,z.scope))}),g.append(F),$.push(f("div",{class:"ml-tabs-content ml-stack",id:H,role:"tabpanel","aria-labelledby":P,tabindex:"0",hidden:!R,"data-state":R?"active":"inactive"},x(w,z.id,z.scope).flatMap(te=>N(w,te))))}return[f("div",{class:"ml-tabs","data-ml":"tabs","data-variant":u.variant??"default","data-orientation":"horizontal"},g,$)]}case"Accordion":{let p=n.headingLevel(C,B),g=x(w,B,V).map($=>{let q=pe(w.base,`${$.key}-trigger`),z=pe(w.base,`${$.key}-panel`),P=f("span",{class:"ml-accordion-trigger-label"});return S(()=>{P.textContent=X(n.read(C,n.component(C,$.id)?.props.title,$.scope))}),f("div",{class:"ml-accordion-item","data-state":"closed"},f(`h${p}`,{class:"ml-accordion-heading"},f("button",{class:"ml-accordion-trigger",id:q,type:"button","aria-expanded":"false","aria-controls":z,"data-state":"closed"},P,ke("chevron","ml-accordion-chevron"))),f("div",{class:"ml-accordion-panel",id:z,role:"region","aria-labelledby":q,"data-state":"closed",hidden:!0},f("div",{class:"ml-accordion-panel-inner ml-stack"},x(w,$.id,$.scope).flatMap(H=>N(w,H)))))});return[f("div",{class:"ml-accordion","data-ml":"accordion","data-ml-multiple":u.type==="multiple"?"true":null},g)]}case"Tab":case"AccordionItem":return[];case"Input":case"DatePicker":{let p=Fe(f("input",{class:"ml-input",id:L,type:b.type==="DatePicker"?"date":u.type??"text","data-variant":u.variant??"default","data-size":u.size??"md",maxlength:b.type==="Input"?n.rules.limits.textLength:null,min:u.min,max:u.max}));b.type==="DatePicker"&&J(u.value)&&p.addEventListener("change",()=>W(u.value,p.value||null)),S(()=>{let $=X(T(u.placeholder));$?p.setAttribute("placeholder",$):p.removeAttribute("placeholder")});let g=f("div",{class:"ml-input-field"});return g.append(ue(L),f("div",{class:"ml-input-control"},p),...[Re()].filter(Boolean),re(g,p)),[g]}case"Textarea":{let p=Fe(f("textarea",{class:"ml-textarea",id:L,rows:u.rows??4,maxlength:n.rules.limits.textLength}));S(()=>{let $=X(T(u.placeholder));$?p.setAttribute("placeholder",$):p.removeAttribute("placeholder")});let g=f("div",{class:"ml-input-field"});return g.append(ue(L),p,...[Re()].filter(Boolean),re(g,p)),[g]}case"Select":{let p=`${L}-label`,g=`${L}-list`,$=f("span",{class:"ml-select-value"}),q=f("button",{class:"ml-select",id:L,type:"button",role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":g,"aria-labelledby":p,"data-size":u.size??"md","data-state":"closed"},$,ke("chevron","ml-select-chevron")),z=f("ul",{class:"ml-select-list",id:g,role:"listbox","aria-labelledby":p});_();for(let[H,R]of ee().entries())z.append(f("li",{class:"ml-select-option",id:`${L}-option-${H}`,role:"option","data-value":R.value,"aria-selected":"false","data-state":"unchecked"},R.label));let P=f("div",{class:"ml-select-root","data-ml":"select"},A(f("span",{class:"ml-select-label",id:p}),u.label),f("div",{class:"ml-select-control"},q),f("div",{class:"ml-select-popover"},z));return S(()=>{let H=X(T(u.value)),R=ee().find(F=>F.value===H);$.textContent=R?R.label:X(T(u.placeholder))||"\xA0",$.toggleAttribute("data-placeholder",!R);for(let F of z.children){let te=F.dataset.value===H;F.setAttribute("aria-selected",String(te)),F.dataset.state=te?"checked":"unchecked"}q.disabled=U(),ae()?q.setAttribute("aria-required","true"):q.removeAttribute("aria-required")}),J(u.value)&&P.addEventListener("ml-change",H=>W(u.value,H.detail.value)),P.append(re(P,q)),[P]}case"RadioGroup":{let p=`${L}-label`;_();let g=ee(),$=g.map((R,F)=>f("input",{class:"ml-radio-input",id:`${L}-${F}`,type:"radio",name:L,value:R.value})),q=g.map((R,F)=>f("label",{class:"ml-radio-item",for:`${L}-${F}`,"data-state":"unchecked"},f("span",{class:"ml-radio-control"},$[F],f("span",{class:"ml-radio-indicator","aria-hidden":"true"})),f("span",{class:"ml-radio-copy"},f("span",{class:"ml-radio-label"},R.label)))),z=u.orientation??"vertical",P=f("div",{class:"ml-radio-group",id:L,role:"radiogroup","aria-labelledby":p,"aria-orientation":z,"data-orientation":z},A(f("div",{class:"ml-radio-group-label",id:p}),u.label),f("div",{class:"ml-radio-group-items"},q)),H=X(u.value);S(()=>{let R=J(u.value)?X(T(u.value)):H;for(let[F,te]of $.entries())te.checked=te.value===R,te.disabled=U(),q[F].dataset.state=te.checked?"checked":"unchecked";ae()?P.setAttribute("aria-required","true"):P.removeAttribute("aria-required")});for(let R of $)R.addEventListener("change",()=>{if(J(u.value))W(u.value,R.value);else{H=R.value;for(let F of O)F()}});return P.append(re(P,P)),[P]}case"Checkbox":{let p=f("input",{class:"ml-checkbox-input",id:L,type:"checkbox"}),g=f("span",{class:"ml-checkbox-copy"},f("label",{class:"ml-checkbox-label",for:L},A(f("span",{class:"ml-checkbox-text"}),u.label)),u.description!==void 0?A(f("span",{class:"ml-checkbox-description",id:`${L}-description`}),u.description):null),$=f("div",{class:"ml-checkbox-field","data-state":"unchecked"},f("label",{class:"ml-checkbox-control","data-hit":"expand"},p,f("span",{class:"ml-checkbox-indicator","aria-hidden":"true"},ke("check"))),g);return J(u.checked)||(p.checked=u.checked===!0),S(()=>{J(u.checked)&&(p.checked=T(u.checked)===!0),p.disabled=U(),p.required=ae(),$.dataset.state=p.checked?"checked":"unchecked"}),p.addEventListener("change",()=>{J(u.checked)&&W(u.checked,p.checked),$.dataset.state=p.checked?"checked":"unchecked"}),$.append(re($,p)),[$]}case"Switch":{let p=`${L}-label`,g=f("button",{class:"ml-toggle",id:L,type:"button",role:"switch","data-ml":"switch","aria-checked":String(J(u.checked)?T(u.checked)===!0:u.checked===!0),"aria-labelledby":p,"data-size":u.size??"md","data-hit":"expand"},f("span",{class:"ml-toggle-thumb","aria-hidden":"true"}));return g.dataset.state=g.getAttribute("aria-checked")==="true"?"checked":"unchecked",S(()=>{if(J(u.checked)){let $=T(u.checked)===!0;g.setAttribute("aria-checked",String($)),g.dataset.state=$?"checked":"unchecked"}g.disabled=U()}),J(u.checked)&&g.addEventListener("ml-change",$=>W(u.checked,$.detail.value)),[f("span",{class:"ml-switch-field"},g,A(f("span",{class:"ml-switch-label",id:p}),u.label))]}case"Slider":{let p=u.min??0,g=u.max??100,$=`${L}-label`,q=f("span",{class:"ml-slider-output"}),z=f("span",{class:"ml-slider-range","aria-hidden":"true"}),P=f("span",{class:"ml-slider-thumb",id:L,role:"slider",tabindex:"0","aria-labelledby":$,"aria-valuemin":p,"aria-valuemax":g}),H=f("div",{class:"ml-slider-field","data-ml":"slider","data-size":u.size??"md","data-ml-step":u.step??1},f("div",{class:"ml-slider-header"},A(f("span",{class:"ml-slider-label",id:$}),u.label),q),f("div",{class:"ml-slider"},f("div",{class:"ml-slider-track"},z,P))),R=typeof u.value=="number"?u.value:p;return S(()=>{let F=J(u.value)?T(u.value):R,te=typeof F=="number"&&Number.isFinite(F)?Math.min(g,Math.max(p,F)):p,We=g>p?(te-p)/(g-p)*100:0;P.setAttribute("aria-valuenow",String(te)),q.textContent=String(te),z.style.width=`${We}%`,P.style.left=`${We}%`,U()?(H.dataset.disabled="",P.setAttribute("aria-disabled","true")):(delete H.dataset.disabled,P.removeAttribute("aria-disabled"))}),H.addEventListener("ml-change",F=>{J(u.value)?W(u.value,F.detail.value):R=F.detail.value}),[H]}case"Button":{let p=A(f("span",{class:"ml-button-label"}),u.text),g=Y(f("button",{class:"ml-button",id:L,type:"button","data-variant":u.variant??"primary","data-size":u.size??"md","data-width":u.width==="full"?"full":null},p));return S(()=>{g.disabled=U()}),g.addEventListener("click",()=>I(C,B,V)),[g]}case"Badge":return[f("span",{class:"ml-badge","data-tone":u.tone??"neutral","data-variant":u.variant??"soft","data-size":u.size??"md"},A(f("span",{class:"ml-badge-label"}),u.text))];case"Progress":{let p=u.max??100,g=f("span",{class:"ml-progress-value","aria-hidden":"true"}),$=f("div",{class:"ml-progress-fill","aria-hidden":"true"}),q=f("div",{class:"ml-progress-track",role:"progressbar","aria-valuemin":"0","aria-valuemax":p},$),z=A(f("span"),u.label),P=f("div",{class:"ml-progress-label"},z,g);return S(()=>{let H=T(u.value),R=typeof H=="number"&&Number.isFinite(H)?Math.min(p,Math.max(0,H)):0,F=Math.round(R/p*100);q.setAttribute("aria-valuenow",String(R)),q.setAttribute("aria-valuetext",`${F}%`),q.setAttribute("aria-label",X(T(u.label))),$.style.width=`${F}%`,g.textContent=`${F}%`,g.hidden=T(u.showLabel)!==!0}),[f("div",{class:"ml-progress-root","data-tone":u.tone??"primary","data-size":u.size??"md","data-state":"determinate"},P,q)]}case"Avatar":{let p=f("span",{class:"ml-avatar-fallback",role:"img"}),g=u.status?f("span",{class:"ml-avatar-status",role:"status","data-status":u.status}):null;return S(()=>{let $=X(T(u.name));p.setAttribute("aria-label",$),p.textContent=$.replace(/[^\p{L}\p{N}\s]/gu,"").trim().split(/\s+/).filter(Boolean).slice(0,2).map(q=>q[0].toUpperCase()).join(""),g?.setAttribute("aria-label",`${$} is ${u.status}`)}),[f("span",{class:"ml-avatar-root","data-size":u.size??"md"},f("span",{class:"ml-avatar"},p),g)]}case"Table":{let p=Array.isArray(u.columns)?u.columns:[],g=f("tbody",{class:"ml-table-body"}),$=A(f("caption",{class:"ml-table-caption"}),u.caption),q=f("div",{class:"ml-table-container"},f("table",{class:"ml-table","data-size":u.size??"md"},$,f("thead",{class:"ml-table-header"},f("tr",{class:"ml-table-row"},p.map(z=>A(f("th",{class:"ml-table-head",scope:"col","data-align":z.align??"left"}),z.label)))),g));return S(()=>{q.setAttribute("aria-label",X(T(u.caption)));let z=T(u.rows);g.replaceChildren(...(Array.isArray(z)?z.slice(0,n.rules.limits.rows):[]).map(P=>f("tr",{class:"ml-table-row"},p.map(H=>f("td",{class:"ml-table-cell","data-align":H.align??"left"},Xt(P,H.key,i)))))),queueMicrotask(()=>{let P=q.scrollWidth>q.clientWidth+1;P?q.setAttribute("tabindex","0"):q.removeAttribute("tabindex"),q.setAttribute("role",P?"region":"presentation"),P||q.removeAttribute("role")})}),[q]}default:return[]}}let E=n.subscribe(a);return a(),{host:n,receive:(w,M={})=>(t.streaming=!!M.streaming,n.receive(w,M)),setSystemMode:w=>{if(t.systemMode=w??void 0,t.theme!=="inherit")for(let[M,C]of c){let O=n.surface(M)?.theme;O&&(C.node.dataset.mode=s(O))}},destroy:()=>{E(),r.remove()}}}function Xt(e,t,n){let i=e!==null&&typeof e=="object"&&Object.hasOwn(e,t)?e[t]:void 0;return typeof i=="boolean"?i?n.yes:n.no:typeof i=="string"||typeof i=="number"?String(i):"\u2014"}var Pe={version:"1.11.0",catalogId:"https://ui.mlola.com/a2ui/catalog/v1",title:"Mlola Render catalog",description:"Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",protocolVersions:["v0.9","v0.9.1"],themes:["graphite","atelier","machined","aerogel","nordic"],defaultTheme:"graphite",modes:["light","dark","system"],groups:{layout:"Layout",text:"Text",container:"Containers",form:"Forms",action:"Actions",data:"Data"},limits:{messages:200,surfaces:20,components:300,depth:24,idLength:128,textLength:4e3,labelLength:120,options:100,columns:12,rows:500,contextKeys:32,pathLength:512,dataBytes:262144,inputBytes:1048576},components:{Stack:{group:"layout",description:"Places its children in a column with the theme's spacing. Use it as the root of most surfaces.",mlola:{class:"ml-stack"},props:{children:{kind:"children",required:!0,description:"The components inside, top to bottom."}}},Row:{group:"layout",description:"Places its children side by side and wraps them on a narrow screen. Use it for a row of buttons or badges.",mlola:{class:"ml-cluster"},props:{children:{kind:"children",required:!0,description:"The components inside, start to end."}}},Grid:{group:"layout",description:"Places its children in equal columns that collapse to one column on a phone.",mlola:{class:"ml-grid"},props:{children:{kind:"children",required:!0,description:"The components inside, in reading order."},columns:{kind:"enum",description:"How many columns on a wide screen. Leave it out to fit as many as the width allows.",values:["1","2","3","4","6"]}}},Heading:{group:"text",description:"A heading. Levels follow the page outline: never skip a level going deeper.",mlola:{element:"h1-h6"},props:{text:{kind:"text",required:!0,description:"The heading's words.",maxLength:120},level:{kind:"integer",description:"The outline level, 1 to 6. Inside a chat a surface usually starts at 2.",minimum:1,maximum:6,default:2}}},Text:{group:"text",description:"A paragraph of plain text.",mlola:{element:"p"},props:{text:{kind:"text",required:!0,description:"The words. Line breaks are kept; markup is shown as text."}}},Card:{group:"container",description:"Groups related content on a surface of its own.",mlola:{item:"card",export:"Card"},props:{children:{kind:"children",required:!0,description:"The card's content."},variant:{kind:"enum",description:"How the card stands off the page.",values:["default","elevated","glass","specular"],default:"default"}}},Alert:{group:"container",description:"A message about the surface: a confirmation, a warning or an error. Warnings and errors interrupt a screen reader; calmer tones are announced politely.",mlola:{item:"alert",export:"Alert"},props:{title:{kind:"text",description:"A short summary, read first.",maxLength:120},text:{kind:"text",required:!0,description:"What happened and what to do about it."},tone:{kind:"enum",description:"What the message means.",values:["neutral","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"A card, or a tinted band across the surface.",values:["card","soft"],default:"card"}}},EmptyState:{group:"container",description:"Says that there is nothing here yet and what to do next.",mlola:{item:"empty-state",export:"EmptyState"},props:{title:{kind:"text",required:!0,description:"What is empty, in a few words.",maxLength:120},description:{kind:"text",description:"What to do next."},children:{kind:"children",description:"Actions, usually one or two Buttons."},size:{kind:"enum",description:"inline inside a surface, page when it fills one.",values:["inline","page"],default:"inline"}}},Tabs:{group:"container",description:"Shows one panel at a time, chosen from a row of tabs. Its children are Tab components.",accepts:["Tab"],mlola:{item:"tabs",export:"Tabs"},props:{label:{kind:"text",required:!0,description:"What the tabs choose between, for a screen reader.",maxLength:120},children:{kind:"children",required:!0,description:"The Tab components, in order.",minItems:1},variant:{kind:"enum",description:"The look of the tab row.",values:["default","pills","enclosed"],default:"default"}}},Tab:{group:"container",description:"One tab of a Tabs: its name and its panel.",parents:["Tabs"],mlola:{item:"tabs",export:"TabsTrigger"},props:{label:{kind:"text",required:!0,description:"The tab's name.",maxLength:120},children:{kind:"children",required:!0,description:"What the panel shows."}}},Accordion:{group:"container",description:"A list of sections that open and close. Its children are AccordionItem components.",accepts:["AccordionItem"],mlola:{item:"accordion",export:"Accordion"},props:{children:{kind:"children",required:!0,description:"The AccordionItem components, in order.",minItems:1},type:{kind:"enum",description:"single keeps one section open at a time; multiple lets several stay open.",values:["single","multiple"],default:"single"}}},AccordionItem:{group:"container",description:"One section of an Accordion: its title and its content.",parents:["Accordion"],mlola:{item:"accordion",export:"AccordionItem"},props:{title:{kind:"text",required:!0,description:"The section's title, which opens and closes it.",maxLength:120},children:{kind:"children",required:!0,description:"The section's content."}}},Input:{group:"form",description:"A one-line text field with its label.",mlola:{item:"input",export:"Input"},props:{label:{kind:"text",required:!0,description:"The field's name, shown above it and read by a screen reader.",maxLength:120},value:{kind:"text",description:'Bind it to the data model ({"path": "/form/email"}) so the value comes back with the action.'},type:{kind:"enum",description:"The kind of text, which picks the phone keyboard and the browser's checks.",values:["text","email","password","url","tel","search"],default:"text"},placeholder:{kind:"text",description:"An example of what to type. Never a replacement for the label.",maxLength:120},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"},variant:{kind:"enum",description:"How the field sits on its surface.",values:["default","filled","subtle"],default:"default"}}},Textarea:{group:"form",description:"A text field for several lines, with its label.",mlola:{item:"textarea",export:"Textarea"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"text",description:"Bind it to the data model so the value comes back with the action."},placeholder:{kind:"text",description:"An example of what to type. Never the only label.",maxLength:120},hint:{kind:"text",description:"A short help line under the field.",maxLength:120},rows:{kind:"integer",description:"How many lines show before it scrolls.",minimum:2,maximum:12,default:4},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Select:{group:"form",description:"Picks one value from a list that opens on demand. Use RadioGroup when there are only two to five options and room to show them.",mlola:{item:"select",export:"Select"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:1},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},placeholder:{kind:"text",description:"Shown while nothing is chosen.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},RadioGroup:{group:"form",description:"Picks one value from options that are all visible.",mlola:{item:"radio-group",export:"RadioGroup"},props:{label:{kind:"text",required:!0,description:"The question the options answer.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:2},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},orientation:{kind:"enum",description:"Options stacked or in a row.",values:["horizontal","vertical"],default:"vertical"},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Checkbox:{group:"form",description:"A yes or no choice with its label.",mlola:{item:"checkbox",export:"Checkbox"},props:{label:{kind:"text",required:!0,description:"What checking it means.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model so the choice comes back with the action."},description:{kind:"text",description:"More about the choice, under the label.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Switch:{group:"form",description:"Turns a setting on or off right away.",mlola:{item:"toggle",export:"Switch"},props:{label:{kind:"text",required:!0,description:"The setting it turns on.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Slider:{group:"form",description:"Picks a number in a range by dragging or with the arrow keys.",mlola:{item:"slider",export:"Slider"},props:{label:{kind:"text",required:!0,description:"What the number is.",maxLength:120},value:{kind:"number",description:"Bind it to the data model."},min:{kind:"number",description:"The lowest value.",literal:!0,default:0},max:{kind:"number",description:"The highest value.",literal:!0,default:100},step:{kind:"number",description:"How far one arrow press moves it.",literal:!0,default:1},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md"],default:"md"}}},DatePicker:{group:"form",description:"A date field that opens a calendar and picks one day. The reader sees the date in their own format; the value is an ISO date.",mlola:{item:"date-picker",export:"DatePicker"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"date",description:'The chosen day as an ISO date, like "2026-10-12". Bind it to the data model so it comes back with the action.'},min:{kind:"date",description:"The earliest day that can be picked.",literal:!0},max:{kind:"date",description:"The latest day that can be picked.",literal:!0},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Button:{group:"action",description:'Sends an action back to the agent. Its text says what happens ("Create workspace", not "Submit").',mlola:{item:"button",export:"Button"},props:{text:{kind:"text",required:!0,description:"What pressing it does.",maxLength:120},action:{kind:"action",required:!0,description:"The event sent when it is pressed."},variant:{kind:"enum",description:"primary for the main action of a surface, one at most.",values:["primary","secondary","subtle","danger","outline","link"],default:"primary"},size:{kind:"enum",description:"Icon-only buttons are not in the catalog: every button has words.",values:["sm","md","lg"],excluded:["icon"],default:"md"},width:{kind:"enum",description:"auto fits the words, full fills the container.",values:["auto","full"],default:"auto"},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Badge:{group:"data",description:"A short label for a status or a count.",mlola:{item:"badge",export:"Badge"},props:{text:{kind:"text",required:!0,description:"The badge's words, a few at most.",maxLength:120},tone:{kind:"enum",description:"What the status means.",values:["neutral","primary","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"How strongly the badge stands out.",values:["soft","solid","outline"],default:"soft"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Progress:{group:"data",description:"Shows how far along something is.",mlola:{item:"progress",export:"Progress"},props:{label:{kind:"text",required:!0,description:"What is in progress, for a screen reader.",maxLength:120},value:{kind:"number",description:"How far along, from 0 to max."},max:{kind:"number",description:"The value that means complete.",literal:!0,default:100},showLabel:{kind:"boolean",description:"Shows the percentage beside the bar."},tone:{kind:"enum",description:"What the progress means.",values:["primary","info","success","warning","danger"],default:"primary"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Avatar:{group:"data",description:"A person or a team shown by their initials.",mlola:{item:"avatar",export:"Avatar"},props:{name:{kind:"text",required:!0,description:"The full name: the initials come from it and a screen reader reads it.",maxLength:120},size:{kind:"enum",description:"The avatar's size.",values:["xs","sm","md","lg","xl"],default:"md"},status:{kind:"enum",description:"A presence dot, announced with the name.",values:["online","offline","away","busy"]}}},Table:{group:"data",description:"Rows of data under named columns. Cells hold text and numbers.",mlola:{item:"table",export:"Table"},props:{caption:{kind:"text",required:!0,description:"What the table shows, read first by a screen reader.",maxLength:120},columns:{kind:"columns",required:!0,description:'Each {"key", "label", "align"?}: key names the row field the column shows.',minItems:1,align:{values:["left","center","right"]}},rows:{kind:"rows",required:!0,description:"An array of objects keyed by column key, or a path to one in the data model."},size:{kind:"enum",description:"Row density.",values:["sm","md"],default:"md"}}}},aliases:{Column:"Stack",List:"Stack",TextField:"Input",CheckBox:"Checkbox",ChoicePicker:"Select",Toggle:"Switch",Label:"Text",Paragraph:"Text",Title:"Heading",Callout:"Alert",Banner:"Alert",Chip:"Badge",Tag:"Badge",ProgressBar:"Progress",DataTable:"Table",DataGrid:"Table",DateTimeInput:"DatePicker",DateInput:"DatePicker",Calendar:"DatePicker"},borrowed:{components:{Image:"Say what matters in Text, or leave the image out.",Icon:"Every control has words: put the meaning in the text, or in a Badge.",Video:"Describe it in Text, or leave it out.",AudioPlayer:"Describe it in Text, or leave it out.",Modal:"A surface shows inline, with no dialog. Put the content on the surface, or in a Tab or an AccordionItem to keep it out of the way.",Divider:"Spacing comes from Stack, and a Card or a Heading separates groups. Leave the divider out."},props:{weight:"Children share space by the theme's layout. For equal columns use a Grid.",justify:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.",align:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.","Stack.direction":"A Stack is a column. For side by side use a Row.","Text.variant":'Text is one style of paragraph. For a heading use a Heading with "level".',"Button.child":'A Button holds its words in "text", not in a child component.',"Tabs.tabs":`A Tabs' "children" are Tab components, each with a "label" and "children".`,"Checkbox.value":`A Checkbox's state is "checked": true, false or {"path": "/\u2026"}.`,"Switch.value":`A Switch's state is "checked": true, false or {"path": "/\u2026"}.`,"Input.validationRegexp":'Client-side checks are not in the Mlola catalog yet. Mark the field "required", and check the value when the action arrives.',"Select.variant":"A Select picks one value. For several choices, use a Checkbox for each.","Select.displayStyle":"A Select always opens a list. For options that are all visible use a RadioGroup.","Select.filterable":"A Select lists its options as they are. Keep to the ones that matter, at most 100.","Input.variant=longText":"For several lines use a Textarea.","Input.variant=obscured":'For a password use "type": "password".',"Input.variant=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.variant=shortText":'An Input is one line already, so leave "variant" out.',"Button.variant=default":'For a button beside the main one use "secondary".',"Button.variant=borderless":'For a quiet button use "subtle" or "link".',"DatePicker.enableDate":'A DatePicker always picks a day, so leave "enableDate" out.',"DatePicker.enableTime":"Times are not in the Mlola catalog yet: a DatePicker picks a day. Ask for the time in an Input with a hint."}},examples:[]};var Zt="2026-01-26",ze=document.documentElement,ut=document.querySelector("#status"),ve=new Map,Ne=0,we=e=>window.parent.postMessage({jsonrpc:"2.0",...e},"*"),pt=(e,t={})=>we({method:e,params:t}),mt=(e,t={})=>new Promise((n,i)=>{Ne+=1,ve.set(Ne,{resolve:n,reject:i}),we({id:Ne,method:e,params:t})}),xe=e=>{ut.textContent=e,ut.hidden=!e};function ft(e){let t=e?.theme==="dark"?"dark":e?.theme==="light"?"light":null;t&&(ze.dataset.mode=t,de.setSystemMode(t))}var de=dt(document.querySelector("#surfaces"),{rules:Pe,onAction:e=>{let{surfaceId:t,sourceComponentId:n}=e.action,o=`I pressed "${de.host.read(t,de.host.component(t,n)?.props.text)}" in the ${t} surface. A2UI action: ${JSON.stringify(e)}`;mt("ui/message",{role:"user",content:[{type:"text",text:o}]}).catch(()=>xe("The host did not take the message. Try again."))}});function ht(e,t){let n=e?.messages;if(de.host.reset(),n===void 0)return;let i=de.receive(n,{streaming:t});t||xe(i.errors.length&&!de.host.surfaces().length?"The agent's interface had errors, so it is not shown. The agent has been told what to fix.":"")}window.addEventListener("message",e=>{if(e.source!==window.parent)return;let t=e.data;if(!(!t||t.jsonrpc!=="2.0")){if(t.id!==void 0&&ve.has(t.id)&&("result"in t||"error"in t)){let{resolve:n,reject:i}=ve.get(t.id);ve.delete(t.id),"error"in t?i(t.error):n(t.result);return}switch(t.method){case"ui/notifications/tool-input-partial":ht(t.params?.arguments,!0);break;case"ui/notifications/tool-input":ht(t.params?.arguments,!1);break;case"ui/notifications/tool-cancelled":de.host.surfaces().length||xe("The agent stopped before the interface was ready.");break;case"ui/notifications/host-context-changed":ft(t.params);break;case"ui/resource-teardown":case"ping":we({id:t.id,result:{}});break;default:t.id!==void 0&&t.method&&we({id:t.id,error:{code:-32601,message:`Method not found: ${t.method}`}})}}});var Be=0;new ResizeObserver(()=>{let e=Math.ceil(ze.getBoundingClientRect().height);e!==Be&&(Be=e,pt("ui/notifications/size-changed",{width:Math.ceil(ze.getBoundingClientRect().width),height:Be}))}).observe(document.body);mt("ui/initialize",{appInfo:{name:"mlola-render",version:Pe.version},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:Zt}).then(e=>{ft(e?.hostContext),pt("ui/notifications/initialized")}).catch(e=>xe(`The host did not start this view${e?.message?`: ${e.message}`:"."}`));})();
8474
+ <script>"use strict";(()=>{function kt(e,t){let n=(String(t).split(".")[1]??"").length;return Number(e.toFixed(Math.min(n,10)))}function he(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,l=Number.isFinite(i)&&i>0?i:1,a=Number.isFinite(e)?e:o,s=Math.min(r,Math.max(o,a)),c=o+Math.round((s-o)/l)*l;return kt(Math.min(r,Math.max(o,c)),l)}function Ge(e,{min:t=0,max:n=100,step:i=1}={}){let o=Number.isFinite(t)?t:0,r=Number.isFinite(n)&&n>o?n:o+100,l=Number.isFinite(e)?Math.min(1,Math.max(0,e)):0;return he(o+l*(r-o),{min:o,max:r,step:i})}function Ue(e,{min:t=0,max:n=100}={}){let i=Number.isFinite(t)?t:0,o=Number.isFinite(n)&&n>i?n:i+100;return o===i?0:(Math.min(o,Math.max(i,e))-i)/(o-i)*100}function Je(e,t,{min:n=0,max:i=100,step:o=1}={}){let r=Number.isFinite(n)?n:0,l=Number.isFinite(i)&&i>r?i:r+100,a=Number.isFinite(o)&&o>0?o:1,s=Math.max(a,(l-r)/10),c={ArrowLeft:-a,ArrowDown:-a,ArrowRight:a,ArrowUp:a,PageDown:-s,PageUp:s};if(e==="Home")return he(r,{min:r,max:l,step:a});if(e==="End")return he(l,{min:r,max:l,step:a});let d=c[e];if(d!==void 0)return he(t+d,{min:r,max:l,step:a})}var on=Object.freeze({delay:250,slop:8});function Ve(e,t,n=6){return Math.abs(e)>=n&&Math.abs(e)>=Math.abs(t)}function Ke(e,t,n,{horizontal:i=!0,wrap:o=!0,enabled:r=()=>!0}={}){if(e<=0)return-1;let l=(h,y)=>{let g=h;for(let M=0;M<e;M+=1){if(r(g))return g;g+=y,g<0&&(g=e-1),g>=e&&(g=0)}return-1};if(n==="Home")return l(0,1);if(n==="End")return l(e-1,-1);let c=n===(i?"ArrowRight":"ArrowDown")?1:n===(i?"ArrowLeft":"ArrowUp")?-1:0;if(!c)return-1;let d=t;for(let h=0;h<e;h+=1){if(d+=c,d<0){if(!o)return-1;d=e-1}if(d>=e){if(!o)return-1;d=0}if(r(d))return d}return-1}function Ye(e,t,n){return e<=0?-1:n&&t<=0?e-1:!n&&t===e-1?0:-1}var _e={top:"bottom",bottom:"top",left:"right",right:"left"};function Ae(e,t,n,{side:i="bottom",align:o="center",offset:r=8,padding:l=8}={}){let a={top:e.y-l,bottom:n.height-(e.y+e.height)-l,left:e.x-l,right:n.width-(e.x+e.width)-l},s=g=>(g==="top"||g==="bottom"?t.height:t.width)+r,c=i;a[i]<s(i)&&a[_e[i]]>a[i]&&(c=_e[i]);let d=c==="top"||c==="bottom",h,y;return d?(y=c==="bottom"?e.y+e.height+r:e.y-t.height-r,h=o==="start"?e.x:o==="end"?e.x+e.width-t.width:e.x+e.width/2-t.width/2):(h=c==="right"?e.x+e.width+r:e.x-t.width-r,y=o==="start"?e.y:o==="end"?e.y+e.height-t.height:e.y+e.height/2-t.height/2),h=Math.min(Math.max(h,l),Math.max(l,n.width-t.width-l)),y=Math.min(Math.max(y,l),Math.max(l,n.height-t.height-l)),{x:Math.round(h),y:Math.round(y),side:c}}function Xe(e,t,n,{side:i="top",offset:o=8,padding:r=8}={}){let l=i==="left"||i==="right",a=Math.max(e.x,n.width-e.x-e.width)-r,s=l&&t.width+o>a?"top":i,c=Ae(e,t,n,{side:s,align:"center",offset:o,padding:r}),d=c.side==="top"||c.side==="bottom",h=d?e.x+e.width/2-t.width/2:e.y+e.height/2-t.height/2;return{...c,shift:Math.round((d?c.x:c.y)-h)}}var Ze=Symbol.for("mlola.scrollLock");function Qe(e=globalThis.document){if(!e?.documentElement)return()=>{};let t=e.documentElement,n=t[Ze]??(t[Ze]={count:0,saved:null});if(n.count===0){let o=e.defaultView,r=t.clientWidth;n.saved={overflow:t.style.overflow,scrollbarGutter:t.style.scrollbarGutter,paddingInlineEnd:t.style.paddingInlineEnd},t.style.scrollbarGutter="stable",t.style.overflow="hidden";let l=t.clientWidth-r,a=0;if(l>0&&o){t.style.scrollbarGutter=n.saved.scrollbarGutter;let s=Number.parseFloat(o.getComputedStyle(t).paddingInlineEnd)||0;t.style.paddingInlineEnd=`${s+l}px`,a=l}t.style.setProperty("--ml-scroll-lock-offset",`${a}px`),t.setAttribute("data-ml-scroll-locked","")}n.count+=1;let i=!1;return()=>{i||(i=!0,n.count=Math.max(0,n.count-1),!(n.count>0||!n.saved)&&(t.style.overflow=n.saved.overflow,t.style.scrollbarGutter=n.saved.scrollbarGutter,t.style.paddingInlineEnd=n.saved.paddingInlineEnd,t.style.removeProperty("--ml-scroll-lock-offset"),t.removeAttribute("data-ml-scroll-locked"),n.saved=null))}}var Se="__mlolaEnhanced",Te=(e,t)=>e.dispatchEvent(new CustomEvent("ml-change",{detail:{value:t},bubbles:!0})),wt=["a[href]","button:not([disabled])","input:not([disabled]):not([type='hidden'])","select:not([disabled])","textarea:not([disabled])","[tabindex]:not([tabindex='-1'])"].join(",");function et(e){return[...e.querySelectorAll(wt)].filter(t=>t.offsetWidth>0||t.offsetHeight>0||t===document.activeElement)}function P(e,t,n,i){return e.addEventListener(t,n,i),()=>e.removeEventListener(t,n,i)}function Le(e,t,n,i=Ae){let o=typeof e.showPopover=="function";o&&!e.hasAttribute("popover")&&e.setAttribute("popover","manual");let r=!1,l=0,a=()=>{let c=t.getBoundingClientRect(),{minWidth:d,...h}=n();d&&(e.style.minWidth=`${d}px`);let y=i({x:c.left,y:c.top,width:c.width,height:c.height},{width:e.offsetWidth,height:e.offsetHeight},{width:window.innerWidth,height:window.innerHeight},h);e.style.left=`${y.x}px`,e.style.top=`${y.y}px`,y.shift!==void 0&&e.style.setProperty("--ml-floating-shift",`${y.shift}px`),e.dataset.side=y.side},s=()=>{cancelAnimationFrame(l),l=requestAnimationFrame(()=>{r&&a()})};return{show(){r=!0,e.hidden=!1,o&&e.isConnected&&!e.matches(":popover-open")&&e.showPopover(),a()},hide(){r=!1,o&&e.matches(":popover-open")&&e.hidePopover(),e.hidden=!0},cleanups:[P(window,"scroll",s,!0),P(window,"resize",s),()=>cancelAnimationFrame(l)]}}function ke(e,t,n,i={}){return Ke(e.length,t,n,{...i,enabled:o=>!e[o].disabled&&e[o].getAttribute("aria-disabled")!=="true"})}var Me={accordion(e){let t=e.dataset.mlMultiple==="true",n=e.dataset.mlCollapsible!=="false",i=()=>[...e.querySelectorAll(".ml-accordion-item")],o=()=>[...e.querySelectorAll(".ml-accordion-trigger")],r=(a,s)=>{let c=a.querySelector(".ml-accordion-trigger"),d=a.querySelector(".ml-accordion-panel"),h=s?"open":"closed";a.dataset.state=h,c&&(c.dataset.state=h,c.setAttribute("aria-expanded",String(s))),d&&(d.dataset.state=h,d.hidden=!s)},l=a=>{let s=a.dataset.state==="open";if(!(s&&!n)){if(!t&&!s)for(let c of i())c!==a&&r(c,!1);r(a,!s)}};return[P(e,"click",a=>{let s=a.target.closest(".ml-accordion-trigger");s&&e.contains(s)&&l(s.closest(".ml-accordion-item"))}),P(e,"keydown",a=>{let s=a.target.closest(".ml-accordion-trigger");if(!s)return;let c=o(),d=c.indexOf(s),h=ke(c,d,a.key,{horizontal:!1});h>=0&&(a.preventDefault(),c[h].focus())})]},tabs(e){let t=e.dataset.orientation!=="vertical",n=()=>[...e.querySelectorAll(".ml-tabs-trigger")],i=o=>{for(let r of n()){let l=r===o;r.dataset.state=l?"active":"inactive",r.setAttribute("aria-selected",String(l)),r.tabIndex=l?0:-1;let a=document.getElementById(r.getAttribute("aria-controls")??"");a&&(a.dataset.state=l?"active":"inactive",a.hidden=!l)}};return[P(e,"click",o=>{let r=o.target.closest(".ml-tabs-trigger");r&&e.contains(r)&&!r.disabled&&i(r)}),P(e,"keydown",o=>{let r=o.target.closest(".ml-tabs-trigger");if(!r)return;let l=n(),a=ke(l,l.indexOf(r),o.key,{horizontal:t});a<0||(o.preventDefault(),l[a].focus(),i(l[a]))})]},"dropdown-menu":e=>{let t=e.querySelector(".ml-dropdown-trigger"),n=e.querySelector(".ml-dropdown-menu");if(!t||!n)return[];let i=()=>[...n.querySelectorAll(".ml-dropdown-item")].filter(s=>!s.disabled&&s.getAttribute("aria-disabled")!=="true"),o=Le(n,t,()=>({side:"bottom",align:n.dataset.align==="end"?"end":"start",offset:6})),r=s=>{if(e.dataset.state=s?"open":"closed",n.dataset.state=s?"open":"closed",s?o.show():o.hide(),t.setAttribute("aria-expanded",String(s)),!s)for(let c of i())delete c.dataset.highlighted},l=()=>e.dataset.state==="open",a=s=>{for(let c of i())delete c.dataset.highlighted;s&&(s.dataset.highlighted="",s.focus())};return r(!1),[P(t,"click",()=>{if(l()){r(!1);return}r(!0),a(i()[0])}),P(e,"keydown",s=>{let c=i();if(s.key==="Escape"){if(!l())return;s.preventDefault(),r(!1),t.focus();return}if(s.key==="Tab"){r(!1);return}if(s.key==="ArrowDown"||s.key==="ArrowUp"){if(s.preventDefault(),!l()){r(!0),a(c[s.key==="ArrowDown"?0:c.length-1]);return}let d=c.findIndex(y=>"highlighted"in y.dataset),h=ke(c,d,s.key,{horizontal:!1});h>=0&&a(c[h])}}),P(n,"pointermove",s=>{let c=s.target.closest(".ml-dropdown-item");c&&i().includes(c)&&a(c)}),P(document,"pointerdown",s=>{l()&&!e.contains(s.target)&&r(!1)}),...o.cleanups]},switch:e=>{let t=i=>{e.setAttribute("aria-checked",String(i)),e.dataset.state=i?"checked":"unchecked"},n=()=>{let i=e.getAttribute("aria-checked")!=="true";t(i),Te(e,i)};return e.hasAttribute("aria-checked")||t(!1),[P(e,"click",n),P(e,"keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),n())})]},modal(e){let t=e.dataset.mlEscape!=="false",n=e.dataset.mlOverlay!=="false",i=null,o=()=>{},r=()=>document.querySelector(`.ml-modal-overlay[data-ml-for="${e.id}"], .ml-sheet-overlay[data-ml-for="${e.id}"]`),l=()=>{e.dataset.state="closed",e.hidden=!0;let s=r();s&&(s.hidden=!0),o(),o=()=>{},i&&document.contains(i)&&i.focus()},a=s=>{i=s??document.activeElement,e.dataset.state="open",e.hidden=!1;let c=r();c&&(c.hidden=!1),o(),o=Qe(),(et(e)[0]??e).focus()};return e.mlolaDialog={open:a,close:l},[P(document,"click",s=>{let c=s.target.closest(`[data-ml-opens="${e.id}"]`);if(c){s.preventDefault(),a(c);return}let d=s.target.closest(".ml-modal-close, .ml-sheet-close, [data-ml-close]");d&&e.contains(d)&&l(),n&&s.target===r()&&l()}),P(document,"keydown",s=>{if(e.hidden)return;if(s.key==="Escape"&&t&&!s.defaultPrevented){s.preventDefault(),l();return}if(s.key!=="Tab")return;let c=et(e),d=Ye(c.length,c.indexOf(document.activeElement),s.shiftKey);d<0||(s.preventDefault(),c[d].focus())})]},select(e){let t=e.querySelector(".ml-select"),n=e.querySelector(".ml-select-popover"),i=e.querySelector(".ml-select-list");if(!t||!n||!i)return[];let o=i.getAttribute("aria-multiselectable")==="true",r=()=>[...i.querySelectorAll(".ml-select-option")].filter(h=>h.getAttribute("aria-disabled")!=="true"),l=Le(n,t,()=>({side:"bottom",align:"start",offset:6,minWidth:t.offsetWidth})),a=h=>{if(t.dataset.state=h?"open":"closed",h?l.show():l.hide(),t.setAttribute("aria-expanded",String(h)),!h){for(let y of r())delete y.dataset.highlighted;t.removeAttribute("aria-activedescendant")}},s=()=>t.dataset.state==="open",c=h=>{for(let y of r())delete y.dataset.highlighted;h&&(h.dataset.highlighted="",h.id&&t.setAttribute("aria-activedescendant",h.id))},d=h=>{if(!h)return;let y=h.getAttribute("aria-selected")==="true";if(!o)for(let C of r())C.setAttribute("aria-selected","false"),C.dataset.state="unchecked";let g=o?!y:!0;h.setAttribute("aria-selected",String(g)),h.dataset.state=g?"checked":"unchecked";let M=e.querySelector(".ml-select-value"),q=C=>C.dataset.value??C.textContent.trim();M&&!o&&(M.textContent=h.textContent.trim(),delete M.dataset.placeholder),Te(e,o?r().filter(C=>C.dataset.state==="checked").map(q):q(h)),o||(a(!1),t.focus())};return a(!1),[P(t,"click",()=>a(!s())),P(i,"click",h=>d(h.target.closest(".ml-select-option"))),P(i,"pointermove",h=>{let y=h.target.closest(".ml-select-option");y&&r().includes(y)&&c(y)}),P(e,"keydown",h=>{let y=r();if(h.key==="Escape"){if(!s())return;h.preventDefault(),a(!1),t.focus();return}if(h.key==="Tab"){a(!1);return}if(h.key==="ArrowDown"||h.key==="ArrowUp"){if(h.preventDefault(),!s()){a(!0),c(y[h.key==="ArrowDown"?0:y.length-1]);return}let g=y.findIndex(q=>"highlighted"in q.dataset),M=ke(y,g,h.key,{horizontal:!1});M>=0&&c(y[M]);return}if(h.key==="Home"||h.key==="End"){if(!s())return;h.preventDefault(),c(h.key==="Home"?y[0]:y[y.length-1]);return}if(h.key==="Enter"||h.key===" "&&h.target!==e.querySelector(".ml-select-search")){if(h.preventDefault(),!s()){a(!0);return}d(y.find(g=>"highlighted"in g.dataset))}}),P(document,"pointerdown",h=>{s()&&!e.contains(h.target)&&a(!1)}),...l.cleanups]},slider(e){let t=e.querySelector(".ml-slider-track"),n=e.querySelector(".ml-slider-range"),i=e.querySelector(".ml-slider-thumb"),o=e.querySelector('[role="slider"]');if(!t||!o)return[];let r=()=>({min:Number(o.getAttribute("aria-valuemin")??0),max:Number(o.getAttribute("aria-valuemax")??100),step:Number(e.dataset.mlStep??1)}),l=e.dataset.disabled!==void 0||o.getAttribute("aria-disabled")==="true",a=e.querySelector(".ml-slider-output"),s=()=>Number(o.getAttribute("aria-valuenow")??r().min),c=g=>{let M=r(),q=he(g,M);o.setAttribute("aria-valuenow",String(q));let C=Ue(q,M);n&&(n.style.width=`${C}%`),i&&(i.style.left=`${C}%`),a&&(a.textContent=String(q)),Te(e,q)},d=g=>{let M=t.getBoundingClientRect();return M.width?Ge((g.clientX-M.left)/M.width,r()):s()},h=e.querySelector(".ml-slider")??t,y=null;return[P(h,"pointerdown",g=>{if(l||g.button!==0)return;let M=g.pointerType==="touch";y={id:g.pointerId,touch:M,x:g.clientX,y:g.clientY,active:!M},M||(h.setPointerCapture?.(g.pointerId),c(d(g))),o.focus()}),P(h,"pointermove",g=>{if(!(l||!y||y.id!==g.pointerId)){if(!y.active){if(!Ve(g.clientX-y.x,g.clientY-y.y))return;y.active=!0,h.setPointerCapture?.(g.pointerId)}c(d(g))}}),P(h,"pointerup",g=>{let M=y;y=null,h.releasePointerCapture?.(g.pointerId),!l&&M?.touch&&!M.active&&c(d(g))}),P(h,"pointercancel",()=>{y=null}),P(o,"keydown",g=>{if(l)return;let M=Je(g.key,s(),r());M!==void 0&&(g.preventDefault(),c(M))})]},tooltip(e){let t=e.querySelector(".ml-tooltip"),n=e.firstElementChild;if(!t||!n)return[];let i=Number(e.dataset.mlDelay??200),o=t.dataset.side||"top",r=Le(t,n,()=>({side:o}),Xe),l=null,a=()=>{clearTimeout(l),l=setTimeout(()=>{t.dataset.state="open",r.show(),t.id&&n.setAttribute("aria-describedby",t.id)},Math.max(0,i))},s=()=>{clearTimeout(l),r.hide(),delete t.dataset.state,n.removeAttribute("aria-describedby")};return s(),[...r.cleanups,P(e,"pointerenter",a),P(e,"pointerleave",s),P(e,"focusin",a),P(e,"focusout",s),P(document,"keydown",c=>{c.key!=="Escape"||t.hidden||c.defaultPrevented||(c.preventDefault(),s())},!0)]},toast(e){let t=new Map,n=s=>Number(s.dataset.mlDuration??e.dataset.mlDuration??5e3),i=s=>{let c=t.get(s);c&&clearTimeout(c),t.delete(s),s.remove(),e.querySelector(".ml-toast")||e.dispatchEvent(new CustomEvent("ml-empty",{bubbles:!0}))},o=s=>{if("mlPaused"in s.dataset)return;let c=n(s),d=t.get(s);d&&clearTimeout(d),c>0&&t.set(s,setTimeout(()=>i(s),c))},r=s=>{s.dataset.mlEnhanced===void 0&&(s.dataset.mlEnhanced="",o(s))},l=()=>[...e.querySelectorAll(".ml-toast")];e.hasAttribute("role")||e.setAttribute("role","region"),e.showPopover&&(e.popover="manual",e.showPopover());for(let s of l())r(s);let a=new MutationObserver(s=>{for(let c of s)for(let d of c.addedNodes){if(d.nodeType!==1)continue;let h=d.matches?.(".ml-toast")?[d,...d.querySelectorAll(".ml-toast")]:[...d.querySelectorAll(".ml-toast")];for(let y of h)r(y)}});return a.observe(e,{childList:!0,subtree:!0}),[P(e,"click",s=>{let c=s.target.closest(".ml-toast");!c||!e.contains(c)||s.target.closest(".ml-toast-close")&&(s.preventDefault(),i(c))}),P(e,"pointerenter",s=>{let c=s.target.closest(".ml-toast");c&&(c.dataset.mlPaused="",o(c))},!0),P(e,"pointerleave",s=>{let c=s.target.closest(".ml-toast");c&&(delete c.dataset.mlPaused,o(c))},!0),P(e,"focusin",s=>{let c=s.target.closest(".ml-toast");c&&(c.dataset.mlPaused="",o(c))}),P(e,"focusout",s=>{let c=s.target.closest(".ml-toast");c&&(delete c.dataset.mlPaused,o(c))}),()=>{a.disconnect();for(let s of t.values())clearTimeout(s)}]}};Me.sheet=Me.modal;function tt(e=document){let t=[...e.matches?.("[data-ml]")?[e]:[],...e.querySelectorAll("[data-ml]")],n=0;for(let i of t){if(i[Se])continue;let o=Me[i.dataset.ml];if(!o)continue;let r=o(i)??[];i[Se]=()=>{for(let l of r)l();delete i[Se]},n+=1}return n}var pe=["createSurface","updateComponents","updateDataModel","deleteSurface"],vt=new Set(["id","component","accessibility"]),$t=new Set(["style","className","class","css","color","background","backgroundColor","theme","sx","tw"]),ge=new Set(["__proto__","prototype","constructor"]),xt=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/,Ie=/^[A-Za-z0-9_-]{1,64}$/,At=/^(\d{4})-(\d{2})-(\d{2})$/,se=e=>{let t=typeof e=="string"?At.exec(e):null;if(!t)return!1;let[n,i,o]=t.slice(1).map(Number),r=new Date(Date.UTC(n,i-1,o));return r.getUTCFullYear()===n&&r.getUTCMonth()===i-1&&r.getUTCDate()===o};var D=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),re=(e,t)=>Object.hasOwn(e,t)?e[t]:void 0,X=e=>e===null?"null":Array.isArray(e)?"an array":typeof e=="object"?"an object":`a ${typeof e}`,b=e=>e!==null&&typeof e=="object"?X(e):typeof e=="string"&&e.length>80?JSON.stringify(`${e.slice(0,77)}\u2026`):String(JSON.stringify(e)),St=e=>String(e).replaceAll("~","~0").replaceAll("/","~1"),w=(e,...t)=>t.reduce((n,i)=>`${n}/${St(i)}`,e),ne=e=>e.map(t=>b(t)).join(", "),nt=e=>e.endsWith("s")?`${e}'`:`${e}'s`,rt=e=>e.endsWith("s")?e:`${e}s`,Tt=e=>({...e.align?{align:e.align}:{},...e.fields});function ot(e,t){if(typeof e!="string")return{messages:e,error:null};if(t&&e.length>t.inputBytes)return{messages:null,error:`The input is ${e.length} characters; at most ${t.inputBytes} are checked at a time. Send fewer messages per call.`};let n=e.trim();if(!n)return{messages:null,error:"The input is empty. Pass A2UI messages: one object, an array, or one object per line."};try{return{messages:JSON.parse(n),error:null}}catch(i){let o=n.split(`
8475
+ `).map(r=>r.trim()).filter(Boolean);if(o.length>1){let r=[];for(let[l,a]of o.entries())try{r.push(JSON.parse(a))}catch(s){return{messages:null,error:`Line ${l+1} is not JSON: ${s.message}`}}return{messages:r,error:null}}return{messages:null,error:`The input is not JSON: ${i.message}`}}}function Oe(e){return{rules:e,surfaces:new Map}}function it(e,t){let n={errors:[],advice:[]},i=D(t),o=i?[t]:t;if(!Array.isArray(o))return n.errors.push(p("","",`Expected A2UI messages: an object with "version" and one of ${pe.join(", ")}, or an array of them. Got ${X(t)}.`)),n;let{limits:r}=e.rules;if(o.length||n.errors.push(p("","","There are no messages. Start with createSurface, then updateComponents.")),o.length>r.messages)return n.errors.push(p("","",`At most ${r.messages} messages are checked at a time; this is ${o.length}. Check the rest in another call.`)),n;for(let[l,a]of o.entries())Lt(e,a,i?"":`/${l}`,n);return n}function st(e,t){let n={errors:[],advice:[]},i=e.surfaces.get(t);if(!i||i.deleted)return n;n.errors.push(...i.problems);for(let o of i.components.values())at(e.rules,i.id,o.props,o.at,n);return i.components.size&&Vt(e.rules,i,n),n}function p(e,t,n){return{code:"VALIDATION_FAILED",surfaceId:e??"",path:t,message:n}}function Ce(e,t,n){return{code:"ADVICE",surfaceId:e??"",path:t,message:n}}function Lt(e,t,n,i){let{rules:o}=e;if(!D(t)){i.errors.push(p("",n,`A message is an object with "version" and one of ${pe.join(", ")}; this one is ${X(t)}.`));return}let r=pe.filter(h=>h in t),l=r.length===1&&D(t[r[0]])&&typeof t[r[0]].surfaceId=="string"?t[r[0]].surfaceId:"";if(o.protocolVersions.includes(t.version)||i.errors.push(p(l,w(n,"version"),t.version===void 0?`Add "version": ${b(o.protocolVersions.at(-1))} to every message.`:`Version ${b(t.version)} is not supported; use ${ne(o.protocolVersions)}.`)),r.length!==1){i.errors.push(p(l,n,r.length?`A message carries one of ${pe.join(", ")}; this one has ${r.join(" and ")}. Send them as separate messages.`:`A message carries one of ${pe.join(", ")}; this one has none.`));return}for(let h of Object.keys(t))h!=="version"&&h!==r[0]&&i.errors.push(p(l,w(n,h),`A message holds only "version" and ${b(r[0])}; remove ${b(h)}.`));let a=r[0],s=t[a],c=w(n,a);if(!D(s)){i.errors.push(p("",c,`${a} is an object; got ${X(s)}.`));return}let d=s.surfaceId;if(typeof d!="string"||!d.trim()||d.length>o.limits.idLength){i.errors.push(p("",w(c,"surfaceId"),`${a} needs a "surfaceId": a string of 1 to ${o.limits.idLength} characters that names the surface.`));return}if(a==="createSurface")Mt(e,s,c,i);else{let h=e.surfaces.get(d);if(!h||h.deleted){i.errors.push(p(d,w(c,"surfaceId"),h?.deleted?`Surface ${b(d)} was deleted; send createSurface again before ${a}.`:`No surface is called ${b(d)}. Send createSurface for it first, in the same messages.`));return}a==="updateComponents"?It(o,h,s,c,i):a==="updateDataModel"?Ot(o,h,s,c,i):Ct(e,h,s,c,i)}}function oe(e,t,n,i,o,r){for(let l of Object.keys(e))t.includes(l)||o.errors.push(p(i,w(n,l),`${r} does not take ${b(l)}. It takes ${ne(t)}.`))}function Mt(e,t,n,i){let{rules:o}=e,{surfaceId:r}=t,l=i.errors.length;oe(t,["surfaceId","catalogId","theme","sendDataModel"],n,r,i,"createSurface"),t.catalogId!==o.catalogId&&i.errors.push(p(r,w(n,"catalogId"),`Set "catalogId" to ${b(o.catalogId)}: this renderer draws the Mlola catalog${typeof t.catalogId=="string"?`, not ${b(t.catalogId)}`:""}.`)),t.sendDataModel!==void 0&&typeof t.sendDataModel!="boolean"&&i.errors.push(p(r,w(n,"sendDataModel"),'"sendDataModel" is true or false.'));let a={name:o.defaultTheme,mode:"system"};if(t.theme!==void 0){let d=w(n,"theme");if(!D(t.theme))i.errors.push(p(r,d,`"theme" is an object like {"name": ${b(o.defaultTheme)}, "mode": "system"}.`));else{for(let h of Object.keys(t.theme))h==="name"||h==="mode"||i.errors.push(p(r,w(d,h),/color|font|radius|spacing|icon/i.test(h)?`Colors, type and shape come from the theme; pick one by name instead of setting ${b(h)}: ${ne(o.themes)}.`:`"theme" takes "name" and "mode"; remove ${b(h)}.`));t.theme.name!==void 0&&(o.themes.includes(t.theme.name)?a.name=t.theme.name:i.errors.push(p(r,w(d,"name"),`Theme ${b(t.theme.name)} does not exist; use ${ne(o.themes)}.`))),t.theme.mode!==void 0&&(o.modes.includes(t.theme.mode)?a.mode=t.theme.mode:i.errors.push(p(r,w(d,"mode"),`Mode ${b(t.theme.mode)} does not exist; use ${ne(o.modes)} (system follows the reader's setting).`)))}}let s=e.surfaces.get(r);if(s&&!s.deleted){i.errors.push(p(r,w(n,"surfaceId"),`Surface ${b(r)} already exists. Use another surfaceId, or send deleteSurface first.`));return}let c=0;for(let d of e.surfaces.values())d.deleted||(c+=1);if(c>=o.limits.surfaces){i.errors.push(p(r,n,`At most ${o.limits.surfaces} surfaces are open at once; send deleteSurface for one that is done.`));return}e.surfaces.delete(r),e.surfaces.set(r,{id:r,theme:a,sendDataModel:t.sendDataModel===!0,deleted:!1,components:new Map,data:{},dataBytes:0,at:n,problems:i.errors.slice(l)})}function Ct(e,t,n,i,o){oe(n,["surfaceId"],i,t.id,o,"deleteSurface"),t.deleted=!0,t.components=new Map,t.data={},t.dataBytes=0;let r=[...e.surfaces.values()].filter(l=>l.deleted);for(let l of r.slice(0,Math.max(0,r.length-e.rules.limits.surfaces)))e.surfaces.delete(l.id)}function It(e,t,n,i,o){oe(n,["surfaceId","components"],i,t.id,o,"updateComponents");let r=w(i,"components");if(!Array.isArray(n.components)||!n.components.length){o.errors.push(p(t.id,r,'"components" is a non-empty array of components, each with an "id" and a "component".'));return}if(n.components.length>e.limits.components){o.errors.push(p(t.id,r,`This message sends ${n.components.length} components; a surface holds at most ${e.limits.components}. Split it into more surfaces.`));return}let l=new Set;for(let[a,s]of n.components.entries()){let c=w(r,a);if(!D(s)){o.errors.push(p(t.id,c,`A component is an object with "id" and "component"; got ${X(s)}.`));continue}let{id:d}=s;if(typeof d!="string"||!d.trim()||d.length>e.limits.idLength){o.errors.push(p(t.id,w(c,"id"),`Every component needs an "id": a string of 1 to ${e.limits.idLength} characters, unique on the surface.`));continue}if(l.has(d)){o.errors.push(p(t.id,w(c,"id"),`Two components in this message have the id ${b(d)}; give each its own.`));continue}if(l.add(d),!t.components.has(d)&&t.components.size>=e.limits.components){o.errors.push(p(t.id,c,`A surface holds at most ${e.limits.components} components; split it into more surfaces.`));break}let h=at(e,t.id,s,c,o);t.components.set(d,{id:d,type:s.component,props:s,definition:h,at:c})}}function Ot(e,t,n,i,o){oe(n,["surfaceId","path","value"],i,t.id,o,"updateDataModel");let r=n.path??"/",l=w(i,"path");if(typeof r!="string"||r!==""&&!qe(r,{absolute:!0,rules:e})){o.errors.push(p(t.id,l,'"path" is a JSON Pointer like "/form/email", or "/" for the whole data model.'));return}let a=0,s;try{let d=n.value===void 0?void 0:JSON.stringify(n.value);s=d===void 0?void 0:JSON.parse(d),a=t.dataBytes-jt(be(t.data,r))+(d?.length??0)}catch{o.errors.push(p(t.id,w(i,"value"),"This value is nested too deeply to read; flatten it."));return}if(a>e.limits.dataBytes){o.errors.push(p(t.id,w(i,"value"),`A surface's data model holds at most ${e.limits.dataBytes} bytes of JSON; send less, or page through it.`));return}let c=De(t.data,r,s);if(c.error){o.errors.push(p(t.id,l,c.error));return}t.data=c.root,t.dataBytes=a}var jt=e=>e===void 0?0:JSON.stringify(e)?.length??0;function at(e,t,n,i,o){let r=n.component,l=w(i,"component");if(typeof r!="string"||!r)return o.errors.push(p(t,l,'Every component names its type in "component", for example "Stack", "Text" or "Button".')),null;let a=re(e.components,r);if(!a)return o.errors.push(p(t,l,Et(e,r))),null;for(let[s,c]of Object.entries(n)){if(vt.has(s))continue;let d=re(a.props,s),h=w(i,s);if(!d){o.errors.push(p(t,h,Pt(e,r,a,s)));continue}Bt(e,t,r,s,d,c,h,o)}for(let[s,c]of Object.entries(a.props))c.required&&n[s]===void 0&&o.errors.push(p(t,i,`${r} needs ${b(s)}${c.description?`: ${qt(c.description)}`:"."}`));return n.accessibility!==void 0&&Nt(e,t,n.accessibility,w(i,"accessibility"),o),Jt(e,t,r,a,n,i,o),a}var qt=e=>e.charAt(0).toLowerCase()+e.slice(1);function Et(e,t){let n=re(e.aliases,t)??Object.keys(e.components).find(o=>o.toLowerCase()===t.toLowerCase());if(n)return`${b(t)} is not in the Mlola catalog; use ${b(n)}.`;let i=re(e.borrowed.components,t);return i?`${b(t)} is not in the Mlola catalog. ${i}`:`${b(t)} is not in the Mlola catalog. It has: ${Dt(e).map(([o,r])=>`${o} (${r.join(", ")})`).join("; ")}.`}function Dt(e){return Object.entries(e.groups).map(([t,n])=>[n,Object.keys(e.components).filter(i=>e.components[i].group===t)])}function Pt(e,t,n,i){let o=Object.keys(n.props),r=re(e.borrowed.props,`${t}.${i}`)??re(e.borrowed.props,i);return r?`${t} does not take ${b(i)}. ${r}`:$t.has(i)?`${t} takes no ${b(i)}: Mlola Render draws with the surface's theme. Choose a named value instead (${o.filter(l=>n.props[l].kind==="enum").join(", ")||"none on this component"}).`:i==="child"&&o.includes("children")?`${t} takes "children", an array of ids, not "child".`:i==="checks"?'Client-side checks are not in the Mlola catalog yet; use "required" on the field, and check the values when the action arrives.':/^on[A-Z]/.test(i)?`${t} does not take ${b(i)}. A Button's "action" sends an event to the agent; inputs bind their value with {"path": \u2026}.`:`${t} does not take ${b(i)}. It takes: ${o.join(", ")}.`}function Nt(e,t,n,i,o){if(!D(n)){o.errors.push(p(t,i,'"accessibility" is an object with "label" and "description".'));return}for(let[r,l]of Object.entries(n)){if(r!=="label"&&r!=="description"){o.errors.push(p(t,w(i,r),`"accessibility" takes "label" and "description"; remove ${b(r)}.`));continue}je(e,t,l,w(i,r),{maxLength:e.limits.labelLength},!1,o)}}function Bt(e,t,n,i,o,r,l,a){switch(o.kind){case"text":return je(e,t,r,l,o,o.required,a,`${n} ${b(i)}`);case"boolean":return typeof r=="boolean"||!o.literal&&ae(e,t,r,l,a)?void 0:a.errors.push(p(t,l,`${n} ${b(i)} is true or false${o.literal?"":', or {"path": "/\u2026"}'}; got ${X(r)}.`));case"number":return typeof r=="number"&&Number.isFinite(r)||!o.literal&&ae(e,t,r,l,a)?void 0:a.errors.push(p(t,l,`${n} ${b(i)} is a number${o.literal?"":' or {"path": "/\u2026"}'}; got ${X(r)}.`));case"integer":return Number.isInteger(r)&&r>=o.minimum&&r<=o.maximum?void 0:a.errors.push(p(t,l,`${n} ${b(i)} is a whole number from ${o.minimum} to ${o.maximum}; got ${b(r)}.`));case"date":return se(r)||!o.literal&&ae(e,t,r,l,a)?void 0:a.errors.push(p(t,l,`${n} ${b(i)} is a day written as an ISO date, like "2026-10-12"${o.literal?"":', or {"path": "/\u2026"}'}; got ${b(r)}.`));case"enum":return typeof r=="string"&&o.values.includes(r)?void 0:a.errors.push(p(t,l,zt(e,n,i,o,r)));case"children":return Rt(e,t,n,i,o,r,l,a);case"action":return Ft(e,t,r,l,a);case"options":return Wt(e,t,n,o,r,l,a);case"columns":return Ht(e,t,n,i,o,r,l,a);case"rows":return _t(e,t,i,o,r,l,a);case"key":return typeof r=="string"&&Ie.test(r)&&!ge.has(r)?void 0:a.errors.push(p(t,l,`${n} ${b(i)} names a field of each row: letters, digits, _ or -, like "month"; got ${b(r)}.`));case"numbers":return Gt(e,t,n,i,o,r,l,a);default:return a.errors.push(p(t,l,`${n} ${b(i)} has a kind this validator does not know (${o.kind}).`))}}function zt(e,t,n,i,o){if(typeof o=="string"){let r=i.values.find(a=>a.toLowerCase()===o.toLowerCase());if(r)return`${t} ${b(n)} is ${b(r)}, not ${b(o)}: values are case-sensitive.`;let l=re(e.borrowed.props,`${t}.${n}=${o}`);if(l)return`${t} ${b(n)} ${b(o)} is not in the catalog. ${l}`;if(i.excluded?.includes(o))return`${t} ${b(n)} ${b(o)} is not in the catalog: ${i.description??"it needs content the catalog does not offer."} Use ${ne(i.values)}.`}return`${t} ${b(n)} ${typeof o=="string"?`${b(o)} does not exist`:`is a name, not ${X(o)}`}; use ${ne(i.values)}.`}function je(e,t,n,i,o,r,l,a="This text"){if(typeof n=="string"){let s=o.maxLength??e.limits.textLength;n.length>s?l.errors.push(p(t,i,`${a} is ${n.length} characters; keep it to ${s}.`)):r&&!n.trim()&&l.errors.push(p(t,i,`${a} is empty. It is what a person sees and a screen reader reads; write the words.`));return}if(!ae(e,t,n,i,l)){if(D(n)&&"call"in n){l.errors.push(p(t,i,'Functions are not in the Mlola catalog yet; use a literal string or {"path": "/\u2026"}.'));return}l.errors.push(p(t,i,`${a} is a string or {"path": "/\u2026"}; got ${X(n)}.`))}}function ae(e,t,n,i,o){if(!D(n)||!("path"in n))return!1;let r=Object.keys(n).filter(l=>l!=="path");return r.length&&o.errors.push(p(t,i,`A binding holds only "path"; remove ${ne(r)}.`)),(typeof n.path!="string"||!qe(n.path,{rules:e}))&&o.errors.push(p(t,w(i,"path"),`${b(n.path)} is not a data path. Write a JSON Pointer like "/form/email" (or "name" inside a template), at most ${e.limits.pathLength} characters.`)),!0}function qe(e,{absolute:t=!1,rules:n}){if(!e||e.length>n.limits.pathLength)return!1;if(t&&e==="/")return!0;if(t&&!e.startsWith("/"))return!1;let i=(e.startsWith("/")?e.slice(1):e).split("/");for(let o of i)if(/~(?![01])/.test(o)||ge.has(Ee(o)))return!1;return!0}var Ee=e=>e.replaceAll("~1","/").replaceAll("~0","~");function Rt(e,t,n,i,o,r,l,a){if(Array.isArray(r)){r.length<(o.minItems??0)&&a.errors.push(p(t,l,`${n} needs at least ${o.minItems} ${o.minItems===1?"child":"children"}.`)),r.length>e.limits.components&&a.errors.push(p(t,l,`${n} lists ${r.length} children; a surface holds at most ${e.limits.components} components.`));let s=new Set;for(let[c,d]of r.entries())typeof d!="string"||!d?a.errors.push(p(t,w(l,c),`A child is a component id (a string); got ${X(d)}.`)):s.has(d)?a.errors.push(p(t,w(l,c),`${b(d)} is listed twice in ${n}'s children; a component appears in one place.`)):s.add(d);return}if(D(r)&&("componentId"in r||"path"in r)){oe(r,["componentId","path"],l,t,a,"A template"),(typeof r.componentId!="string"||!r.componentId)&&a.errors.push(p(t,w(l,"componentId"),'A template names the component to repeat in "componentId".')),(typeof r.path!="string"||!qe(r.path,{rules:e}))&&a.errors.push(p(t,w(l,"path"),`A template's "path" points at an array in the data model, like "/items".`));return}a.errors.push(p(t,l,`${n} ${b(i)} is an array of component ids, or a template {"componentId", "path"}; got ${X(r)}.`))}function Ft(e,t,n,i,o){if(!D(n)){o.errors.push(p(t,i,`"action" is {"event": {"name": "\u2026", "context": {\u2026}}}; got ${X(n)}.`));return}if("functionCall"in n){o.errors.push(p(t,w(i,"functionCall"),'Client-side functions are not in the Mlola catalog yet; send an event and handle it in the agent: {"event": {"name": "\u2026"}}.'));return}oe(n,["event"],i,t,o,"An action");let r=n.event,l=w(i,"event");if(!D(r)){o.errors.push(p(t,l,'An action sends an event: {"name": "\u2026", "context": {\u2026}}.'));return}if(oe(r,["name","context"],l,t,o,"An event"),(typeof r.name!="string"||!xt.test(r.name))&&o.errors.push(p(t,w(l,"name"),`An event's "name" starts with a letter and uses letters, digits, _ . : or - (at most 64), like "create_workspace".`)),r.context===void 0)return;let a=w(l,"context");if(!D(r.context)){o.errors.push(p(t,a,`An event's "context" is an object of values or {"path": \u2026} bindings.`));return}let s=Object.keys(r.context);s.length>e.limits.contextKeys&&o.errors.push(p(t,a,`An event's context holds at most ${e.limits.contextKeys} values; bind a whole object with {"path": "/form"} instead.`));for(let c of s.slice(0,e.limits.contextKeys)){let d=r.context[c],h=w(a,c);ge.has(c)?o.errors.push(p(t,h,`${b(c)} cannot be a context key.`)):D(d)&&!ae(e,t,d,h,o)?o.errors.push(p(t,h,'A context value is a string, number, boolean, array or {"path": \u2026}; an object needs a binding.')):Array.isArray(d)&&d.some(y=>y!==null&&typeof y=="object")?o.errors.push(p(t,h,'An array in the context holds strings, numbers and true or false; for a list from the data model use {"path": "/\u2026"}.')):typeof d=="string"&&d.length>e.limits.textLength&&o.errors.push(p(t,h,`This value is ${d.length} characters; keep it to ${e.limits.textLength}.`))}}function Wt(e,t,n,i,o,r,l){if(ae(e,t,o,r,l))return;if(!Array.isArray(o)){l.errors.push(p(t,r,`${n} "options" is an array of {"label", "value"}, or {"path": "/\u2026"}; got ${X(o)}.`));return}if(o.length<(i.minItems??1)&&l.errors.push(p(t,r,`${n} needs at least ${i.minItems} options${n==="RadioGroup"?"; for one yes or no choice use a Checkbox":""}.`)),o.length>e.limits.options){l.errors.push(p(t,r,`${n} lists ${o.length} options; keep it to ${e.limits.options}.`));return}let a=new Set;for(let[s,c]of o.entries()){let d=w(r,s);if(!D(c)){l.errors.push(p(t,d,`An option is {"label": "\u2026", "value": "\u2026"}; got ${X(c)}.`));continue}oe(c,["label","value"],d,t,l,"An option"),(typeof c.label!="string"||!c.label.trim()||c.label.length>e.limits.labelLength)&&l.errors.push(p(t,w(d,"label"),`An option's "label" is the words a person picks, 1 to ${e.limits.labelLength} characters.`)),typeof c.value!="string"||!c.value||c.value.length>e.limits.labelLength?l.errors.push(p(t,w(d,"value"),`An option's "value" is the string sent back, 1 to ${e.limits.labelLength} characters.`)):a.has(c.value)?l.errors.push(p(t,w(d,"value"),`Two options have the value ${b(c.value)}; give each its own.`)):a.add(c.value)}}function Ht(e,t,n,i,o,r,l,a){let s=o.item??"column",c=Tt(o);if(!Array.isArray(r)||r.length<(o.minItems??1)){a.errors.push(p(t,l,`${b(i)} is a non-empty array of {"key", "label"${Object.keys(c).map(y=>`, ${b(y)}?`).join("")}}.`));return}let d=o.maxItems??e.limits.columns;if(r.length>d){a.errors.push(p(t,l,o.maxItems?`${n} takes at most ${d} ${rt(s)}; this is ${r.length}.`:`A table shows at most ${d} columns; more cannot be read on a phone.`));return}let h=new Set;for(let[y,g]of r.entries()){let M=w(l,y);if(!D(g)){a.errors.push(p(t,M,`A ${s} is {"key": "\u2026", "label": "\u2026"}; got ${X(g)}.`));continue}oe(g,["key","label",...Object.keys(c)],M,t,a,`A ${s}`),typeof g.key!="string"||!Ie.test(g.key)||ge.has(g.key)?a.errors.push(p(t,w(M,"key"),`A ${nt(s)} "key" names the row field it shows: letters, digits, _ or -, like "order".`)):h.has(g.key)?a.errors.push(p(t,w(M,"key"),`Two ${rt(s)} have the key ${b(g.key)}.`)):h.add(g.key),je(e,t,g.label,w(M,"label"),{maxLength:e.limits.labelLength},!0,a,`The ${nt(s)} "label"`);for(let[q,C]of Object.entries(c)){let k=g[q];k===void 0||(C.values?C.values.includes(k):typeof k=="boolean")||a.errors.push(p(t,w(M,q),C.values?`${b(q)} is ${ne(C.values)}.`:`${b(q)} is true or false.`))}}}function _t(e,t,n,i,o,r,l){if(ae(e,t,o,r,l))return;if(!Array.isArray(o)){l.errors.push(p(t,r,`${b(n)} is an array of objects, or {"path": "/\u2026"} to one in the data model; got ${X(o)}.`));return}if(o.length<(i.minItems??0)){l.errors.push(p(t,r,`${b(n)} needs at least ${i.minItems} ${i.minItems===1?"row":"rows"}.`));return}let a=Math.min(i.maxItems??e.limits.rows,e.limits.rows);if(o.length>a){l.errors.push(p(t,r,`${b(n)} holds at most ${a} rows; ${i.maxItems?"keep the ones that matter":"page through the rest"}.`));return}for(let[s,c]of o.entries()){let d=w(r,s);if(!D(c)){l.errors.push(p(t,d,`A row is an object of its fields, like {"name": "\u2026"}; got ${X(c)}.`));continue}for(let[h,y]of Object.entries(c))y===null||typeof y=="number"||typeof y=="boolean"||typeof y=="string"&&y.length<=e.limits.textLength||l.errors.push(p(t,w(d,h),typeof y=="string"?`A cell holds at most ${e.limits.textLength} characters.`:`A cell holds text, a number or true/false; got ${X(y)}.`))}}function Gt(e,t,n,i,o,r,l,a){if(ae(e,t,r,l,a))return;let s=`${n} ${b(i)}`;if(!Array.isArray(r)){a.errors.push(p(t,l,`${s} is an array of numbers, or {"path": "/\u2026"} to one in the data model; got ${X(r)}.`));return}if(r.length<(o.minItems??0)||r.length>e.limits.rows){a.errors.push(p(t,l,`${s} holds ${o.minItems??0} to ${e.limits.rows} numbers; this is ${r.length}.`));return}let c=r.findIndex(d=>typeof d!="number"||!Number.isFinite(d));c!==-1&&a.errors.push(p(t,w(l,c),`${s} holds numbers only; this one is ${b(r[c])}.`))}function Ut(e,t,n,i,o,r){for(let[l,a]of Object.entries(n.props)){let s=i[l];if(!a.rows||s===void 0)continue;let c=i[a.rows],d=Array.isArray(s)?s.filter(D):[],h=Object.entries(a.fields??{}).filter(([,g])=>g.writes).map(([g])=>g),y=Array.isArray(s)&&!(D(c)&&"path"in c)?s.findIndex(g=>D(g)&&h.some(M=>g[M]===!0)):-1;if(y>=0&&r.errors.push(p(e,w(o,l,y),`What a person enters here is written to ${b(a.rows)}, so bind it to the data model: {"path": "/\u2026"}, with the rows in updateDataModel.`)),!(!Array.isArray(c)||a.kind!=="key"&&!a.numeric))for(let g of a.kind==="key"?[s]:d.map(M=>M.key)){if(typeof g!="string"||!Ie.test(g)||ge.has(g))continue;let M=k=>a.numeric?k==null||typeof k=="number"&&Number.isFinite(k)&&k>=(a.minimum??-1/0):typeof k=="string"&&k.trim()!==""||typeof k=="number",q=c.findIndex(k=>D(k)&&!M(re(k,g)));if(q===-1)continue;let C=re(c[q],g);r.errors.push(p(e,C===void 0?w(o,a.rows,q):w(o,a.rows,q,g),a.numeric?`${t} draws ${b(g)} as a number${a.minimum===void 0?"":` of at least ${a.minimum}`}; this row has ${b(C)}. Write the number itself, or leave it out for a gap.`:`${t} names each row by its ${b(g)}; this row has ${C===void 0?"none":b(C)}.`))}}}function Jt(e,t,n,i,o,r,l){let a=s=>typeof o[s]=="number"?o[s]:i.props[s]?.default;if(n==="Slider"){let s=a("min"),c=a("max"),d=a("step");typeof s=="number"&&typeof c=="number"&&s>=c&&l.errors.push(p(t,w(r,"max"),`Slider "max" (${c}) must be greater than "min" (${s}).`)),typeof d=="number"&&(d<=0||d>c-s)&&l.errors.push(p(t,w(r,"step"),'Slider "step" is greater than 0 and at most max minus min.')),typeof o.value=="number"&&(o.value<s||o.value>c)&&l.errors.push(p(t,w(r,"value"),`Slider "value" ${o.value} is outside ${s} to ${c}.`))}if(n==="Progress"){let s=a("max");typeof s=="number"&&s<=0&&l.errors.push(p(t,w(r,"max"),'Progress "max" is greater than 0.')),typeof o.value=="number"&&(o.value<0||o.value>s)&&l.errors.push(p(t,w(r,"value"),`Progress "value" ${o.value} is outside 0 to ${s}.`))}if(n==="DatePicker"){let{min:s,max:c,value:d}=o;se(s)&&se(c)&&s>c?l.errors.push(p(t,w(r,"max"),`DatePicker "max" (${c}) comes before "min" (${s}); make it the later day.`)):se(d)&&(se(s)&&d<s||se(c)&&d>c)&&l.errors.push(p(t,w(r,"value"),`DatePicker "value" ${d} is outside ${se(s)?s:"any day"} to ${se(c)?c:"any day"}.`))}if((n==="Select"||n==="RadioGroup")&&typeof o.value=="string"&&Array.isArray(o.options)){let s=o.options.filter(D).map(c=>c.value);s.includes(o.value)||l.errors.push(p(t,w(r,"value"),`${n} "value" ${b(o.value)} is not one of its options (${ne(s)}).`))}Ut(t,n,i,o,r,l)}function fe(e){let t=e.props.children;return Array.isArray(t)?{ids:t.filter(n=>typeof n=="string"),template:null}:D(t)&&typeof t.componentId=="string"?{ids:[t.componentId],template:t}:{ids:[],template:null}}function Vt(e,t,n){let{components:i}=t,o=i.get("root");if(!o){n.errors.push(p(t.id,t.at,'No component has the id "root". One component is the root of the tree; give it "id": "root".'));return}let r=new Map;for(let d of i.values()){let{ids:h,template:y}=fe(d),g=w(d.at,"children");for(let[M,q]of h.entries()){let C=y?w(g,"componentId"):w(g,M),k=i.get(q);if(!k){n.errors.push(p(t.id,C,`No component has the id ${b(q)}. Add it, or remove it from ${d.type}'s children.`));continue}if(q===d.id){n.errors.push(p(t.id,C,`${b(q)} lists itself as a child: the children form a loop. A component cannot be inside its own tree.`));continue}if(q==="root"){n.errors.push(p(t.id,C,'"root" is the top of the tree and cannot be a child.'));continue}let I=r.get(q);if(I&&I!==d.id){n.errors.push(p(t.id,C,`${b(q)} is already a child of ${b(I)}. A component appears in one place; give the second one its own id.`));continue}r.set(q,d.id),k.definition?.parents&&d.definition&&!k.definition.parents.includes(d.type)&&n.errors.push(p(t.id,C,`${k.type} goes directly inside ${k.definition.parents.join(" or ")}, not inside ${d.type}.`)),d.definition?.accepts&&k.definition&&!d.definition.accepts.includes(k.type)&&n.errors.push(p(t.id,C,`${d.type} holds only ${d.definition.accepts.join(" and ")} components; ${b(q)} is a ${k.type}.`))}}for(let d of i.values())d.definition?.parents&&d.id!=="root"&&!r.has(d.id)&&n.errors.push(p(t.id,d.at,`${d.type} goes directly inside ${d.definition.parents.join(" or ")}; list ${b(d.id)} in one's children.`));let l=new Set(["root"]),a=new Set,s=[],c=[{node:o,depth:1,templated:!1}];for(;c.length;){let{node:d,depth:h,templated:y}=c.pop();if(s.push(d),y&&a.add(d.id),h>e.limits.depth){n.errors.push(p(t.id,d.at,`The tree is more than ${e.limits.depth} levels deep at ${b(d.id)}; flatten it.`));continue}let{ids:g,template:M}=fe(d);for(let q=g.length-1;q>=0;q-=1){let C=i.get(g[q]);if(!(!C||r.get(C.id)!==d.id)){if(l.has(C.id)){n.errors.push(p(t.id,w(d.at,"children"),`${b(C.id)} contains itself: the children form a loop. A component cannot be inside its own tree.`));continue}l.add(C.id),c.push({node:C,depth:h+1,templated:y||!!M})}}}for(let d of i.values())!l.has(d.id)&&!(d.definition?.parents&&!r.has(d.id))&&n.advice.push(Ce(t.id,d.at,`${b(d.id)} is not inside "root", so it will not show. List it in a parent's children, or remove it.`));Kt(e,t,s,a,n),Yt(t,s,n)}function Kt(e,t,n,i,o){let r=a=>D(a)&&typeof a.path=="string"&&!a.path.startsWith("/"),l=(a,s)=>o.errors.push(p(t.id,w(s,"path"),`${b(a.path)} is relative, which only works inside a template; write it from the top of the data model, like "/${a.path}".`));for(let a of n)if(!(i.has(a.id)||!a.definition))for(let[s,c]of Object.entries(a.props)){let d=w(a.at,s);if(s==="children")r(c)&&o.errors.push(p(t.id,w(d,"path"),`A template's "path" points at an array from the top of the data model, like "/${c.path}"; a relative path works only inside another template.`));else if(s==="accessibility"&&D(c))for(let h of["label","description"])r(c[h])&&l(c[h],w(d,h));else if(s==="action"&&D(c)&&D(c.event)&&D(c.event.context))for(let[h,y]of Object.entries(c.event.context))r(y)&&l(y,w(d,"event","context",h));else r(c)&&l(c,d)}}function Yt(e,t,n){let i=0,o=null,r=new Map,l=(a,s)=>a.props[s]??a.definition?.props[s]?.default;for(let a of t){if(a.type==="Heading"&&Number.isInteger(l(a,"level"))){let c=l(a,"level");i&&c>i+1&&n.errors.push(p(e.id,w(a.at,"level"),`This heading jumps from level ${i} to ${c}; use ${i+1}. A screen reader uses the levels to move through the surface.`)),i=c}a.type==="Button"&&l(a,"variant")==="primary"&&(o?n.advice.push(Ce(e.id,w(a.at,"variant"),`${b(o)} is already the primary action; keep one primary Button per surface and make this one "secondary".`)):o=a.id);let s=typeof a.props.label=="string"?a.props.label.trim().toLowerCase():null;s&&a.definition?.group==="form"&&(r.has(s)?n.advice.push(Ce(e.id,w(a.at,"label"),`${b(r.get(s))} has the same label; give each field its own so they can be told apart.`)):r.set(s,a.id))}}var lt=/^(0|[1-9][0-9]{0,5})$/;function be(e,t){if(t===""||t==="/")return e;let n=e;for(let i of t.slice(1).split("/").map(Ee)){if(!D(n)&&!Array.isArray(n)||Array.isArray(n)&&!lt.test(i))return;n=Object.hasOwn(n,i)?n[i]:void 0}return n}function De(e,t,n){if(t===""||t==="/")return{root:n===void 0?{}:n};let i=t.slice(1).split("/").map(Ee),o=D(e)||Array.isArray(e)?e:{},r=o;for(let[a,s]of i.entries()){if(Array.isArray(r)&&!lt.test(s))return{error:`${b(i.slice(0,a).join("/")||"/")} holds an array, so the next segment is an index like 0, not ${b(s)}.`};if(Array.isArray(r)&&Number(s)>r.length)return{error:`${b(i.slice(0,a).join("/")||"/")} holds ${r.length} ${r.length===1?"item":"items"}, so the next index is at most ${r.length}, not ${s}.`};if(a===i.length-1)break;!D(r[s])&&!Array.isArray(r[s])&&(r[s]={}),r=r[s]}let l=i.at(-1);return n===void 0?delete r[l]:r[l]=n,{root:o}}var Xt=["createSurface","updateComponents","updateDataModel","deleteSurface"],Zt=/^(?:\/\d+)?\/(?:createSurface|updateComponents|updateDataModel|deleteSurface)(\/.*)?$/,Qt=new Set(["EmptyState","Accordion"]),J=e=>D(e)&&typeof e.path=="string",Pe=e=>e!==null&&typeof e=="object"?JSON.parse(JSON.stringify(e)):e;function ye(e,t=""){return e.startsWith("/")?e:e?`${t}/${e}`:t||"/"}function ct(e,t="v0.9.1"){let n=Zt.exec(e.path);return{version:t,error:{code:e.code,surfaceId:e.surfaceId,path:n?n[1]||"/":e.path||"/",message:e.message}}}function dt(e,t={}){let n=t,i=Oe(e),o=n.version??e.protocolVersions.at(-1),r=n.now??(()=>new Date),l=new Map,a=new Set,s=new Set,c=0,d=[],h=$=>{n.onError?n.onError($):d.push(...$)},y=0,g=()=>{c+=1;for(let $ of[...a])$()};function M($){let u=new Map,T=$.get("root");if(!T)return u;let W=new Set(["root"]),L=[T],S=1;for(;L.length;){let A=L.pop();A.type==="Heading"?S=Number.isInteger(A.props.level)?A.props.level:A.definition?.props.level?.default??2:Qt.has(A.type)&&u.set(A.id,Math.min(6,S+1));let{ids:_}=fe(A);for(let K=_.length-1;K>=0;K-=1){let Y=$.get(_[K]);Y&&!W.has(Y.id)&&(W.add(Y.id),L.push(Y))}}return u}function q($,{streaming:u=!1}={}){let T=ot($,e.limits);if(T.error){let S={errors:[{code:"VALIDATION_FAILED",surfaceId:"",path:"",message:T.error}],advice:[]};return h(S.errors.map(A=>ct(A,o))),S}let L=Array.isArray(T.messages)&&!T.messages.length?{errors:[],advice:[]}:it(i,T.messages);for(let S of Array.isArray(T.messages)?T.messages:[T.messages])if(D(S))for(let A of Xt)D(S[A])&&typeof S[A].surfaceId=="string"&&s.add(S[A].surfaceId);for(let S of[...l.keys()]){let A=i.surfaces.get(S);(!A||A.deleted)&&l.delete(S)}if(!u){let S=new Set(L.errors.map(A=>`${A.path}\0${A.message}`));for(let A of s){let _=i.surfaces.get(A);if(!_||_.deleted||!_.components.size)continue;let K=st(i,A);if(K.errors.length){for(let Q of K.errors){let ee=`${Q.path}\0${Q.message}`;S.has(ee)||L.errors.push(Q),S.add(ee)}continue}L.advice.push(...K.advice);let Y=new Map(_.components);y+=1,l.set(A,{components:Y,theme:_.theme,levels:M(Y),missing:l.get(A)?.missing??new Set,structure:y})}s.clear()}return L.errors.length&&h(L.errors.map(S=>ct(S,o))),g(),L}let C=$=>l.get($)??null,k=$=>i.surfaces.get($)?.data;function I($,u,T=""){return J(u)?be(k($),ye(u.path,T)):u}function O($,u,T=""){let W=C($),L=W?.components.get(u);if(!L)return[];let{ids:S,template:A}=fe(L);if(!A)return S.filter(Q=>W.components.has(Q)).map(Q=>({id:Q,scope:T,key:`${Q}@${T}`}));if(!W.components.has(A.componentId))return[];let _=ye(A.path,T),K=be(k($),_);if(!Array.isArray(K))return[];let Y=_==="/"?"":_;return K.slice(0,e.limits.components).map((Q,ee)=>({id:A.componentId,scope:`${Y}/${ee}`,key:`${A.componentId}@${Y}/${ee}`}))}function E($,u,T,W=""){let L=i.surfaces.get($);if(!L||L.deleted||!J(u))return!1;let S=ye(u.path,W),A=De(L.data,S,T);if(A.error)return!1;L.data=A.root;let _=C($);if(_?.missing.size)for(let K of[..._.missing])K.endsWith(`|${S}`)&&_.missing.delete(K);return g(),!0}function*B($,u="root",T="",W=0){let L=C($)?.components.get(u);if(!(!L||W>e.limits.depth)){yield{node:L,scope:T};for(let S of O($,u,T))yield*B($,S.id,S.scope,W+1)}}let V=$=>$==null||$===!1||typeof $=="string"&&!$.trim();function le($,u,T=""){let W=C($),S=W?.components.get(u)?.props.action?.event;if(!W||!D(S))return{sent:null,missing:[]};let A=D(S.context)?S.context:{},_=Object.values(A).filter(J).map(G=>ye(G.path,T)),K=G=>_.some(U=>U==="/"||U===G||G.startsWith(`${U}/`)),Y=[];for(let G of B($)){let{props:U,definition:ce}=G.node;if(ce?.group!=="form"||I($,U.required,G.scope)!==!0)continue;let ie=J(U.value)?U.value:J(U.checked)?U.checked:null;if(!ie)continue;let ue=ye(ie.path,G.scope);K(ue)&&V(be(k($),ue))&&Y.push({id:G.node.id,scope:G.scope,key:`${G.node.id}@${G.scope}`,path:ue,label:I($,U.label,G.scope)})}if((Y.length||_.length)&&(W.missing=new Set(Y.map(G=>`${G.key}|${G.path}`))),Y.length)return g(),{sent:null,missing:Y};let Q={version:o,action:{name:S.name,surfaceId:$,sourceComponentId:u,timestamp:r().toISOString(),context:Object.fromEntries(Object.entries(A).map(([G,U])=>[G,Pe(I($,U,T))??null]))}},ee=i.surfaces.get($);return n.onAction?.(Q,ee?.sendDataModel?{dataModel:Pe(ee.data)}:{}),g(),{sent:Q,missing:[]}}return{rules:e,receive:q,surfaces:()=>[...l.keys()],surface:$=>l.has($)?{id:$,theme:l.get($).theme}:null,component:($,u)=>C($)?.components.get(u)??null,children:O,read:I,write:E,press:le,missing:($,u,T="")=>{let W=C($);if(!W?.missing.size)return!1;let L=`${u}@${T}|`;for(let S of W.missing)if(S.startsWith(L))return!0;return!1},structure:$=>C($)?.structure??0,headingLevel:($,u)=>C($)?.levels.get(u)??2,configure:$=>{if(n={...n,...$},n.onError&&d.length){let u=d;d=[],n.onError(u)}},reset:()=>{i=Oe(e),l.clear(),s.clear(),g()},dataModel:$=>Pe(k($)),subscribe:$=>(a.add($),()=>a.delete($)),revision:()=>c}}var ut={info:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="M12 11v6M12 7h.01" pathLength="1"></path></svg>',success:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m7.5 12 3 3 6-6" pathLength="1"></path></svg>',warning:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m10.3 3.8-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3.2l-8-14a2 2 0 0 0-3.4 0Z" pathLength="1"></path><path d="M12 9v4M12 17h.01" pathLength="1"></path></svg>',danger:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><circle cx="12" cy="12" r="9.5" pathLength="1"></circle><path d="m9 9 6 6M15 9l-6 6" pathLength="1"></path></svg>',check:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="20 6 9 17 4 12" pathLength="1"></polyline></svg>',chevron:'<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" class="mlola-glyph" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><polyline points="6 9 12 15 18 9" pathLength="1"></polyline></svg>'};var en={required:"Fill in this field.",missing:e=>`Fill in ${e.join(", ")} first.`,yes:"Yes",no:"No"},Z=e=>e==null?"":String(e),ht=e=>e!=null&&e!=="",me=(e,t)=>`${e}-${Array.from(t,n=>/[A-Za-z0-9_-]/.test(n)?n:`_${n.codePointAt(0)?.toString(16)}`).join("")}`,tn=0;function f(e,t={},...n){let i=document.createElement(e);for(let[o,r]of Object.entries(t))r==null||r===!1||i.setAttribute(o,r===!0?"":String(r));for(let o of n.flat())o!=null&&o!==!1&&i.append(o);return i}function we(e,t){let n=document.createElement("span");n.innerHTML=ut[e];let i=n.firstElementChild;return t&&i.classList.add(t),i}function mt(e,t={}){let n=t.host??dt(t.rules,{onAction:t.onAction,onError:t.onError}),i={...en,...t.labels},o=`ml-render-${tn+=1}`,r=f("div",{class:"ml-render"}),l=f("p",{role:"status",class:"ml-visually-hidden"});r.append(l),e.append(r);let a=new Map,s=k=>k.mode==="system"&&t.systemMode?t.systemMode:k.mode;function c(){let k=t.surfaceId?n.surface(t.surfaceId)?[t.surfaceId]:[]:n.surfaces();for(let[O,E]of a)k.includes(O)||(E.node.remove(),a.delete(O));t.streaming?r.setAttribute("aria-busy","true"):r.removeAttribute("aria-busy");for(let O of k){let E=a.get(O);if(E&&E.structure===n.structure(O)&&E.lists.every(V=>V.count()===V.length)){for(let V of E.updaters)V();continue}let B=y(O,E);E?E.node.replaceWith(B.node):r.insertBefore(B.node,l),a.set(O,B),tt(B.node),h(B.node,B.kept)}let I=l;for(let O of[...k].reverse()){let E=a.get(O).node;E.nextSibling!==I&&r.insertBefore(E,I),I=E}}function d(k){let I=k.contains(document.activeElement)?document.activeElement:null;return{focus:I?.id??null,selection:I&&"selectionStart"in I?[I.selectionStart,I.selectionEnd]:null,tabs:[...k.querySelectorAll('.ml-tabs-trigger[aria-selected="true"]')].map(O=>O.id),open:[...k.querySelectorAll('.ml-accordion-item[data-state="open"] .ml-accordion-trigger')].map(O=>O.id)}}function h(k,I){if(!I)return;for(let E of I.tabs)document.getElementById(E)?.click();for(let E of k.querySelectorAll(".ml-accordion-trigger"))I.open.includes(E.id)!==(E.getAttribute("aria-expanded")==="true")&&E.click();let O=I.focus?document.getElementById(I.focus):null;if(O&&(O.focus(),I.selection&&"setSelectionRange"in O))try{O.setSelectionRange(...I.selection)}catch{}}function y(k,I){let O=I?d(I.node):null,E=n.surface(k),B=t.theme==="inherit"?null:E.theme,V=f("div",{class:"ml-render-surface","data-surface":k,"data-theme":B?.name,"data-mode":B?s(B):null,"data-themed":B?!0:null}),le={surfaceId:k,base:`${o}-${k}`,updaters:[],lists:[]};return V.append(...q(le,{id:"root",scope:"",key:"root@"})),{node:V,structure:n.structure(k),lists:le.lists,updaters:le.updaters,kept:O}}function g(k,I,O){let E=n.component(k.surfaceId,I),B=n.children(k.surfaceId,I,O);return E&&!Array.isArray(E.props.children)&&E.props.children&&k.lists.push({length:B.length,count:()=>n.children(k.surfaceId,I,O).length}),B}function M(k,I,O){let{missing:E}=n.press(k,I,O);if(l.textContent=E.length?i.missing(E.map(V=>Z(V.label))):"",!E.length)return;let B=document.getElementById(me(`${o}-${k}`,E[0].key));(B?.matches("input, textarea, button, [tabindex]")?B:B?.querySelector("input, textarea, button, [tabindex]"))?.focus()}function q(k,I){let{surfaceId:O,updaters:E}=k,{id:B,scope:V,key:le}=I,$=n.component(O,B);if(!$)return[];let u=$.props,T=m=>n.read(O,m,V),W=(m,v)=>n.write(O,m,v,V),L=me(k.base,le),S=m=>{m(),E.push(m)},A=(m,v)=>(S(()=>{m.textContent=Z(T(v))}),m),_=()=>g(k,B,V).flatMap(m=>q(k,m)),K=u.accessibility??{},Y=m=>(S(()=>{let v=Z(T(K.label)),x=Z(T(K.description));v?m.setAttribute("aria-label",v):m.removeAttribute("aria-label"),x?m.setAttribute("aria-description",x):m.removeAttribute("aria-description")}),m),Q=m=>K.label===void 0?m:(m.setAttribute("role","group"),Y(m)),ee=()=>Array.isArray(T(u.options))?T(u.options).filter(m=>typeof m?.label=="string"&&typeof m?.value=="string"&&m.value):[],G=()=>{if(!J(u.options))return;let m=()=>JSON.stringify(ee());k.lists.push({length:m(),count:m})},U=()=>T(u.disabled)===!0,ce=()=>T(u.required)===!0,ie=(m,v)=>{let x=f("p",{id:`${L}-error`,role:"alert",class:"ml-input-error",hidden:!0});return S(()=>{let j=n.missing(O,B,V);x.hidden=!j,x.textContent=j?i.required:"",m.toggleAttribute("data-invalid",j),j?v.setAttribute("aria-invalid","true"):v.removeAttribute("aria-invalid");let z=[ht(u.hint)?`${L}-hint`:null,j?`${L}-error`:null].filter(Boolean).join(" ");z?v.setAttribute("aria-describedby",z):v.removeAttribute("aria-describedby")}),x},ue=m=>{let v=f("label",{id:`${m}-label`,for:m,class:"ml-input-label"}),x=document.createTextNode(""),j=f("span",{"aria-hidden":"true",class:"ml-required-mark"},"*");return v.append(x),S(()=>{x.textContent=Z(T(u.label)),ce()?v.append(j):j.remove()}),v},Fe=()=>ht(u.hint)?A(f("p",{id:`${L}-hint`,class:"ml-input-hint"}),u.hint):null,We=m=>(J(u.value)?(S(()=>{let v=Z(T(u.value));m.value!==v&&(m.value=v)}),m.addEventListener("input",()=>W(u.value,m.value))):m.value=Z(u.value),S(()=>{m.disabled=U(),m.required=ce()}),m);switch($.type){case"Stack":return[Q(f("div",{class:"ml-stack"},_()))];case"Row":return[Q(f("div",{class:"ml-cluster"},_()))];case"Grid":return[Q(f("div",{class:"ml-grid","data-columns":u.columns},_()))];case"Heading":return[A(f(`h${u.level??2}`),u.text)];case"Text":return[A(f("p",{class:"ml-render-text"}),u.text)];case"Card":return[Q(f("div",{class:"ml-card","data-variant":u.variant??"default"},f("div",{class:"ml-card-content ml-stack"},_())))];case"Alert":{let m=u.tone??"neutral";return[f("div",{class:"ml-alert",role:m==="danger"||m==="warning"?"alert":"status","data-tone":m,"data-variant":u.variant??"card","data-state":"open"},f("span",{"aria-hidden":"true",class:"ml-alert-icon"},we(m==="neutral"?"info":m)),f("div",{class:"ml-alert-content"},u.title!==void 0?A(f("p",{class:"ml-alert-title"}),u.title):null,A(f("div",{class:"ml-alert-description"}),u.text)))]}case"EmptyState":{let m=u.children!==void 0?_():[];return[f("section",{class:"ml-empty","data-size":u.size??"inline"},A(f(`h${n.headingLevel(O,B)}`,{class:"ml-empty-title"}),u.title),u.description!==void 0?A(f("p",{class:"ml-empty-description"}),u.description):null,m.length?f("div",{class:"ml-empty-actions"},m):null)]}case"Tabs":{let m=g(k,B,V);if(!m.length)return[];let v=f("div",{class:"ml-tabs-list",role:"tablist","aria-orientation":"horizontal"});S(()=>v.setAttribute("aria-label",Z(T(u.label))));let x=[];for(let[j,z]of m.entries()){let N=me(k.base,`${z.key}-tab`),H=me(k.base,`${z.key}-panel`),R=j===0,F=f("button",{class:"ml-tabs-trigger",id:N,type:"button",role:"tab","aria-selected":String(R),"aria-controls":H,tabindex:R?"0":"-1","data-state":R?"active":"inactive"});S(()=>{F.textContent=Z(n.read(O,n.component(O,z.id)?.props.label,z.scope))}),v.append(F),x.push(f("div",{class:"ml-tabs-content ml-stack",id:H,role:"tabpanel","aria-labelledby":N,tabindex:"0",hidden:!R,"data-state":R?"active":"inactive"},g(k,z.id,z.scope).flatMap(te=>q(k,te))))}return[f("div",{class:"ml-tabs","data-ml":"tabs","data-variant":u.variant??"default","data-orientation":"horizontal"},v,x)]}case"Accordion":{let m=n.headingLevel(O,B),v=g(k,B,V).map(x=>{let j=me(k.base,`${x.key}-trigger`),z=me(k.base,`${x.key}-panel`),N=f("span",{class:"ml-accordion-trigger-label"});return S(()=>{N.textContent=Z(n.read(O,n.component(O,x.id)?.props.title,x.scope))}),f("div",{class:"ml-accordion-item","data-state":"closed"},f(`h${m}`,{class:"ml-accordion-heading"},f("button",{class:"ml-accordion-trigger",id:j,type:"button","aria-expanded":"false","aria-controls":z,"data-state":"closed"},N,we("chevron","ml-accordion-chevron"))),f("div",{class:"ml-accordion-panel",id:z,role:"region","aria-labelledby":j,"data-state":"closed",hidden:!0},f("div",{class:"ml-accordion-panel-inner ml-stack"},g(k,x.id,x.scope).flatMap(H=>q(k,H)))))});return[f("div",{class:"ml-accordion","data-ml":"accordion","data-ml-multiple":u.type==="multiple"?"true":null},v)]}case"Tab":case"AccordionItem":return[];case"Input":case"DatePicker":{let m=We(f("input",{class:"ml-input",id:L,type:$.type==="DatePicker"?"date":u.type??"text","data-variant":u.variant??"default","data-size":u.size??"md",maxlength:$.type==="Input"?n.rules.limits.textLength:null,min:u.min,max:u.max}));$.type==="DatePicker"&&J(u.value)&&m.addEventListener("change",()=>W(u.value,m.value||null)),S(()=>{let x=Z(T(u.placeholder));x?m.setAttribute("placeholder",x):m.removeAttribute("placeholder")});let v=f("div",{class:"ml-input-field"});return v.append(ue(L),f("div",{class:"ml-input-control"},m),...[Fe()].filter(Boolean),ie(v,m)),[v]}case"Textarea":{let m=We(f("textarea",{class:"ml-textarea",id:L,rows:u.rows??4,maxlength:n.rules.limits.textLength}));S(()=>{let x=Z(T(u.placeholder));x?m.setAttribute("placeholder",x):m.removeAttribute("placeholder")});let v=f("div",{class:"ml-input-field"});return v.append(ue(L),m,...[Fe()].filter(Boolean),ie(v,m)),[v]}case"Select":{let m=`${L}-label`,v=`${L}-list`,x=f("span",{class:"ml-select-value"}),j=f("button",{class:"ml-select",id:L,type:"button",role:"combobox","aria-haspopup":"listbox","aria-expanded":"false","aria-controls":v,"aria-labelledby":m,"data-size":u.size??"md","data-state":"closed"},x,we("chevron","ml-select-chevron")),z=f("ul",{class:"ml-select-list",id:v,role:"listbox","aria-labelledby":m});G();for(let[H,R]of ee().entries())z.append(f("li",{class:"ml-select-option",id:`${L}-option-${H}`,role:"option","data-value":R.value,"aria-selected":"false","data-state":"unchecked"},R.label));let N=f("div",{class:"ml-select-root","data-ml":"select"},A(f("span",{class:"ml-select-label",id:m}),u.label),f("div",{class:"ml-select-control"},j),f("div",{class:"ml-select-popover"},z));return S(()=>{let H=Z(T(u.value)),R=ee().find(F=>F.value===H);x.textContent=R?R.label:Z(T(u.placeholder))||"\xA0",x.toggleAttribute("data-placeholder",!R);for(let F of z.children){let te=F.dataset.value===H;F.setAttribute("aria-selected",String(te)),F.dataset.state=te?"checked":"unchecked"}j.disabled=U(),ce()?j.setAttribute("aria-required","true"):j.removeAttribute("aria-required")}),J(u.value)&&N.addEventListener("ml-change",H=>W(u.value,H.detail.value)),N.append(ie(N,j)),[N]}case"RadioGroup":{let m=`${L}-label`;G();let v=ee(),x=v.map((R,F)=>f("input",{class:"ml-radio-input",id:`${L}-${F}`,type:"radio",name:L,value:R.value})),j=v.map((R,F)=>f("label",{class:"ml-radio-item",for:`${L}-${F}`,"data-state":"unchecked"},f("span",{class:"ml-radio-control"},x[F],f("span",{class:"ml-radio-indicator","aria-hidden":"true"})),f("span",{class:"ml-radio-copy"},f("span",{class:"ml-radio-label"},R.label)))),z=u.orientation??"vertical",N=f("div",{class:"ml-radio-group",id:L,role:"radiogroup","aria-labelledby":m,"aria-orientation":z,"data-orientation":z},A(f("div",{class:"ml-radio-group-label",id:m}),u.label),f("div",{class:"ml-radio-group-items"},j)),H=Z(u.value);S(()=>{let R=J(u.value)?Z(T(u.value)):H;for(let[F,te]of x.entries())te.checked=te.value===R,te.disabled=U(),j[F].dataset.state=te.checked?"checked":"unchecked";ce()?N.setAttribute("aria-required","true"):N.removeAttribute("aria-required")});for(let R of x)R.addEventListener("change",()=>{if(J(u.value))W(u.value,R.value);else{H=R.value;for(let F of E)F()}});return N.append(ie(N,N)),[N]}case"Checkbox":{let m=f("input",{class:"ml-checkbox-input",id:L,type:"checkbox"}),v=f("span",{class:"ml-checkbox-copy"},f("label",{class:"ml-checkbox-label",for:L},A(f("span",{class:"ml-checkbox-text"}),u.label)),u.description!==void 0?A(f("span",{class:"ml-checkbox-description",id:`${L}-description`}),u.description):null),x=f("div",{class:"ml-checkbox-field","data-state":"unchecked"},f("label",{class:"ml-checkbox-control","data-hit":"expand"},m,f("span",{class:"ml-checkbox-indicator","aria-hidden":"true"},we("check"))),v);return J(u.checked)||(m.checked=u.checked===!0),S(()=>{J(u.checked)&&(m.checked=T(u.checked)===!0),m.disabled=U(),m.required=ce(),x.dataset.state=m.checked?"checked":"unchecked"}),m.addEventListener("change",()=>{J(u.checked)&&W(u.checked,m.checked),x.dataset.state=m.checked?"checked":"unchecked"}),x.append(ie(x,m)),[x]}case"Switch":{let m=`${L}-label`,v=f("button",{class:"ml-toggle",id:L,type:"button",role:"switch","data-ml":"switch","aria-checked":String(J(u.checked)?T(u.checked)===!0:u.checked===!0),"aria-labelledby":m,"data-size":u.size??"md","data-hit":"expand"},f("span",{class:"ml-toggle-thumb","aria-hidden":"true"}));return v.dataset.state=v.getAttribute("aria-checked")==="true"?"checked":"unchecked",S(()=>{if(J(u.checked)){let x=T(u.checked)===!0;v.setAttribute("aria-checked",String(x)),v.dataset.state=x?"checked":"unchecked"}v.disabled=U()}),J(u.checked)&&v.addEventListener("ml-change",x=>W(u.checked,x.detail.value)),[f("span",{class:"ml-switch-field"},v,A(f("span",{class:"ml-switch-label",id:m}),u.label))]}case"Slider":{let m=u.min??0,v=u.max??100,x=`${L}-label`,j=f("span",{class:"ml-slider-output"}),z=f("span",{class:"ml-slider-range","aria-hidden":"true"}),N=f("span",{class:"ml-slider-thumb",id:L,role:"slider",tabindex:"0","aria-labelledby":x,"aria-valuemin":m,"aria-valuemax":v}),H=f("div",{class:"ml-slider-field","data-ml":"slider","data-size":u.size??"md","data-ml-step":u.step??1},f("div",{class:"ml-slider-header"},A(f("span",{class:"ml-slider-label",id:x}),u.label),j),f("div",{class:"ml-slider"},f("div",{class:"ml-slider-track"},z,N))),R=typeof u.value=="number"?u.value:m;return S(()=>{let F=J(u.value)?T(u.value):R,te=typeof F=="number"&&Number.isFinite(F)?Math.min(v,Math.max(m,F)):m,He=v>m?(te-m)/(v-m)*100:0;N.setAttribute("aria-valuenow",String(te)),j.textContent=String(te),z.style.width=`${He}%`,N.style.left=`${He}%`,U()?(H.dataset.disabled="",N.setAttribute("aria-disabled","true")):(delete H.dataset.disabled,N.removeAttribute("aria-disabled"))}),H.addEventListener("ml-change",F=>{J(u.value)?W(u.value,F.detail.value):R=F.detail.value}),[H]}case"Button":{let m=A(f("span",{class:"ml-button-label"}),u.text),v=Y(f("button",{class:"ml-button",id:L,type:"button","data-variant":u.variant??"primary","data-size":u.size??"md","data-width":u.width==="full"?"full":null},m));return S(()=>{v.disabled=U()}),v.addEventListener("click",()=>M(O,B,V)),[v]}case"Badge":return[f("span",{class:"ml-badge","data-tone":u.tone??"neutral","data-variant":u.variant??"soft","data-size":u.size??"md"},A(f("span",{class:"ml-badge-label"}),u.text))];case"Progress":{let m=u.max??100,v=f("span",{class:"ml-progress-value","aria-hidden":"true"}),x=f("div",{class:"ml-progress-fill","aria-hidden":"true"}),j=f("div",{class:"ml-progress-track",role:"progressbar","aria-valuemin":"0","aria-valuemax":m},x),z=A(f("span"),u.label),N=f("div",{class:"ml-progress-label"},z,v);return S(()=>{let H=T(u.value),R=typeof H=="number"&&Number.isFinite(H)?Math.min(m,Math.max(0,H)):0,F=Math.round(R/m*100);j.setAttribute("aria-valuenow",String(R)),j.setAttribute("aria-valuetext",`${F}%`),j.setAttribute("aria-label",Z(T(u.label))),x.style.width=`${F}%`,v.textContent=`${F}%`,v.hidden=T(u.showLabel)!==!0}),[f("div",{class:"ml-progress-root","data-tone":u.tone??"primary","data-size":u.size??"md","data-state":"determinate"},N,j)]}case"Avatar":{let m=f("span",{class:"ml-avatar-fallback",role:"img"}),v=u.status?f("span",{class:"ml-avatar-status",role:"status","data-status":u.status}):null;return S(()=>{let x=Z(T(u.name));m.setAttribute("aria-label",x),m.textContent=x.replace(/[^\p{L}\p{N}\s]/gu,"").trim().split(/\s+/).filter(Boolean).slice(0,2).map(j=>j[0].toUpperCase()).join(""),v?.setAttribute("aria-label",`${x} is ${u.status}`)}),[f("span",{class:"ml-avatar-root","data-size":u.size??"md"},f("span",{class:"ml-avatar"},m),v)]}case"Table":{let m=Array.isArray(u.columns)?u.columns:[],v=f("tbody",{class:"ml-table-body"}),x=A(f("caption",{class:"ml-table-caption"}),u.caption),j=f("div",{class:"ml-table-container"},f("table",{class:"ml-table","data-size":u.size??"md"},x,f("thead",{class:"ml-table-header"},f("tr",{class:"ml-table-row"},m.map(z=>A(f("th",{class:"ml-table-head",scope:"col","data-align":z.align??"left"}),z.label)))),v));return S(()=>{j.setAttribute("aria-label",Z(T(u.caption)));let z=T(u.rows);v.replaceChildren(...(Array.isArray(z)?z.slice(0,n.rules.limits.rows):[]).map(N=>f("tr",{class:"ml-table-row"},m.map(H=>f("td",{class:"ml-table-cell","data-align":H.align??"left"},nn(N,H.key,i)))))),queueMicrotask(()=>{let N=j.scrollWidth>j.clientWidth+1;N?j.setAttribute("tabindex","0"):j.removeAttribute("tabindex"),j.setAttribute("role",N?"region":"presentation"),N||j.removeAttribute("role")})}),[j]}default:return[]}}let C=n.subscribe(c);return c(),{host:n,receive:(k,I={})=>(t.streaming=!!I.streaming,n.receive(k,I)),setSystemMode:k=>{if(t.systemMode=k??void 0,t.theme!=="inherit")for(let[I,O]of a){let E=n.surface(I)?.theme;E&&(O.node.dataset.mode=s(E))}},destroy:()=>{C(),r.remove()}}}function nn(e,t,n){let i=e!==null&&typeof e=="object"&&Object.hasOwn(e,t)?e[t]:void 0;return typeof i=="boolean"?i?n.yes:n.no:typeof i=="string"||typeof i=="number"?String(i):"\u2014"}var Ne={version:"1.12.2",catalogId:"https://ui.mlola.com/a2ui/catalog/v1",title:"Mlola Render catalog",description:"Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",protocolVersions:["v0.9","v0.9.1"],themes:["graphite","atelier","machined","aerogel","nordic"],defaultTheme:"graphite",modes:["light","dark","system"],groups:{layout:"Layout",text:"Text",container:"Containers",form:"Forms",action:"Actions",data:"Data"},limits:{messages:200,surfaces:20,components:300,depth:24,idLength:128,textLength:4e3,labelLength:120,options:100,columns:12,rows:500,contextKeys:32,pathLength:512,dataBytes:262144,inputBytes:1048576},components:{Stack:{group:"layout",description:"Places its children in a column with the theme's spacing. Use it as the root of most surfaces.",mlola:{class:"ml-stack"},props:{children:{kind:"children",required:!0,description:"The components inside, top to bottom."}}},Row:{group:"layout",description:"Places its children side by side and wraps them on a narrow screen. Use it for a row of buttons or badges.",mlola:{class:"ml-cluster"},props:{children:{kind:"children",required:!0,description:"The components inside, start to end."}}},Grid:{group:"layout",description:"Places its children in equal columns that collapse to one column on a phone.",mlola:{class:"ml-grid"},props:{children:{kind:"children",required:!0,description:"The components inside, in reading order."},columns:{kind:"enum",description:"How many columns on a wide screen. Leave it out to fit as many as the width allows.",values:["1","2","3","4","6"]}}},Heading:{group:"text",description:"A heading. Levels follow the page outline: never skip a level going deeper.",mlola:{element:"h1-h6"},props:{text:{kind:"text",required:!0,description:"The heading's words.",maxLength:120},level:{kind:"integer",description:"The outline level, 1 to 6. Inside a chat a surface usually starts at 2.",minimum:1,maximum:6,default:2}}},Text:{group:"text",description:"A paragraph of plain text.",mlola:{element:"p"},props:{text:{kind:"text",required:!0,description:"The words. Line breaks are kept; markup is shown as text."}}},Card:{group:"container",description:"Groups related content on a surface of its own.",mlola:{item:"card",export:"Card"},props:{children:{kind:"children",required:!0,description:"The card's content."},variant:{kind:"enum",description:"How the card stands off the page.",values:["default","elevated","glass","specular"],default:"default"}}},Alert:{group:"container",description:"A message about the surface: a confirmation, a warning or an error. Warnings and errors interrupt a screen reader; calmer tones are announced politely.",mlola:{item:"alert",export:"Alert"},props:{title:{kind:"text",description:"A short summary, read first.",maxLength:120},text:{kind:"text",required:!0,description:"What happened and what to do about it."},tone:{kind:"enum",description:"What the message means.",values:["neutral","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"A card, or a tinted band across the surface.",values:["card","soft"],default:"card"}}},EmptyState:{group:"container",description:"Says that there is nothing here yet and what to do next.",mlola:{item:"empty-state",export:"EmptyState"},props:{title:{kind:"text",required:!0,description:"What is empty, in a few words.",maxLength:120},description:{kind:"text",description:"What to do next."},children:{kind:"children",description:"Actions, usually one or two Buttons."},size:{kind:"enum",description:"inline inside a surface, page when it fills one.",values:["inline","page"],default:"inline"}}},Tabs:{group:"container",description:"Shows one panel at a time, chosen from a row of tabs. Its children are Tab components.",accepts:["Tab"],mlola:{item:"tabs",export:"Tabs"},props:{label:{kind:"text",required:!0,description:"What the tabs choose between, for a screen reader.",maxLength:120},children:{kind:"children",required:!0,description:"The Tab components, in order.",minItems:1},variant:{kind:"enum",description:"The look of the tab row.",values:["default","pills","enclosed"],default:"default"}}},Tab:{group:"container",description:"One tab of a Tabs: its name and its panel.",parents:["Tabs"],mlola:{item:"tabs",export:"TabsTrigger"},props:{label:{kind:"text",required:!0,description:"The tab's name.",maxLength:120},children:{kind:"children",required:!0,description:"What the panel shows."}}},Accordion:{group:"container",description:"A list of sections that open and close. Its children are AccordionItem components.",accepts:["AccordionItem"],mlola:{item:"accordion",export:"Accordion"},props:{children:{kind:"children",required:!0,description:"The AccordionItem components, in order.",minItems:1},type:{kind:"enum",description:"single keeps one section open at a time; multiple lets several stay open.",values:["single","multiple"],default:"single"}}},AccordionItem:{group:"container",description:"One section of an Accordion: its title and its content.",parents:["Accordion"],mlola:{item:"accordion",export:"AccordionItem"},props:{title:{kind:"text",required:!0,description:"The section's title, which opens and closes it.",maxLength:120},children:{kind:"children",required:!0,description:"The section's content."}}},Input:{group:"form",description:"A one-line text field with its label.",mlola:{item:"input",export:"Input"},props:{label:{kind:"text",required:!0,description:"The field's name, shown above it and read by a screen reader.",maxLength:120},value:{kind:"text",description:'Bind it to the data model ({"path": "/form/email"}) so the value comes back with the action.'},type:{kind:"enum",description:"The kind of text, which picks the phone keyboard and the browser's checks.",values:["text","email","password","url","tel","search"],default:"text"},placeholder:{kind:"text",description:"An example of what to type. Never a replacement for the label.",maxLength:120},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"},variant:{kind:"enum",description:"How the field sits on its surface.",values:["default","filled","subtle"],default:"default"}}},Textarea:{group:"form",description:"A text field for several lines, with its label.",mlola:{item:"textarea",export:"Textarea"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"text",description:"Bind it to the data model so the value comes back with the action."},placeholder:{kind:"text",description:"An example of what to type. Never the only label.",maxLength:120},hint:{kind:"text",description:"A short help line under the field.",maxLength:120},rows:{kind:"integer",description:"How many lines show before it scrolls.",minimum:2,maximum:12,default:4},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Select:{group:"form",description:"Picks one value from a list that opens on demand. Use RadioGroup when there are only two to five options and room to show them.",mlola:{item:"select",export:"Select"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:1},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},placeholder:{kind:"text",description:"Shown while nothing is chosen.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},RadioGroup:{group:"form",description:"Picks one value from options that are all visible.",mlola:{item:"radio-group",export:"RadioGroup"},props:{label:{kind:"text",required:!0,description:"The question the options answer.",maxLength:120},options:{kind:"options",required:!0,description:'The choices, each {"label", "value"}.',minItems:2},value:{kind:"text",description:"The chosen option's value. Bind it to the data model."},orientation:{kind:"enum",description:"Options stacked or in a row.",values:["horizontal","vertical"],default:"vertical"},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Checkbox:{group:"form",description:"A yes or no choice with its label.",mlola:{item:"checkbox",export:"Checkbox"},props:{label:{kind:"text",required:!0,description:"What checking it means.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model so the choice comes back with the action."},description:{kind:"text",description:"More about the choice, under the label.",maxLength:120},required:{kind:"boolean",description:"The person must fill it in before the action is sent; a screen reader says so."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Switch:{group:"form",description:"Turns a setting on or off right away.",mlola:{item:"toggle",export:"Switch"},props:{label:{kind:"text",required:!0,description:"The setting it turns on.",maxLength:120},checked:{kind:"boolean",description:"Bind it to the data model."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Slider:{group:"form",description:"Picks a number in a range by dragging or with the arrow keys.",mlola:{item:"slider",export:"Slider"},props:{label:{kind:"text",required:!0,description:"What the number is.",maxLength:120},value:{kind:"number",description:"Bind it to the data model."},min:{kind:"number",description:"The lowest value.",literal:!0,default:0},max:{kind:"number",description:"The highest value.",literal:!0,default:100},step:{kind:"number",description:"How far one arrow press moves it.",literal:!0,default:1},disabled:{kind:"boolean",description:"Shows the control but does not let it change."},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md"],default:"md"}}},DatePicker:{group:"form",description:"A date field that opens a calendar and picks one day. The reader sees the date in their own format; the value is an ISO date.",mlola:{item:"date-picker",export:"DatePicker"},props:{label:{kind:"text",required:!0,description:"The field's name.",maxLength:120},value:{kind:"date",description:'The chosen day as an ISO date, like "2026-10-12". Bind it to the data model so it comes back with the action.'},min:{kind:"date",description:"The earliest day that can be picked.",literal:!0},max:{kind:"date",description:"The latest day that can be picked.",literal:!0},hint:{kind:"text",description:"Help shown under the field.",maxLength:120},required:{kind:"boolean",description:"The form cannot be sent without it."},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Button:{group:"action",description:'Sends an action back to the agent. Its text says what happens ("Create workspace", not "Submit").',mlola:{item:"button",export:"Button"},props:{text:{kind:"text",required:!0,description:"What pressing it does.",maxLength:120},action:{kind:"action",required:!0,description:"The event sent when it is pressed."},variant:{kind:"enum",description:"primary for the main action of a surface, one at most.",values:["primary","secondary","subtle","danger","outline","link"],default:"primary"},size:{kind:"enum",description:"Icon-only buttons are not in the catalog: every button has words.",values:["sm","md","lg"],excluded:["icon"],default:"md"},width:{kind:"enum",description:"auto fits the words, full fills the container.",values:["auto","full"],default:"auto"},disabled:{kind:"boolean",description:"Shows the control but does not let it change."}}},Badge:{group:"data",description:"A short label for a status or a count.",mlola:{item:"badge",export:"Badge"},props:{text:{kind:"text",required:!0,description:"The badge's words, a few at most.",maxLength:120},tone:{kind:"enum",description:"What the status means.",values:["neutral","primary","info","success","warning","danger"],default:"neutral"},variant:{kind:"enum",description:"How strongly the badge stands out.",values:["soft","solid","outline"],default:"soft"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Progress:{group:"data",description:"Shows how far along something is.",mlola:{item:"progress",export:"Progress"},props:{label:{kind:"text",required:!0,description:"What is in progress, for a screen reader.",maxLength:120},value:{kind:"number",description:"How far along, from 0 to max."},max:{kind:"number",description:"The value that means complete.",literal:!0,default:100},showLabel:{kind:"boolean",description:"Shows the percentage beside the bar."},tone:{kind:"enum",description:"What the progress means.",values:["primary","info","success","warning","danger"],default:"primary"},size:{kind:"enum",description:"The control size from the density scale.",values:["sm","md","lg"],default:"md"}}},Avatar:{group:"data",description:"A person or a team shown by their initials.",mlola:{item:"avatar",export:"Avatar"},props:{name:{kind:"text",required:!0,description:"The full name: the initials come from it and a screen reader reads it.",maxLength:120},size:{kind:"enum",description:"The avatar's size.",values:["xs","sm","md","lg","xl"],default:"md"},status:{kind:"enum",description:"A presence dot, announced with the name.",values:["online","offline","away","busy"]}}},Table:{group:"data",description:"Rows of data under named columns. Cells hold text and numbers.",mlola:{item:"table",export:"Table"},props:{caption:{kind:"text",required:!0,description:"What the table shows, read first by a screen reader.",maxLength:120},columns:{kind:"columns",required:!0,description:'Each {"key", "label", "align"?}: key names the row field the column shows.',minItems:1,align:{values:["left","center","right"]}},rows:{kind:"rows",required:!0,description:"An array of objects keyed by column key, or a path to one in the data model."},size:{kind:"enum",description:"Row density.",values:["sm","md"],default:"md"}}}},aliases:{Column:"Stack",List:"Stack",TextField:"Input",CheckBox:"Checkbox",ChoicePicker:"Select",Toggle:"Switch",Label:"Text",Paragraph:"Text",Title:"Heading",Callout:"Alert",Banner:"Alert",Chip:"Badge",Tag:"Badge",ProgressBar:"Progress",DataTable:"Table",DataGrid:"Table",DateTimeInput:"DatePicker",DateInput:"DatePicker",Calendar:"DatePicker"},borrowed:{components:{Image:"Say what matters in Text, or leave the image out.",Icon:"Every control has words: put the meaning in the text, or in a Badge.",Video:"Describe it in Text, or leave it out.",AudioPlayer:"Describe it in Text, or leave it out.",Modal:"A surface shows inline, with no dialog. Put the content on the surface, or in a Tab or an AccordionItem to keep it out of the way.",Divider:"Spacing comes from Stack, and a Card or a Heading separates groups. Leave the divider out."},props:{weight:"Children share space by the theme's layout. For equal columns use a Grid.",justify:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.",align:"A Row or a Stack places its children by the theme's layout. For equal columns use a Grid.","Stack.direction":"A Stack is a column. For side by side use a Row.","Text.variant":'Text is one style of paragraph. For a heading use a Heading with "level".',"Button.child":'A Button holds its words in "text", not in a child component.',"Tabs.tabs":`A Tabs' "children" are Tab components, each with a "label" and "children".`,"Checkbox.value":`A Checkbox's state is "checked": true, false or {"path": "/\u2026"}.`,"Switch.value":`A Switch's state is "checked": true, false or {"path": "/\u2026"}.`,"Input.validationRegexp":'Client-side checks are not in the Mlola catalog yet. Mark the field "required", and check the value when the action arrives.',"Select.variant":"A Select picks one value. For several choices, use a Checkbox for each.","Select.displayStyle":"A Select always opens a list. For options that are all visible use a RadioGroup.","Select.filterable":"A Select lists its options as they are. Keep to the ones that matter, at most 100.","Input.variant=longText":"For several lines use a Textarea.","Input.variant=obscured":'For a password use "type": "password".',"Input.variant=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.variant=shortText":'An Input is one line already, so leave "variant" out.',"Input.type=number":"Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.","Input.type=date":"For a day use a DatePicker.","Input.type=time":'Times are not a field type yet. Use a Select of the times on offer, or an Input with a hint like "19:30".',"Input.autocomplete":'The browser fills a field in by its "type": use "email", "tel" or "url" where one fits, and leave "autocomplete" out.',"Switch.description":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Switch.hint":'A Switch has only its "label". Say the rest in a Text before it, or use a Checkbox, which takes a "description".',"Button.variant=default":'For a button beside the main one use "secondary".',"Button.variant=borderless":'For a quiet button use "subtle" or "link".',"DatePicker.enableDate":'A DatePicker always picks a day, so leave "enableDate" out.',"DatePicker.enableTime":"Times are not in the Mlola catalog yet: a DatePicker picks a day. Ask for the time in an Input with a hint."}},examples:[]};var rn="2026-01-26",Re=document.documentElement,pt=document.querySelector("#status"),ve=new Map,Be=0,$e=e=>window.parent.postMessage({jsonrpc:"2.0",...e},"*"),gt=(e,t={})=>$e({method:e,params:t}),bt=(e,t={})=>new Promise((n,i)=>{Be+=1,ve.set(Be,{resolve:n,reject:i}),$e({id:Be,method:e,params:t})}),xe=e=>{pt.textContent=e,pt.hidden=!e};function yt(e){let t=e?.theme==="dark"?"dark":e?.theme==="light"?"light":null;t&&(Re.dataset.mode=t,de.setSystemMode(t))}var de=mt(document.querySelector("#surfaces"),{rules:Ne,onAction:e=>{let{surfaceId:t,sourceComponentId:n}=e.action,o=`I pressed "${de.host.read(t,de.host.component(t,n)?.props.text)}" in the ${t} surface. A2UI action: ${JSON.stringify(e)}`;bt("ui/message",{role:"user",content:[{type:"text",text:o}]}).catch(()=>xe("The host did not take the message. Try again."))}});function ft(e,t){let n=e?.messages;if(de.host.reset(),n===void 0)return;let i=de.receive(n,{streaming:t});t||xe(i.errors.length&&!de.host.surfaces().length?"The agent's interface had errors, so it is not shown. The agent has been told what to fix.":"")}window.addEventListener("message",e=>{if(e.source!==window.parent)return;let t=e.data;if(!(!t||t.jsonrpc!=="2.0")){if(t.id!==void 0&&ve.has(t.id)&&("result"in t||"error"in t)){let{resolve:n,reject:i}=ve.get(t.id);ve.delete(t.id),"error"in t?i(t.error):n(t.result);return}switch(t.method){case"ui/notifications/tool-input-partial":ft(t.params?.arguments,!0);break;case"ui/notifications/tool-input":ft(t.params?.arguments,!1);break;case"ui/notifications/tool-cancelled":de.host.surfaces().length||xe("The agent stopped before the interface was ready.");break;case"ui/notifications/host-context-changed":yt(t.params);break;case"ui/resource-teardown":case"ping":$e({id:t.id,result:{}});break;default:t.id!==void 0&&t.method&&$e({id:t.id,error:{code:-32601,message:`Method not found: ${t.method}`}})}}});var ze=0;new ResizeObserver(()=>{let e=Math.ceil(Re.getBoundingClientRect().height);e!==ze&&(ze=e,gt("ui/notifications/size-changed",{width:Math.ceil(Re.getBoundingClientRect().width),height:ze}))}).observe(document.body);bt("ui/initialize",{appInfo:{name:"mlola-render",version:Ne.version},appCapabilities:{availableDisplayModes:["inline"]},protocolVersion:rn}).then(e=>{yt(e?.hostContext),gt("ui/notifications/initialized")}).catch(e=>xe(`The host did not start this view${e?.message?`: ${e.message}`:"."}`));})();
8476
8476
  </script>
8477
8477
  </body>
8478
8478
  </html>
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://ui.mlola.com/a2ui/catalog/v1",
4
4
  "title": "Mlola Render catalog",
5
- "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class. Generated from Mlola UI 1.11.0; check messages with `npx mlola-ui render check` or the check_render MCP tool, which also hold what a schema cannot (one root, no loops, heading order, values in range).",
5
+ "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class. Generated from Mlola UI 1.12.2; check messages with `npx mlola-ui render check` or the check_render MCP tool, which also hold what a schema cannot (one root, no loops, heading order, values in range).",
6
6
  "catalogId": "https://ui.mlola.com/a2ui/catalog/v1",
7
7
  "components": {
8
8
  "Stack": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "Generated by scripts/build-render-catalog.mjs from packages/registry/render/definition.json. Do not edit.",
3
- "version": "1.11.0",
3
+ "version": "1.12.2",
4
4
  "catalogId": "https://ui.mlola.com/a2ui/catalog/v1",
5
5
  "title": "Mlola Render catalog",
6
6
  "description": "Mlola UI components for interfaces an agent composes at runtime. Every component is accessible by construction and follows the surface's theme; an agent picks named values (tone, variant, size) and never writes a color, size or class.",
@@ -1006,6 +1006,12 @@
1006
1006
  "Input.variant=obscured": "For a password use \"type\": \"password\".",
1007
1007
  "Input.variant=number": "Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.",
1008
1008
  "Input.variant=shortText": "An Input is one line already, so leave \"variant\" out.",
1009
+ "Input.type=number": "Numbers are not a field type yet. Use a Slider for a number in a range, or an Input with a hint.",
1010
+ "Input.type=date": "For a day use a DatePicker.",
1011
+ "Input.type=time": "Times are not a field type yet. Use a Select of the times on offer, or an Input with a hint like \"19:30\".",
1012
+ "Input.autocomplete": "The browser fills a field in by its \"type\": use \"email\", \"tel\" or \"url\" where one fits, and leave \"autocomplete\" out.",
1013
+ "Switch.description": "A Switch has only its \"label\". Say the rest in a Text before it, or use a Checkbox, which takes a \"description\".",
1014
+ "Switch.hint": "A Switch has only its \"label\". Say the rest in a Text before it, or use a Checkbox, which takes a \"description\".",
1009
1015
  "Button.variant=default": "For a button beside the main one use \"secondary\".",
1010
1016
  "Button.variant=borderless": "For a quiet button use \"subtle\" or \"link\".",
1011
1017
  "DatePicker.enableDate": "A DatePicker always picks a day, so leave \"enableDate\" out.",
@@ -1,6 +1,6 @@
1
1
  /** Types for Mlola Render's check (check.js). See docs/render.md. */
2
2
 
3
- export type RenderPropKind = "text" | "boolean" | "number" | "integer" | "date" | "enum" | "children" | "action" | "options" | "columns" | "rows";
3
+ export type RenderPropKind = "text" | "boolean" | "number" | "integer" | "date" | "enum" | "children" | "action" | "options" | "columns" | "rows" | "key" | "numbers";
4
4
 
5
5
  export interface RenderProp {
6
6
  kind: RenderPropKind;
@@ -13,8 +13,17 @@ export interface RenderProp {
13
13
  minimum?: number;
14
14
  maximum?: number;
15
15
  minItems?: number;
16
+ maxItems?: number;
16
17
  literal?: boolean;
17
18
  align?: { values: string[] };
19
+ /** For "columns": what one entry is called in messages ("column" when left out). */
20
+ item?: string;
21
+ /** For "columns": what an entry takes beside its key and label. Named values, or true and false; `writes` marks one that lets a person edit the rows. */
22
+ fields?: Record<string, { values?: string[]; writes?: boolean }>;
23
+ /** The "rows" prop this one reads its fields from, so rows written into the component are held to it. */
24
+ rows?: string;
25
+ /** With `rows`: the fields it names hold numbers. */
26
+ numeric?: boolean;
18
27
  }
19
28
 
20
29
  export interface RenderComponent {
@@ -99,8 +108,11 @@ export function checkSurfaces(state: RenderState, issues?: { errors: RenderIssue
99
108
  /** One surface, checked whole: how it was created, every component it holds now and their tree. */
100
109
  export function checkSurface(state: RenderState, surfaceId: string): { errors: RenderIssue[]; advice: RenderIssue[] };
101
110
 
102
- /** The catalog as Markdown an agent reads before composing a surface. */
103
- export function renderCatalogGuide(rules: RenderRules): string;
111
+ /**
112
+ * The catalog as Markdown an agent reads before composing a surface. `themes: false` leaves themes out,
113
+ * for a surface that takes the theme of the page it is shown on.
114
+ */
115
+ export function renderCatalogGuide(rules: RenderRules, options?: { themes?: boolean }): string;
104
116
 
105
117
  /** A result as lines for a terminal or a tool reply. */
106
118
  export function formatRenderReport(result: RenderResult): string;