@casys/mcp-erpnext 2.2.0 → 2.2.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.
@@ -1,10 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Invoice Viewer - mcp-erpnext</title>
7
- <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const d of f.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function l(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();var ea={exports:{}},yo={},ta={exports:{}},oe={};/**
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Invoice Viewer - mcp-erpnext</title>
7
+ <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const d of f.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function l(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();var ea={exports:{}},yo={},ta={exports:{}},oe={};/**
8
8
  * @license React
9
9
  * react.production.min.js
10
10
  *
@@ -119,10 +119,10 @@ Boolean requesting whether a visible border and background is provided by the ho
119
119
  - omitted: host decides border`)});T({method:S("ui/request-display-mode"),params:T({mode:xo.describe("The display mode being requested.")})});var ES=T({mode:xo.describe("The display mode that was actually set. May differ from requested if not supported.")}).passthrough(),TS=le([S("model"),S("app")]).describe("Tool visibility scope - who can access the tool.");T({resourceUri:z().optional(),visibility:Y(TS).optional().describe(`Who can access this tool. Default: ["model", "app"]
120
120
  - "model": Tool visible to and callable by the agent
121
121
  - "app": Tool callable by the app from this server only`)});T({mimeTypes:Y(z()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});T({method:S("ui/download-file"),params:T({contents:Y(le([_p,wp])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.")})});T({method:S("ui/message"),params:T({role:S("user").describe('Message role, currently only "user" is supported.'),content:Y(Io).describe("Message content blocks (text, image, etc.).")})});T({method:S("ui/notifications/sandbox-resource-ready"),params:T({html:z().describe("HTML content to load into the inner iframe."),sandbox:z().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Ha.optional().describe("CSP configuration from resource metadata."),permissions:qa.optional().describe("Sandbox permissions from resource metadata.")})});var CS=T({method:S("ui/notifications/tool-result"),params:ss.describe("Standard MCP tool execution result.")}),zp=T({toolInfo:T({id:Eo.optional().describe("JSON-RPC id of the tools/call request."),tool:Ua.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:dS.optional().describe("Current color theme preference."),styles:SS.optional().describe("Style configuration for theming the app."),displayMode:xo.optional().describe("How the UI is currently displayed."),availableDisplayModes:Y(xo).optional().describe("Display modes the host supports."),containerDimensions:le([T({height:ie().describe("Fixed container height in pixels.")}),T({maxHeight:le([ie(),fa()]).optional().describe("Maximum container height in pixels.")})]).and(le([T({width:ie().describe("Fixed container width in pixels.")}),T({maxWidth:le([ie(),fa()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
122
- container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:z().optional().describe("User's language and region preference in BCP 47 format."),timeZone:z().optional().describe("User's timezone in IANA format."),userAgent:z().optional().describe("Host application identifier."),platform:le([S("web"),S("desktop"),S("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:T({touch:xe().optional().describe("Whether the device supports touch input."),hover:xe().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:T({top:ie().describe("Top safe area inset in pixels."),right:ie().describe("Right safe area inset in pixels."),bottom:ie().describe("Bottom safe area inset in pixels."),left:ie().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),PS=T({method:S("ui/notifications/host-context-changed"),params:zp.describe("Partial context update containing only changed fields.")});T({method:S("ui/update-model-context"),params:T({content:Y(Io).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:ye(z(),_e().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});T({method:S("ui/initialize"),params:T({appInfo:os.describe("App identification (name and version)."),appCapabilities:zS.describe("Features and capabilities this app provides."),protocolVersion:z().describe("Protocol version this app supports.")})});var RS=T({protocolVersion:z().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:os.describe("Host application identification and version."),hostCapabilities:xS.describe("Features and capabilities provided by the host."),hostContext:zp.describe("Rich context about the host environment.")}).passthrough();class NS extends lS{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(o,i={},l={autoResize:!0}){super(l),this._appInfo=o,this._capabilities=i,this.options=l,this.setRequestHandler(is,u=>(console.log("Received ping:",u.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(o){this.setNotificationHandler(vS,i=>o(i.params))}set ontoolinputpartial(o){this.setNotificationHandler(yS,i=>o(i.params))}set ontoolresult(o){this.setNotificationHandler(CS,i=>o(i.params))}set ontoolcancelled(o){this.setNotificationHandler(_S,i=>o(i.params))}set onhostcontextchanged(o){this.setNotificationHandler(PS,i=>{this._hostContext={...this._hostContext,...i.params},o(i.params)})}set onteardown(o){this.setRequestHandler(kS,(i,l)=>o(i.params,l))}set oncalltool(o){this.setRequestHandler(kp,(i,l)=>o(i.params,l))}set onlisttools(o){this.setRequestHandler(Sp,(i,l)=>o(i.params,l))}assertCapabilityForMethod(o){}assertRequestHandlerCapability(o){switch(o){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${o})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${o} registered`)}}assertNotificationCapability(o){}assertTaskCapability(o){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(o){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(o,i){if(typeof o=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${o}"). Did you mean: callServerTool({ name: "${o}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:o},ss,i)}async readServerResource(o,i){return await this.request({method:"resources/read",params:o},yp,i)}async listServerResources(o,i){return await this.request({method:"resources/list",params:o},vp,i)}sendMessage(o,i){return this.request({method:"ui/message",params:o},gS,i)}sendLog(o){return this.notification({method:"notifications/message",params:o})}updateModelContext(o,i){return this.request({method:"ui/update-model-context",params:o},Ca,i)}openLink(o,i){return this.request({method:"ui/open-link",params:o},mS,i)}sendOpenLink=this.openLink;downloadFile(o,i){return this.request({method:"ui/download-file",params:o},hS,i)}requestDisplayMode(o,i){return this.request({method:"ui/request-display-mode",params:o},ES,i)}sendSizeChanged(o){return this.notification({method:"ui/notifications/size-changed",params:o})}setupSizeChangedNotifications(){let o=!1,i=0,l=0,u=()=>{o||(o=!0,requestAnimationFrame(()=>{o=!1;let d=document.documentElement,m=d.style.width,v=d.style.height;d.style.width="fit-content",d.style.height="max-content";let k=d.getBoundingClientRect();d.style.width=m,d.style.height=v;let C=window.innerWidth-d.clientWidth,P=Math.ceil(k.width+C),O=Math.ceil(k.height);(P!==i||O!==l)&&(i=P,l=O,this.sendSizeChanged({width:P,height:O}))}))};u();let f=new ResizeObserver(u);return f.observe(document.documentElement),f.observe(document.body),()=>f.disconnect()}async connect(o=new cS(window.parent,window.parent),i){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");await super.connect(o);try{let l=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:aS}},RS,i);if(l===void 0)throw Error(`Server sent invalid initialize result: ${l}`);this._hostCapabilities=l.hostCapabilities,this._hostInfo=l.hostInfo,this._hostContext=l.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(l){throw this.close(),l}}}function Fe(n){return`var(${n})`}const b={bg:{surface:Fe("--bg-surface"),elevated:Fe("--bg-elevated"),hover:Fe("--bg-hover")},text:{primary:Fe("--text-primary"),secondary:Fe("--text-secondary"),muted:Fe("--text-muted"),faint:Fe("--text-faint")},accent:Fe("--accent"),accentDim:Fe("--accent-dim"),border:Fe("--border"),borderSubtle:Fe("--border-subtle"),success:Fe("--success"),successDim:Fe("--success-dim"),error:Fe("--error"),errorDim:Fe("--error-dim"),warning:Fe("--warning"),warningDim:Fe("--warning-dim"),info:Fe("--info"),infoDim:Fe("--info-dim")},Ge={sans:Fe("--font-sans"),mono:Fe("--font-mono")},Dt={card:{background:b.bg.surface,border:`1px solid ${b.border}`,borderRadius:"8px",padding:"16px"},badge:(n,o)=>({display:"inline-flex",alignItems:"center",padding:"2px 8px",fontSize:"11px",fontWeight:600,borderRadius:"4px",color:n,background:o,letterSpacing:"0.02em"}),input:{background:b.bg.elevated,border:`1px solid ${b.border}`,borderRadius:"6px",padding:"6px 12px",fontSize:"13px",color:b.text.primary,outline:"none",transition:"border-color 0.15s",width:"100%",fontFamily:Ge.sans},button:{background:b.bg.elevated,border:`1px solid ${b.border}`,borderRadius:"6px",padding:"6px 14px",fontSize:"12px",color:b.text.secondary,cursor:"pointer",transition:"all 0.15s",fontFamily:Ge.sans,whiteSpace:"nowrap"},buttonActive:{background:b.accentDim,borderColor:b.accent,color:b.accent},tableHeader:{padding:"8px 12px",textAlign:"left",fontSize:"11px",fontWeight:600,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",borderBottom:`1px solid ${b.border}`,cursor:"pointer",userSelect:"none",whiteSpace:"nowrap",transition:"color 0.15s"},tableCell:{padding:"8px 12px",fontSize:"13px",borderBottom:`1px solid ${b.borderSubtle}`,color:b.text.primary},mono:{fontFamily:Ge.mono,fontSize:"12px"}};function kr(n,o="USD"){return n.toLocaleString("en-US",{style:"currency",currency:o,minimumFractionDigits:2,maximumFractionDigits:2})}function IS(){return N.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[N.jsx("rect",{x:"1",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.9"}),N.jsx("rect",{x:"9",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),N.jsx("rect",{x:"1",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),N.jsx("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.35"})]})}function la(){const n={display:"flex",alignItems:"center",gap:7,padding:"0 14px",height:30,background:b.bg.surface,borderBottom:`1px solid ${b.border}`,flexShrink:0},o={fontFamily:Ge.sans,fontSize:11,fontWeight:700,letterSpacing:"0.08em",textTransform:"uppercase",color:b.accent},i={width:3,height:3,borderRadius:"50%",background:b.text.faint,marginLeft:2,marginRight:2,flexShrink:0},l={fontFamily:Ge.sans,fontSize:10,color:b.text.muted,letterSpacing:"0.03em"};return N.jsxs("div",{style:n,children:[N.jsx("div",{style:{color:b.accent},children:N.jsx(IS,{})}),N.jsx("span",{style:o,children:"ERPNext"}),N.jsx("div",{style:i}),N.jsx("span",{style:l,children:"gestion ERP"})]})}function aa(){const n={display:"flex",justifyContent:"flex-end",alignItems:"center",padding:"6px 16px 8px",borderTop:`1px solid ${b.borderSubtle}`,marginTop:8},o={fontFamily:Ge.sans,fontSize:10,color:b.text.faint,letterSpacing:"0.04em"};return N.jsx("div",{style:n,children:N.jsx("span",{style:o,children:"Casys AI"})})}const yf={success:{color:b.success,bg:b.successDim},error:{color:b.error,bg:b.errorDim},info:{color:b.info,bg:b.infoDim},default:{color:b.text.secondary,bg:b.bg.elevated}};function Er({label:n,variant:o="default",disabled:i,loading:l,confirm:u,onClick:f}){const[d,m]=Le.useState(!1),v=Le.useRef();Le.useEffect(()=>()=>clearTimeout(v.current),[]);const k=yf[o]??yf.default;return N.jsx("button",{onClick:()=>{if(u&&!d){m(!0),clearTimeout(v.current),v.current=setTimeout(()=>m(!1),4e3);return}m(!1),f()},disabled:i||l,style:{...Dt.button,background:k.bg,color:k.color,borderColor:k.color,opacity:i||l?.5:1,fontSize:11,padding:"4px 10px"},children:l?"…":d?"Confirm?":n})}function OS(n,o={}){return!n.request||n.visibilityState!=="visible"||n.refreshInFlight?!1:o.ignoreInterval?!0:n.now-n.lastRefreshStartedAt>=n.minIntervalMs}function jS(n,o){return n?.refreshRequest??o}function $S(n){return n instanceof Error&&/timed? out/i.test(n.message)?"Refresh timed out":"Refresh failed"}function wo(n){return n.structuredContent?JSON.stringify(n.structuredContent):n.content?.find(o=>o.type==="text")?.text??null}const bS={Paid:{color:b.success,bg:b.successDim},Submitted:{color:b.info,bg:b.infoDim},Draft:{color:b.text.muted,bg:b.bg.elevated},Cancelled:{color:b.error,bg:b.errorDim},Overdue:{color:b.error,bg:b.errorDim},Unpaid:{color:b.warning,bg:b.warningDim},"Partly Paid":{color:b.warning,bg:b.warningDim},Return:{color:b.text.muted,bg:b.bg.elevated}};function MS({status:n}){const o=bS[n]??{color:b.text.secondary,bg:b.bg.elevated};return N.jsx("span",{style:Dt.badge(o.color,o.bg),children:n})}function Wi({label:n,value:o,bold:i}){return N.jsxs("div",{style:{padding:"4px 0"},children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:2},children:n}),N.jsx("div",{style:{fontSize:i?15:13,fontWeight:i?600:500,color:b.text.primary,fontFamily:i?Ge.mono:Ge.sans},children:o??"—"})]})}const _f=1e4;function LS({app:n,itemCode:o,onClose:i}){const[l,u]=Le.useState(null),[f,d]=Le.useState(null),[m,v]=Le.useState(!0),[k,C]=Le.useState(null);return Le.useEffect(()=>{let P=!1;return(async()=>{try{const[O,A]=await Promise.all([n.callServerTool({name:"erpnext_item_get",arguments:{name:o}},{timeout:_f}),n.callServerTool({name:"erpnext_stock_balance",arguments:{item_code:o}},{timeout:_f})]);if(P)return;if(!O.isError){const X=wo(O);if(X){const Q=JSON.parse(X);u(Q.data??Q)}}if(!A.isError){const X=wo(A);if(X){const Q=JSON.parse(X);d(Q.data??[])}}O.isError&&A.isError&&C("Failed to load item details")}catch(O){P||C(O instanceof Error?O.message:"Failed to load item details")}finally{P||v(!1)}})(),()=>{P=!0}},[o]),m?N.jsx("div",{style:{padding:16,background:b.bg.surface,borderTop:`2px solid ${b.accent}`},children:[1,2].map(P=>N.jsx("div",{className:"skeleton",style:{height:14,width:`${30+P*15}%`,marginBottom:8}},P))}):N.jsxs("div",{style:{padding:16,background:b.bg.surface,borderTop:`2px solid ${b.accent}`},children:[N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10},children:[N.jsx("span",{style:{fontSize:14,fontWeight:600,color:b.text.primary,fontFamily:Ge.mono},children:o}),N.jsx("button",{onClick:i,style:{...Dt.button,padding:"2px 8px",fontSize:11},children:"✕"})]}),k&&N.jsx("div",{style:{fontSize:11,color:b.error,marginBottom:8},children:k}),l&&N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(140px, 1fr))",gap:6,marginBottom:10},children:[l.item_name&&N.jsx(Wi,{label:"Name",value:String(l.item_name)}),l.item_group&&N.jsx(Wi,{label:"Group",value:String(l.item_group)}),l.stock_uom&&N.jsx(Wi,{label:"UOM",value:String(l.stock_uom)}),l.standard_rate!=null&&N.jsx(Wi,{label:"Std Rate",value:String(l.standard_rate),bold:!0})]}),f&&f.length>0&&N.jsxs("div",{style:{marginBottom:10},children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:6},children:"Stock"}),f.slice(0,5).map((P,O)=>N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"4px 0",borderBottom:`1px solid ${b.borderSubtle}`},children:[N.jsx("span",{style:{fontSize:12,color:b.text.secondary},children:String(P.warehouse??"—")}),N.jsx("span",{style:{fontSize:12,fontFamily:Ge.mono,fontWeight:600,color:Number(P.actual_qty??0)>0?b.success:b.error},children:String(P.actual_qty??0)})]},O))]}),N.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",paddingTop:8,borderTop:`1px solid ${b.border}`},children:[N.jsx(Er,{label:"Full stock view",onClick:async()=>{try{await n.sendMessage({role:"user",content:[{type:"text",text:`Show stock balance for item ${o}`}]})}catch{}}}),N.jsx(Er,{label:"Item details",onClick:async()=>{try{await n.sendMessage({role:"user",content:[{type:"text",text:`Show me the full details of Item ${o}`}]})}catch{}}})]})]})}const nn=new NS({name:"Invoice Viewer",version:"3.0.0"}),DS=15e3,wf=1e4;function ZS(){return N.jsx("div",{style:{padding:24},children:[1,2,3,4,5].map(n=>N.jsx("div",{className:"skeleton",style:{height:n===1?32:20,width:`${40+n*10}%`,marginBottom:8}},n))})}function AS(){return N.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"48px 24px",color:b.text.muted,gap:12,flex:1},children:[N.jsxs("svg",{width:"56",height:"56",viewBox:"0 0 56 56",fill:"none",style:{opacity:.35},children:[N.jsx("rect",{x:"12",y:"6",width:"32",height:"44",rx:"3",stroke:"currentColor",strokeWidth:"2"}),N.jsx("path",{d:"M20 16h16M20 22h12M20 28h14M20 34h8",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",opacity:"0.6"})]}),N.jsx("div",{style:{fontSize:13},children:"No invoice data"})]})}function Sf({type:n,message:o,onDismiss:i}){const l=n==="error";return N.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",marginBottom:12,borderRadius:8,fontSize:12,background:l?b.errorDim:b.successDim,color:l?b.error:b.success,border:`1px solid ${l?b.error+"30":b.success+"30"}`},children:[N.jsx("span",{children:o}),i&&N.jsx("button",{onClick:i,style:{background:"none",border:"none",color:"inherit",cursor:"pointer",fontSize:14,padding:"0 4px"},children:"✕"})]})}function ua({label:n,value:o,bold:i}){return N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"4px 0",fontSize:i?14:13},children:[N.jsx("span",{style:{color:b.text.secondary},children:n}),N.jsx("span",{style:{fontFamily:Ge.mono,fontWeight:i?700:400,color:i?b.accent:b.text.primary},children:o})]})}function FS(){const[n,o]=Le.useState(null),[i,l]=Le.useState(!0),[u,f]=Le.useState(!1),[d,m]=Le.useState(null),[v,k]=Le.useState(null),[C,P]=Le.useState(null),[O,A]=Le.useState(null),X=Le.useRef(null),Q=Le.useRef(null),re=Le.useRef(!1),Ye=Le.useRef(0);function pe(Z){X.current=Z,o(Z)}function se(Z){if(Z.isError){const _=wo(Z);return m(_??"Tool returned an error"),l(!1),!1}const D=wo(Z);if(!D)return!1;try{const _=JSON.parse(D);return Q.current=jS(_,Q.current),pe(_.data??_),m(null),l(!1),!0}catch{return m("Failed to parse invoice payload"),l(!1),!1}}async function te(Z={}){const D=Q.current;if(OS({request:D,visibilityState:typeof document>"u"?"visible":document.visibilityState,refreshInFlight:re.current,now:Date.now(),lastRefreshStartedAt:Ye.current,minIntervalMs:DS},Z)&&!(!D||!nn.getHostCapabilities()?.serverTools)){re.current=!0,Ye.current=Date.now(),f(!0);try{const _=await nn.callServerTool({name:D.toolName,arguments:D.arguments},{timeout:wf});_.isError?m("Refresh failed"):se(_)}catch(_){m($S(_))}finally{re.current=!1,f(!1)}}}async function we(Z,D,_,I){if(nn.getHostCapabilities()?.serverTools){k(Z),P(null);try{const ee=await nn.callServerTool({name:D,arguments:_},{timeout:wf});if(ee.isError){const ne=wo(ee);P(ne??"Action failed")}else P(I),setTimeout(()=>void te({ignoreInterval:!0}),1500)}catch{P("Action failed")}finally{k(null)}}}async function qe(Z,D){k(Z);try{await nn.sendMessage({role:"user",content:[{type:"text",text:D}]})}catch{}k(null)}if(Le.useEffect(()=>{nn.connect().catch(()=>{}),nn.ontoolresult=Z=>{se(Z)},nn.ontoolinputpartial=()=>{X.current||l(!0)}},[]),Le.useEffect(()=>{const Z=()=>void te({ignoreInterval:!0}),D=()=>{document.visibilityState==="visible"&&te({ignoreInterval:!0})};return window.addEventListener("focus",Z),document.addEventListener("visibilitychange",D),()=>{window.removeEventListener("focus",Z),document.removeEventListener("visibilitychange",D)}},[]),Le.useEffect(()=>{A(null)},[n?.name]),i)return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsx(ZS,{}),N.jsx(aa,{})]});if(!n)return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsx(AS,{}),N.jsx(aa,{})]});const Oe=n.currency??"USD",We=!!n.customer,xt=We?"Sales Invoice":"Purchase Invoice",Ut=n.customer_name??n.customer??n.supplier_name??n.supplier??"—",Kt=n.outstanding_amount??0,pt=Kt<=0,Xe=n.items??[],mt=n.net_total??Xe.reduce((Z,D)=>Z+D.amount,0),zt=n.total_taxes_and_charges??n.grand_total-mt,it=n.status==="Draft"||n.docstatus===0,Pe=n.docstatus===1,F=nn.getHostCapabilities()?.serverTools;return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsxs("div",{style:{padding:16,fontFamily:Ge.sans,flex:1,maxWidth:720},children:[N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:16,flexWrap:"wrap",gap:8},children:[N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:11,fontWeight:600,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:4},children:xt}),N.jsx("div",{style:{fontSize:20,fontWeight:700,color:b.text.primary,fontFamily:Ge.mono},children:n.name}),N.jsxs("div",{style:{display:"flex",gap:8,marginTop:6,alignItems:"center",flexWrap:"wrap"},children:[N.jsx(MS,{status:n.status}),n.company&&N.jsx("span",{style:{fontSize:11,color:b.text.faint},children:n.company})]})]}),N.jsx("button",{onClick:()=>void te({ignoreInterval:!0}),disabled:u,style:Dt.button,children:u?"…":"Refresh"})]}),d&&N.jsx(Sf,{type:"error",message:d,onDismiss:()=>m(null)}),!d&&C&&N.jsx(Sf,{type:"success",message:C}),N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16,marginBottom:16,borderBottom:`1px solid ${b.border}`,paddingBottom:16},children:[N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:4},children:We?"Customer":"Supplier"}),N.jsx("div",{style:{fontSize:14,fontWeight:600,color:b.text.primary},children:Ut}),n.contact_email&&N.jsx("div",{style:{fontSize:11,color:b.text.secondary},children:n.contact_email})]}),N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:4},children:"Outstanding"}),N.jsx("div",{style:{fontSize:14,fontWeight:600,color:pt?b.success:b.error,fontFamily:Ge.mono},children:kr(Kt,Oe)}),N.jsx("div",{style:{fontSize:11,color:pt?b.success:b.error},children:pt?"Paid":"Unpaid"})]})]}),N.jsxs("div",{style:{display:"flex",gap:24,marginBottom:16,fontSize:12},children:[N.jsxs("span",{children:[N.jsx("span",{style:{color:b.text.muted},children:"Date "}),N.jsx("span",{style:{color:b.text.primary,fontWeight:500},children:n.posting_date})]}),n.due_date&&N.jsxs("span",{children:[N.jsx("span",{style:{color:b.text.muted},children:"Due "}),N.jsx("span",{style:{color:b.text.primary,fontWeight:500},children:n.due_date})]})]}),Xe.length>0&&N.jsx("div",{style:{border:`1px solid ${b.border}`,borderRadius:12,overflowX:"auto",marginBottom:16},children:N.jsxs("table",{style:{width:"100%",borderCollapse:"collapse"},children:[N.jsx("thead",{children:N.jsxs("tr",{children:[N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface},children:"Item"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Qty"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Rate"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Amount"})]})}),N.jsx("tbody",{children:Xe.map((Z,D)=>{const _=O===D;return N.jsx("tr",{children:N.jsxs("td",{colSpan:4,style:{padding:0},children:[N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"35% 15% 25% 25%",cursor:F?"pointer":"default",transition:"background 0.1s",background:_?b.bg.hover:"transparent"},onClick:F?()=>A(_?null:D):void 0,onMouseEnter:I=>{_||(I.currentTarget.style.background=b.bg.hover)},onMouseLeave:I=>{_||(I.currentTarget.style.background="transparent")},children:[N.jsxs("div",{style:Dt.tableCell,children:[N.jsx("div",{style:{fontWeight:500,color:b.text.primary},children:Z.item_name??Z.item_code}),Z.item_name&&N.jsx("div",{style:{fontSize:11,color:b.text.faint,fontFamily:Ge.mono},children:Z.item_code})]}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono},children:Z.qty}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono,color:b.text.secondary},children:kr(Z.rate,Oe)}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono,fontWeight:500},children:kr(Z.amount,Oe)})]}),_&&N.jsx(LS,{app:nn,itemCode:Z.item_code,onClose:()=>A(null)})]})},D)})})]})}),N.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:16},children:N.jsxs("div",{style:{minWidth:220,borderTop:`1px solid ${b.border}`,paddingTop:8},children:[N.jsx(ua,{label:"Subtotal",value:kr(mt,Oe)}),zt!==0&&N.jsx(ua,{label:"Taxes",value:kr(zt,Oe)}),N.jsx(ua,{label:"Grand Total",value:kr(n.grand_total,Oe),bold:!0})]})}),F&&N.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap",padding:"12px 0",borderTop:`1px solid ${b.border}`},children:[it&&N.jsx(Er,{label:"Submit",variant:"success",confirm:!0,loading:v==="submit",onClick:()=>we("submit","erpnext_doc_submit",{doctype:xt,name:n.name},"Submitted")}),Pe&&N.jsx(Er,{label:"Cancel",variant:"error",confirm:!0,loading:v==="cancel",onClick:()=>we("cancel","erpnext_doc_cancel",{doctype:xt,name:n.name},"Cancelled")}),N.jsx(Er,{label:"Payments",loading:v==="nav_payments",onClick:()=>qe("nav_payments",`Show payment entries for ${xt} ${n.name}`)}),(n.customer??n.supplier)&&N.jsx(Er,{label:We?"Customer invoices":"Supplier invoices",loading:v==="nav_party",onClick:()=>{const Z=n.customer??n.supplier;qe("nav_party",`Show all ${We?"sales":"purchase"} invoices for ${We?"customer":"supplier"} ${Z}`)}})]})]}),N.jsx(aa,{})]})}Rh.createRoot(document.getElementById("app")).render(N.jsx(FS,{}));</script>
123
- <style rel="stylesheet" crossorigin>:root{--accent: #0089FF;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
- </head>
125
- <body>
126
- <div id="app"></div>
127
- </body>
122
+ container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:z().optional().describe("User's language and region preference in BCP 47 format."),timeZone:z().optional().describe("User's timezone in IANA format."),userAgent:z().optional().describe("Host application identifier."),platform:le([S("web"),S("desktop"),S("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:T({touch:xe().optional().describe("Whether the device supports touch input."),hover:xe().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:T({top:ie().describe("Top safe area inset in pixels."),right:ie().describe("Right safe area inset in pixels."),bottom:ie().describe("Bottom safe area inset in pixels."),left:ie().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),PS=T({method:S("ui/notifications/host-context-changed"),params:zp.describe("Partial context update containing only changed fields.")});T({method:S("ui/update-model-context"),params:T({content:Y(Io).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:ye(z(),_e().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});T({method:S("ui/initialize"),params:T({appInfo:os.describe("App identification (name and version)."),appCapabilities:zS.describe("Features and capabilities this app provides."),protocolVersion:z().describe("Protocol version this app supports.")})});var RS=T({protocolVersion:z().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:os.describe("Host application identification and version."),hostCapabilities:xS.describe("Features and capabilities provided by the host."),hostContext:zp.describe("Rich context about the host environment.")}).passthrough();class NS extends lS{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(o,i={},l={autoResize:!0}){super(l),this._appInfo=o,this._capabilities=i,this.options=l,this.setRequestHandler(is,u=>(console.log("Received ping:",u.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(o){this.setNotificationHandler(vS,i=>o(i.params))}set ontoolinputpartial(o){this.setNotificationHandler(yS,i=>o(i.params))}set ontoolresult(o){this.setNotificationHandler(CS,i=>o(i.params))}set ontoolcancelled(o){this.setNotificationHandler(_S,i=>o(i.params))}set onhostcontextchanged(o){this.setNotificationHandler(PS,i=>{this._hostContext={...this._hostContext,...i.params},o(i.params)})}set onteardown(o){this.setRequestHandler(kS,(i,l)=>o(i.params,l))}set oncalltool(o){this.setRequestHandler(kp,(i,l)=>o(i.params,l))}set onlisttools(o){this.setRequestHandler(Sp,(i,l)=>o(i.params,l))}assertCapabilityForMethod(o){}assertRequestHandlerCapability(o){switch(o){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${o})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${o} registered`)}}assertNotificationCapability(o){}assertTaskCapability(o){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(o){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(o,i){if(typeof o=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${o}"). Did you mean: callServerTool({ name: "${o}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:o},ss,i)}async readServerResource(o,i){return await this.request({method:"resources/read",params:o},yp,i)}async listServerResources(o,i){return await this.request({method:"resources/list",params:o},vp,i)}sendMessage(o,i){return this.request({method:"ui/message",params:o},gS,i)}sendLog(o){return this.notification({method:"notifications/message",params:o})}updateModelContext(o,i){return this.request({method:"ui/update-model-context",params:o},Ca,i)}openLink(o,i){return this.request({method:"ui/open-link",params:o},mS,i)}sendOpenLink=this.openLink;downloadFile(o,i){return this.request({method:"ui/download-file",params:o},hS,i)}requestDisplayMode(o,i){return this.request({method:"ui/request-display-mode",params:o},ES,i)}sendSizeChanged(o){return this.notification({method:"ui/notifications/size-changed",params:o})}setupSizeChangedNotifications(){let o=!1,i=0,l=0,u=()=>{o||(o=!0,requestAnimationFrame(()=>{o=!1;let d=document.documentElement,m=d.style.width,v=d.style.height;d.style.width="fit-content",d.style.height="max-content";let k=d.getBoundingClientRect();d.style.width=m,d.style.height=v;let C=window.innerWidth-d.clientWidth,P=Math.ceil(k.width+C),O=Math.ceil(k.height);(P!==i||O!==l)&&(i=P,l=O,this.sendSizeChanged({width:P,height:O}))}))};u();let f=new ResizeObserver(u);return f.observe(document.documentElement),f.observe(document.body),()=>f.disconnect()}async connect(o=new cS(window.parent,window.parent),i){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");await super.connect(o);try{let l=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:aS}},RS,i);if(l===void 0)throw Error(`Server sent invalid initialize result: ${l}`);this._hostCapabilities=l.hostCapabilities,this._hostInfo=l.hostInfo,this._hostContext=l.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(l){throw this.close(),l}}}function Fe(n){return`var(${n})`}const b={bg:{surface:Fe("--bg-surface"),elevated:Fe("--bg-elevated"),hover:Fe("--bg-hover")},text:{primary:Fe("--text-primary"),secondary:Fe("--text-secondary"),muted:Fe("--text-muted"),faint:Fe("--text-faint")},accent:Fe("--accent"),accentDim:Fe("--accent-dim"),border:Fe("--border"),borderSubtle:Fe("--border-subtle"),success:Fe("--success"),successDim:Fe("--success-dim"),error:Fe("--error"),errorDim:Fe("--error-dim"),warning:Fe("--warning"),warningDim:Fe("--warning-dim"),info:Fe("--info"),infoDim:Fe("--info-dim")},Ge={sans:Fe("--font-sans"),mono:Fe("--font-mono")},Dt={card:{background:b.bg.surface,border:`1px solid ${b.border}`,borderRadius:"8px",padding:"16px"},badge:(n,o)=>({display:"inline-flex",alignItems:"center",padding:"2px 8px",fontSize:"11px",fontWeight:600,borderRadius:"4px",color:n,background:o,letterSpacing:"0.02em"}),input:{background:b.bg.elevated,border:`1px solid ${b.border}`,borderRadius:"6px",padding:"6px 12px",fontSize:"13px",color:b.text.primary,outline:"none",transition:"border-color 0.15s",width:"100%",fontFamily:Ge.sans},button:{background:b.bg.elevated,border:`1px solid ${b.border}`,borderRadius:"6px",padding:"6px 14px",fontSize:"12px",color:b.text.secondary,cursor:"pointer",transition:"all 0.15s",fontFamily:Ge.sans,whiteSpace:"nowrap"},buttonActive:{background:b.accentDim,borderColor:b.accent,color:b.accent},tableHeader:{padding:"8px 12px",textAlign:"left",fontSize:"11px",fontWeight:600,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",borderBottom:`1px solid ${b.border}`,cursor:"pointer",userSelect:"none",whiteSpace:"nowrap",transition:"color 0.15s"},tableCell:{padding:"8px 12px",fontSize:"13px",borderBottom:`1px solid ${b.borderSubtle}`,color:b.text.primary},mono:{fontFamily:Ge.mono,fontSize:"12px"}};function kr(n,o="USD"){return n.toLocaleString("en-US",{style:"currency",currency:o,minimumFractionDigits:2,maximumFractionDigits:2})}function IS(){return N.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[N.jsx("rect",{x:"1",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.9"}),N.jsx("rect",{x:"9",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),N.jsx("rect",{x:"1",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),N.jsx("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.35"})]})}function la(){const n={display:"flex",alignItems:"center",gap:7,padding:"0 14px",height:30,background:b.bg.surface,borderBottom:`1px solid ${b.border}`,flexShrink:0},o={fontFamily:Ge.sans,fontSize:11,fontWeight:700,letterSpacing:"0.08em",textTransform:"uppercase",color:b.accent},i={width:3,height:3,borderRadius:"50%",background:b.text.faint,marginLeft:2,marginRight:2,flexShrink:0},l={fontFamily:Ge.sans,fontSize:10,color:b.text.muted,letterSpacing:"0.03em"};return N.jsxs("div",{style:n,children:[N.jsx("div",{style:{color:b.accent},children:N.jsx(IS,{})}),N.jsx("span",{style:o,children:"ERPNext"}),N.jsx("div",{style:i}),N.jsx("span",{style:l,children:"gestion ERP"})]})}function aa(){const n={display:"flex",justifyContent:"flex-end",alignItems:"center",padding:"6px 16px 8px",borderTop:`1px solid ${b.borderSubtle}`,marginTop:8},o={fontFamily:Ge.sans,fontSize:10,color:b.text.faint,letterSpacing:"0.04em"};return N.jsx("div",{style:n,children:N.jsx("span",{style:o,children:"Casys AI"})})}const yf={success:{color:b.success,bg:b.successDim},error:{color:b.error,bg:b.errorDim},info:{color:b.info,bg:b.infoDim},default:{color:b.text.secondary,bg:b.bg.elevated}};function Er({label:n,variant:o="default",disabled:i,loading:l,confirm:u,onClick:f}){const[d,m]=Le.useState(!1),v=Le.useRef();Le.useEffect(()=>()=>clearTimeout(v.current),[]);const k=yf[o]??yf.default;return N.jsx("button",{onClick:()=>{if(u&&!d){m(!0),clearTimeout(v.current),v.current=setTimeout(()=>m(!1),4e3);return}m(!1),f()},disabled:i||l,style:{...Dt.button,background:k.bg,color:k.color,borderColor:k.color,opacity:i||l?.5:1,fontSize:11,padding:"4px 10px"},children:l?"…":d?"Confirm?":n})}function OS(n,o={}){return!n.request||n.visibilityState!=="visible"||n.refreshInFlight?!1:o.ignoreInterval?!0:n.now-n.lastRefreshStartedAt>=n.minIntervalMs}function jS(n,o){return n?.refreshRequest??o}function $S(n){return n instanceof Error&&/timed? out/i.test(n.message)?"Refresh timed out":"Refresh failed"}function wo(n){return n.structuredContent?JSON.stringify(n.structuredContent):n.content?.find(o=>o.type==="text")?.text??null}const bS={Paid:{color:b.success,bg:b.successDim},Submitted:{color:b.info,bg:b.infoDim},Draft:{color:b.text.muted,bg:b.bg.elevated},Cancelled:{color:b.error,bg:b.errorDim},Overdue:{color:b.error,bg:b.errorDim},Unpaid:{color:b.warning,bg:b.warningDim},"Partly Paid":{color:b.warning,bg:b.warningDim},Return:{color:b.text.muted,bg:b.bg.elevated}};function MS({status:n}){const o=bS[n]??{color:b.text.secondary,bg:b.bg.elevated};return N.jsx("span",{style:Dt.badge(o.color,o.bg),children:n})}function Wi({label:n,value:o,bold:i}){return N.jsxs("div",{style:{padding:"4px 0"},children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:2},children:n}),N.jsx("div",{style:{fontSize:i?15:13,fontWeight:i?600:500,color:b.text.primary,fontFamily:i?Ge.mono:Ge.sans},children:o??"—"})]})}const _f=1e4;function LS({app:n,itemCode:o,onClose:i}){const[l,u]=Le.useState(null),[f,d]=Le.useState(null),[m,v]=Le.useState(!0),[k,C]=Le.useState(null);return Le.useEffect(()=>{let P=!1;return(async()=>{try{const[O,A]=await Promise.all([n.callServerTool({name:"erpnext_item_get",arguments:{name:o}},{timeout:_f}),n.callServerTool({name:"erpnext_stock_balance",arguments:{item_code:o}},{timeout:_f})]);if(P)return;if(!O.isError){const X=wo(O);if(X){const Q=JSON.parse(X);u(Q.data??Q)}}if(!A.isError){const X=wo(A);if(X){const Q=JSON.parse(X);d(Q.data??[])}}O.isError&&A.isError&&C("Failed to load item details")}catch(O){P||C(O instanceof Error?O.message:"Failed to load item details")}finally{P||v(!1)}})(),()=>{P=!0}},[o]),m?N.jsx("div",{style:{padding:16,background:b.bg.surface,borderTop:`2px solid ${b.accent}`},children:[1,2].map(P=>N.jsx("div",{className:"skeleton",style:{height:14,width:`${30+P*15}%`,marginBottom:8}},P))}):N.jsxs("div",{style:{padding:16,background:b.bg.surface,borderTop:`2px solid ${b.accent}`},children:[N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:10},children:[N.jsx("span",{style:{fontSize:14,fontWeight:600,color:b.text.primary,fontFamily:Ge.mono},children:o}),N.jsx("button",{onClick:i,style:{...Dt.button,padding:"2px 8px",fontSize:11},children:"✕"})]}),k&&N.jsx("div",{style:{fontSize:11,color:b.error,marginBottom:8},children:k}),l&&N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(140px, 1fr))",gap:6,marginBottom:10},children:[l.item_name&&N.jsx(Wi,{label:"Name",value:String(l.item_name)}),l.item_group&&N.jsx(Wi,{label:"Group",value:String(l.item_group)}),l.stock_uom&&N.jsx(Wi,{label:"UOM",value:String(l.stock_uom)}),l.standard_rate!=null&&N.jsx(Wi,{label:"Std Rate",value:String(l.standard_rate),bold:!0})]}),f&&f.length>0&&N.jsxs("div",{style:{marginBottom:10},children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.04em",marginBottom:6},children:"Stock"}),f.slice(0,5).map((P,O)=>N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"4px 0",borderBottom:`1px solid ${b.borderSubtle}`},children:[N.jsx("span",{style:{fontSize:12,color:b.text.secondary},children:String(P.warehouse??"—")}),N.jsx("span",{style:{fontSize:12,fontFamily:Ge.mono,fontWeight:600,color:Number(P.actual_qty??0)>0?b.success:b.error},children:String(P.actual_qty??0)})]},O))]}),N.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",paddingTop:8,borderTop:`1px solid ${b.border}`},children:[N.jsx(Er,{label:"Full stock view",onClick:async()=>{try{await n.sendMessage({role:"user",content:[{type:"text",text:`Show stock balance for item ${o}`}]})}catch{}}}),N.jsx(Er,{label:"Item details",onClick:async()=>{try{await n.sendMessage({role:"user",content:[{type:"text",text:`Show me the full details of Item ${o}`}]})}catch{}}})]})]})}const nn=new NS({name:"Invoice Viewer",version:"3.0.0"}),DS=15e3,wf=1e4;function ZS(){return N.jsx("div",{style:{padding:24},children:[1,2,3,4,5].map(n=>N.jsx("div",{className:"skeleton",style:{height:n===1?32:20,width:`${40+n*10}%`,marginBottom:8}},n))})}function AS(){return N.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"48px 24px",color:b.text.muted,gap:12,flex:1},children:[N.jsxs("svg",{width:"56",height:"56",viewBox:"0 0 56 56",fill:"none",style:{opacity:.35},children:[N.jsx("rect",{x:"12",y:"6",width:"32",height:"44",rx:"3",stroke:"currentColor",strokeWidth:"2"}),N.jsx("path",{d:"M20 16h16M20 22h12M20 28h14M20 34h8",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",opacity:"0.6"})]}),N.jsx("div",{style:{fontSize:13},children:"No invoice data"})]})}function Sf({type:n,message:o,onDismiss:i}){const l=n==="error";return N.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",marginBottom:12,borderRadius:8,fontSize:12,background:l?b.errorDim:b.successDim,color:l?b.error:b.success,border:`1px solid ${l?b.error+"30":b.success+"30"}`},children:[N.jsx("span",{children:o}),i&&N.jsx("button",{onClick:i,style:{background:"none",border:"none",color:"inherit",cursor:"pointer",fontSize:14,padding:"0 4px"},children:"✕"})]})}function ua({label:n,value:o,bold:i}){return N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",padding:"4px 0",fontSize:i?14:13},children:[N.jsx("span",{style:{color:b.text.secondary},children:n}),N.jsx("span",{style:{fontFamily:Ge.mono,fontWeight:i?700:400,color:i?b.accent:b.text.primary},children:o})]})}function FS(){const[n,o]=Le.useState(null),[i,l]=Le.useState(!0),[u,f]=Le.useState(!1),[d,m]=Le.useState(null),[v,k]=Le.useState(null),[C,P]=Le.useState(null),[O,A]=Le.useState(null),X=Le.useRef(null),Q=Le.useRef(null),re=Le.useRef(!1),Ye=Le.useRef(0);function pe(Z){X.current=Z,o(Z)}function se(Z){if(Z.isError){const _=wo(Z);return m(_??"Tool returned an error"),l(!1),!1}const D=wo(Z);if(!D)return!1;try{const _=JSON.parse(D);return Q.current=jS(_,Q.current),pe(_.data??_),m(null),l(!1),!0}catch{return m("Failed to parse invoice payload"),l(!1),!1}}async function te(Z={}){const D=Q.current;if(OS({request:D,visibilityState:typeof document>"u"?"visible":document.visibilityState,refreshInFlight:re.current,now:Date.now(),lastRefreshStartedAt:Ye.current,minIntervalMs:DS},Z)&&!(!D||!nn.getHostCapabilities()?.serverTools)){re.current=!0,Ye.current=Date.now(),f(!0);try{const _=await nn.callServerTool({name:D.toolName,arguments:D.arguments},{timeout:wf});_.isError?m("Refresh failed"):se(_)}catch(_){m($S(_))}finally{re.current=!1,f(!1)}}}async function we(Z,D,_,I){if(nn.getHostCapabilities()?.serverTools){k(Z),P(null);try{const ee=await nn.callServerTool({name:D,arguments:_},{timeout:wf});if(ee.isError){const ne=wo(ee);P(ne??"Action failed")}else P(I),setTimeout(()=>void te({ignoreInterval:!0}),1500)}catch{P("Action failed")}finally{k(null)}}}async function qe(Z,D){k(Z);try{await nn.sendMessage({role:"user",content:[{type:"text",text:D}]})}catch{}k(null)}if(Le.useEffect(()=>{nn.connect().catch(()=>{}),nn.ontoolresult=Z=>{se(Z)},nn.ontoolinputpartial=()=>{X.current||l(!0)}},[]),Le.useEffect(()=>{const Z=()=>void te({ignoreInterval:!0}),D=()=>{document.visibilityState==="visible"&&te({ignoreInterval:!0})};return window.addEventListener("focus",Z),document.addEventListener("visibilitychange",D),()=>{window.removeEventListener("focus",Z),document.removeEventListener("visibilitychange",D)}},[]),Le.useEffect(()=>{A(null)},[n?.name]),i)return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsx(ZS,{}),N.jsx(aa,{})]});if(!n)return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsx(AS,{}),N.jsx(aa,{})]});const Oe=n.currency??"USD",We=!!n.customer,xt=We?"Sales Invoice":"Purchase Invoice",Ut=n.customer_name??n.customer??n.supplier_name??n.supplier??"—",Kt=n.outstanding_amount??0,pt=Kt<=0,Xe=n.items??[],mt=n.net_total??Xe.reduce((Z,D)=>Z+D.amount,0),zt=n.total_taxes_and_charges??n.grand_total-mt,it=n.status==="Draft"||n.docstatus===0,Pe=n.docstatus===1,F=nn.getHostCapabilities()?.serverTools;return N.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:"100vh"},children:[N.jsx(la,{}),N.jsxs("div",{style:{padding:16,fontFamily:Ge.sans,flex:1,maxWidth:720},children:[N.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:16,flexWrap:"wrap",gap:8},children:[N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:11,fontWeight:600,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:4},children:xt}),N.jsx("div",{style:{fontSize:20,fontWeight:700,color:b.text.primary,fontFamily:Ge.mono},children:n.name}),N.jsxs("div",{style:{display:"flex",gap:8,marginTop:6,alignItems:"center",flexWrap:"wrap"},children:[N.jsx(MS,{status:n.status}),n.company&&N.jsx("span",{style:{fontSize:11,color:b.text.faint},children:n.company})]})]}),N.jsx("button",{onClick:()=>void te({ignoreInterval:!0}),disabled:u,style:Dt.button,children:u?"…":"Refresh"})]}),d&&N.jsx(Sf,{type:"error",message:d,onDismiss:()=>m(null)}),!d&&C&&N.jsx(Sf,{type:"success",message:C}),N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16,marginBottom:16,borderBottom:`1px solid ${b.border}`,paddingBottom:16},children:[N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:4},children:We?"Customer":"Supplier"}),N.jsx("div",{style:{fontSize:14,fontWeight:600,color:b.text.primary},children:Ut}),n.contact_email&&N.jsx("div",{style:{fontSize:11,color:b.text.secondary},children:n.contact_email})]}),N.jsxs("div",{children:[N.jsx("div",{style:{fontSize:10,color:b.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",marginBottom:4},children:"Outstanding"}),N.jsx("div",{style:{fontSize:14,fontWeight:600,color:pt?b.success:b.error,fontFamily:Ge.mono},children:kr(Kt,Oe)}),N.jsx("div",{style:{fontSize:11,color:pt?b.success:b.error},children:pt?"Paid":"Unpaid"})]})]}),N.jsxs("div",{style:{display:"flex",gap:24,marginBottom:16,fontSize:12},children:[N.jsxs("span",{children:[N.jsx("span",{style:{color:b.text.muted},children:"Date"}),N.jsx("span",{style:{color:b.text.primary,fontWeight:500},children:n.posting_date})]}),n.due_date&&N.jsxs("span",{children:[N.jsx("span",{style:{color:b.text.muted},children:"Due"}),N.jsx("span",{style:{color:b.text.primary,fontWeight:500},children:n.due_date})]})]}),Xe.length>0&&N.jsx("div",{style:{border:`1px solid ${b.border}`,borderRadius:12,overflowX:"auto",marginBottom:16},children:N.jsxs("table",{style:{width:"100%",borderCollapse:"collapse"},children:[N.jsx("thead",{children:N.jsxs("tr",{children:[N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface},children:"Item"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Qty"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Rate"}),N.jsx("th",{style:{...Dt.tableHeader,background:b.bg.surface,textAlign:"right"},children:"Amount"})]})}),N.jsx("tbody",{children:Xe.map((Z,D)=>{const _=O===D;return N.jsx("tr",{children:N.jsxs("td",{colSpan:4,style:{padding:0},children:[N.jsxs("div",{style:{display:"grid",gridTemplateColumns:"35% 15% 25% 25%",cursor:F?"pointer":"default",transition:"background 0.1s",background:_?b.bg.hover:"transparent"},onClick:F?()=>A(_?null:D):void 0,onMouseEnter:I=>{_||(I.currentTarget.style.background=b.bg.hover)},onMouseLeave:I=>{_||(I.currentTarget.style.background="transparent")},children:[N.jsxs("div",{style:Dt.tableCell,children:[N.jsx("div",{style:{fontWeight:500,color:b.text.primary},children:Z.item_name??Z.item_code}),Z.item_name&&N.jsx("div",{style:{fontSize:11,color:b.text.faint,fontFamily:Ge.mono},children:Z.item_code})]}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono},children:Z.qty}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono,color:b.text.secondary},children:kr(Z.rate,Oe)}),N.jsx("div",{style:{...Dt.tableCell,textAlign:"right",fontFamily:Ge.mono,fontWeight:500},children:kr(Z.amount,Oe)})]}),_&&N.jsx(LS,{app:nn,itemCode:Z.item_code,onClose:()=>A(null)})]})},D)})})]})}),N.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:16},children:N.jsxs("div",{style:{minWidth:220,borderTop:`1px solid ${b.border}`,paddingTop:8},children:[N.jsx(ua,{label:"Subtotal",value:kr(mt,Oe)}),zt!==0&&N.jsx(ua,{label:"Taxes",value:kr(zt,Oe)}),N.jsx(ua,{label:"Grand Total",value:kr(n.grand_total,Oe),bold:!0})]})}),F&&N.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap",padding:"12px 0",borderTop:`1px solid ${b.border}`},children:[it&&N.jsx(Er,{label:"Submit",variant:"success",confirm:!0,loading:v==="submit",onClick:()=>we("submit","erpnext_doc_submit",{doctype:xt,name:n.name},"Submitted")}),Pe&&N.jsx(Er,{label:"Cancel",variant:"error",confirm:!0,loading:v==="cancel",onClick:()=>we("cancel","erpnext_doc_cancel",{doctype:xt,name:n.name},"Cancelled")}),N.jsx(Er,{label:"Payments",loading:v==="nav_payments",onClick:()=>qe("nav_payments",`Show payment entries for ${xt} ${n.name}`)}),(n.customer??n.supplier)&&N.jsx(Er,{label:We?"Customer invoices":"Supplier invoices",loading:v==="nav_party",onClick:()=>{const Z=n.customer??n.supplier;qe("nav_party",`Show all ${We?"sales":"purchase"} invoices for ${We?"customer":"supplier"} ${Z}`)}})]})]}),N.jsx(aa,{})]})}Rh.createRoot(document.getElementById("app")).render(N.jsx(FS,{}));</script>
123
+ <style rel="stylesheet" crossorigin>:root{--accent: #0089ff;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
+ </head>
125
+ <body>
126
+ <div id="app"></div>
127
+ </body>
128
128
  </html>
@@ -1,10 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Kanban Viewer - mcp-erpnext</title>
7
- <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const d of u)if(d.type==="childList")for(const f of d.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&l(f)}).observe(document,{childList:!0,subtree:!0});function i(u){const d={};return u.integrity&&(d.integrity=u.integrity),u.referrerPolicy&&(d.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?d.credentials="include":u.crossOrigin==="anonymous"?d.credentials="omit":d.credentials="same-origin",d}function l(u){if(u.ep)return;u.ep=!0;const d=i(u);fetch(u.href,d)}})();var ea={exports:{}},yo={},ta={exports:{}},de={};/**
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Kanban Viewer - mcp-erpnext</title>
7
+ <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const d of u)if(d.type==="childList")for(const f of d.addedNodes)f.tagName==="LINK"&&f.rel==="modulepreload"&&l(f)}).observe(document,{childList:!0,subtree:!0});function i(u){const d={};return u.integrity&&(d.integrity=u.integrity),u.referrerPolicy&&(d.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?d.credentials="include":u.crossOrigin==="anonymous"?d.credentials="omit":d.credentials="same-origin",d}function l(u){if(u.ep)return;u.ep=!0;const d=i(u);fetch(u.href,d)}})();var ea={exports:{}},yo={},ta={exports:{}},de={};/**
8
8
  * @license React
9
9
  * react.production.min.js
10
10
  *
@@ -120,9 +120,9 @@ Boolean requesting whether a visible border and background is provided by the ho
120
120
  - "model": Tool visible to and callable by the agent
121
121
  - "app": Tool callable by the app from this server only`)});P({mimeTypes:ae(T()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});P({method:E("ui/download-file"),params:P({contents:ae(he([xp,Ep])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.")})});P({method:E("ui/message"),params:P({role:E("user").describe('Message role, currently only "user" is supported.'),content:ae(No).describe("Message content blocks (text, image, etc.).")})});P({method:E("ui/notifications/sandbox-resource-ready"),params:P({html:T().describe("HTML content to load into the inner iframe."),sandbox:T().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:Ua.optional().describe("CSP configuration from resource metadata."),permissions:Ha.optional().describe("Sandbox permissions from resource metadata.")})});var MS=P({method:E("ui/notifications/tool-result"),params:ss.describe("Standard MCP tool execution result.")}),Rp=P({toolInfo:P({id:zo.optional().describe("JSON-RPC id of the tools/call request."),tool:Za.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:SS.optional().describe("Current color theme preference."),styles:NS.optional().describe("Style configuration for theming the app."),displayMode:xo.optional().describe("How the UI is currently displayed."),availableDisplayModes:ae(xo).optional().describe("Display modes the host supports."),containerDimensions:he([P({height:fe().describe("Fixed container height in pixels.")}),P({maxHeight:he([fe(),da()]).optional().describe("Maximum container height in pixels.")})]).and(he([P({width:fe().describe("Fixed container width in pixels.")}),P({maxWidth:he([fe(),da()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
122
122
  container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:T().optional().describe("User's language and region preference in BCP 47 format."),timeZone:T().optional().describe("User's timezone in IANA format."),userAgent:T().optional().describe("Host application identifier."),platform:he([E("web"),E("desktop"),E("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:P({touch:Re().optional().describe("Whether the device supports touch input."),hover:Re().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:P({top:fe().describe("Top safe area inset in pixels."),right:fe().describe("Right safe area inset in pixels."),bottom:fe().describe("Bottom safe area inset in pixels."),left:fe().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),LS=P({method:E("ui/notifications/host-context-changed"),params:Rp.describe("Partial context update containing only changed fields.")});P({method:E("ui/update-model-context"),params:P({content:ae(No).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:ze(T(),Ce().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});P({method:E("ui/initialize"),params:P({appInfo:os.describe("App identification (name and version)."),appCapabilities:OS.describe("Features and capabilities this app provides."),protocolVersion:T().describe("Protocol version this app supports.")})});var FS=P({protocolVersion:T().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:os.describe("Host application identification and version."),hostCapabilities:jS.describe("Features and capabilities provided by the host."),hostContext:Rp.describe("Rich context about the host environment.")}).passthrough();class AS extends vS{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(o,i={},l={autoResize:!0}){super(l),this._appInfo=o,this._capabilities=i,this.options=l,this.setRequestHandler(is,u=>(console.log("Received ping:",u.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(o){this.setNotificationHandler(TS,i=>o(i.params))}set ontoolinputpartial(o){this.setNotificationHandler(RS,i=>o(i.params))}set ontoolresult(o){this.setNotificationHandler(MS,i=>o(i.params))}set ontoolcancelled(o){this.setNotificationHandler(IS,i=>o(i.params))}set onhostcontextchanged(o){this.setNotificationHandler(LS,i=>{this._hostContext={...this._hostContext,...i.params},o(i.params)})}set onteardown(o){this.setRequestHandler(bS,(i,l)=>o(i.params,l))}set oncalltool(o){this.setRequestHandler(Cp,(i,l)=>o(i.params,l))}set onlisttools(o){this.setRequestHandler(zp,(i,l)=>o(i.params,l))}assertCapabilityForMethod(o){}assertRequestHandlerCapability(o){switch(o){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${o})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${o} registered`)}}assertNotificationCapability(o){}assertTaskCapability(o){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(o){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(o,i){if(typeof o=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${o}"). Did you mean: callServerTool({ name: "${o}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:o},ss,i)}async readServerResource(o,i){return await this.request({method:"resources/read",params:o},kp,i)}async listServerResources(o,i){return await this.request({method:"resources/list",params:o},Sp,i)}sendMessage(o,i){return this.request({method:"ui/message",params:o},CS,i)}sendLog(o){return this.notification({method:"notifications/message",params:o})}updateModelContext(o,i){return this.request({method:"ui/update-model-context",params:o},Ca,i)}openLink(o,i){return this.request({method:"ui/open-link",params:o},ES,i)}sendOpenLink=this.openLink;downloadFile(o,i){return this.request({method:"ui/download-file",params:o},zS,i)}requestDisplayMode(o,i){return this.request({method:"ui/request-display-mode",params:o},$S,i)}sendSizeChanged(o){return this.notification({method:"ui/notifications/size-changed",params:o})}setupSizeChangedNotifications(){let o=!1,i=0,l=0,u=()=>{o||(o=!0,requestAnimationFrame(()=>{o=!1;let f=document.documentElement,h=f.style.width,v=f.style.height;f.style.width="fit-content",f.style.height="max-content";let _=f.getBoundingClientRect();f.style.width=h,f.style.height=v;let z=window.innerWidth-f.clientWidth,S=Math.ceil(_.width+z),j=Math.ceil(_.height);(S!==i||j!==l)&&(i=S,l=j,this.sendSizeChanged({width:S,height:j}))}))};u();let d=new ResizeObserver(u);return d.observe(document.documentElement),d.observe(document.body),()=>d.disconnect()}async connect(o=new wS(window.parent,window.parent),i){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");await super.connect(o);try{let l=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:yS}},FS,i);if(l===void 0)throw Error(`Server sent invalid initialize result: ${l}`);this._hostCapabilities=l.hostCapabilities,this._hostInfo=l.hostInfo,this._hostContext=l.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(l){throw this.close(),l}}}function He(n){return`var(${n})`}const N={bg:{root:He("--bg-root"),surface:He("--bg-surface"),elevated:He("--bg-elevated")},text:{primary:He("--text-primary"),secondary:He("--text-secondary"),muted:He("--text-muted"),faint:He("--text-faint")},accent:He("--accent"),accentDim:He("--accent-dim"),border:He("--border"),borderSubtle:He("--border-subtle"),success:He("--success"),successDim:He("--success-dim"),error:He("--error"),errorDim:He("--error-dim"),warning:He("--warning"),warningDim:He("--warning-dim"),info:He("--info"),infoDim:He("--info-dim")},Et={sans:He("--font-sans"),mono:He("--font-mono")},at={card:{background:N.bg.surface,border:`1px solid ${N.border}`,borderRadius:"8px",padding:"16px"},badge:(n,o)=>({display:"inline-flex",alignItems:"center",padding:"2px 8px",fontSize:"11px",fontWeight:600,borderRadius:"4px",color:n,background:o,letterSpacing:"0.02em"}),input:{background:N.bg.elevated,border:`1px solid ${N.border}`,borderRadius:"6px",padding:"6px 12px",fontSize:"13px",color:N.text.primary,outline:"none",transition:"border-color 0.15s",width:"100%",fontFamily:Et.sans},button:{background:N.bg.elevated,border:`1px solid ${N.border}`,borderRadius:"6px",padding:"6px 14px",fontSize:"12px",color:N.text.secondary,cursor:"pointer",transition:"all 0.15s",fontFamily:Et.sans,whiteSpace:"nowrap"},buttonActive:{background:N.accentDim,borderColor:N.accent,color:N.accent},tableHeader:{padding:"8px 12px",textAlign:"left",fontSize:"11px",fontWeight:600,color:N.text.muted,textTransform:"uppercase",letterSpacing:"0.05em",borderBottom:`1px solid ${N.border}`,cursor:"pointer",userSelect:"none",whiteSpace:"nowrap",transition:"color 0.15s"},tableCell:{padding:"8px 12px",fontSize:"13px",borderBottom:`1px solid ${N.borderSubtle}`,color:N.text.primary},mono:{fontFamily:Et.mono,fontSize:"12px"}};function ZS(){return x.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[x.jsx("rect",{x:"1",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.9"}),x.jsx("rect",{x:"9",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),x.jsx("rect",{x:"1",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),x.jsx("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.35"})]})}function Bi(){const n={display:"flex",alignItems:"center",gap:7,padding:"0 14px",height:30,background:N.bg.surface,borderBottom:`1px solid ${N.border}`,flexShrink:0},o={fontFamily:Et.sans,fontSize:11,fontWeight:700,letterSpacing:"0.08em",textTransform:"uppercase",color:N.accent},i={width:3,height:3,borderRadius:"50%",background:N.text.faint,marginLeft:2,marginRight:2,flexShrink:0},l={fontFamily:Et.sans,fontSize:10,color:N.text.muted,letterSpacing:"0.03em"};return x.jsxs("div",{style:n,children:[x.jsx("div",{style:{color:N.accent},children:x.jsx(ZS,{})}),x.jsx("span",{style:o,children:"ERPNext"}),x.jsx("div",{style:i}),x.jsx("span",{style:l,children:"gestion ERP"})]})}function US(n){return n.error?n.board?{blockingError:null,inlineError:n.error}:{blockingError:n.error,inlineError:null}:{blockingError:null,inlineError:null}}function HS(n){let o;return n.pagination.total!==void 0?o=`${n.pagination.total} cards`:n.pagination.hasMore?o=`${n.pagination.loadedCount}+ cards loaded`:o=`${n.pagination.loadedCount} cards`,`${o} · ${n.doctype} · move tool ${n.moveToolName}`}function la(n){let o;return n instanceof Error?o=n.message:typeof n=="string"?o=n:o="Move failed",/timeout|timed out/i.test(o)?"La mise a jour a expire, veuillez reessayer.":o}const Ip={selectedCardId:null,cardDetail:null,detailLoading:!1,detailError:null};function qS(){return{board:null,loading:!0,error:null,detail:{...Ip}}}function VS(n,o){switch(o.type){case"tool-input":return{...n,loading:!0,error:null};case"hydrate-board":return{board:o.board,loading:!1,error:null,detail:n.detail};case"tool-error":return{...n,loading:!1,error:o.message};case"select-card":return{...n,detail:{selectedCardId:o.cardId,cardDetail:null,detailLoading:!0,detailError:null}};case"hydrate-detail":return{...n,detail:{...n.detail,cardDetail:o.detail,detailLoading:!1,detailError:null}};case"close-detail":return{...n,detail:{...Ip}};case"detail-error":return{...n,detail:{...n.detail,detailLoading:!1,detailError:o.message}};default:return n}}function WS(){const[n,o]=le.useReducer(VS,void 0,qS);return{state:n,startLoading(){o({type:"tool-input"})},hydrateBoard(i){o({type:"hydrate-board",board:i})},setError(i){o({type:"tool-error",message:i})},selectCard(i){o({type:"select-card",cardId:i})},hydrateDetail(i){o({type:"hydrate-detail",detail:i})},closeDetail(){o({type:"close-detail"})},setDetailError(i){o({type:"detail-error",message:i})}}}function Pp(n,o){const i=new Map;for(const l of o)i.set(l.columnId,(i.get(l.columnId)??0)+1);return n.columns.map(l=>({...l,count:i.get(l.id)??0}))}function wf(n,o){const i=n.cards.map(l=>l.id===o.cardId?{...l,columnId:o.toColumn,pending:!0}:l);return{snapshot:n,board:{...n,cards:i,columns:Pp(n,i)}}}function BS(n,o){const i=n.cards.map(l=>l.id!==o.cardId?l:o.serverCard?{...o.serverCard,pending:!1}:{...l,columnId:o.toColumn,pending:!1});return{...n,cards:i,columns:Pp(n,i)}}function aa(n,o){return n}function QS(n,o){return[...n,o]}function JS(n){const[o,...i]=n;return{nextMove:o,restQueue:i}}function KS(n,o,i){const l=n.cards.find(u=>u.id===o);return!l||l.pending||l.columnId===i?!1:n.allowedTransitions.some(u=>u.allowed&&u.fromColumn===l.columnId&&u.toColumn===i)}function GS(n,o={}){return!n.board||!n.request||n.visibilityState!=="visible"||n.dragging||n.processingMove||n.queuedMoves>0||n.refreshInFlight?!1:o.ignoreInterval?!0:n.now-n.lastRefreshStartedAt>=n.minIntervalMs}function YS(n,o){return n?{toolName:"erpnext_kanban_get_board",arguments:n.refreshArguments}:o}const XS=920;function ek(n,o){return o>1&&n<=XS}function tk(n,o){return o<=0||n<0?0:n>=o?o-1:n}function nk(n){return n.structuredContent?JSON.stringify(n.structuredContent):n.content?.find(o=>o.type==="text")?.text??null}const Sf={success:{color:N.success,bg:N.successDim},error:{color:N.error,bg:N.errorDim},info:{color:N.info,bg:N.infoDim},default:{color:N.text.secondary,bg:N.bg.elevated}};function Wi({label:n,variant:o="default",disabled:i,loading:l,confirm:u,onClick:d}){const[f,h]=le.useState(!1),v=le.useRef();le.useEffect(()=>()=>clearTimeout(v.current),[]);const _=Sf[o]??Sf.default;return x.jsx("button",{onClick:()=>{if(u&&!f){h(!0),clearTimeout(v.current),v.current=setTimeout(()=>h(!1),4e3);return}h(!1),d()},disabled:i||l,style:{...at.button,background:_.bg,color:_.color,borderColor:_.color,opacity:i||l?.5:1,fontSize:11,padding:"4px 10px"},children:l?"…":f?"Confirm?":n})}const rk=new Set(["doctype","docstatus","idx","modified_by","owner","creation","modified","_user_tags","_comments","_assign","_liked_by","_seen","__last_sync_on","lft","rgt","old_parent","is_group","is_template","depends_on_tasks","depends_on"]),ok=new Set(["name","status","workflow_state"]),ik={name:"ID",subject:"Subject",status:"Status",priority:"Priority",project:"Project",progress:"Progress (%)",description:"Description",exp_start_date:"Start date",exp_end_date:"Due date",expected_time:"Estimated (h)",actual_time:"Actual time (h)",is_milestone:"Milestone",task_weight:"Weight",total_costing_amount:"Cost",total_billing_amount:"Billing",start:"Start",duration:"Duration",title:"Title",opportunity_from:"Source type",party_name:"Party",opportunity_amount:"Amount",currency:"Currency",probability:"Probability (%)",opportunity_owner:"Owner",expected_closing:"Expected closing",transaction_date:"Created",contact_person:"Contact",source:"Source",customer:"Customer",raised_by:"Raised by",resolution_by:"SLA deadline",opening_date:"Opened",resolution_date:"Resolved",first_responded_on:"First response"},sk=new Set(["is_milestone","is_group","is_template"]),lk=new Set(["exp_start_date","exp_end_date","expected_closing","transaction_date","opening_date","resolution_date","resolution_by","first_responded_on"]),qa={priority:["Low","Medium","High","Urgent"],opportunity_from:["Lead","Customer"]},ak=new Set(["name","status","priority","subject","title","project"]),uk=new Set(["progress","is_milestone"]),Np=new Set(["description","resolution_details","notes"]),ck=[{id:"dates",label:"Dates",fields:["exp_start_date","exp_end_date","expected_closing","transaction_date","opening_date","resolution_date","resolution_by","first_responded_on","start"]},{id:"time",label:"Time Tracking",fields:["expected_time","actual_time","duration"]},{id:"financial",label:"Financial",fields:["opportunity_amount","currency","probability","total_costing_amount","total_billing_amount","task_weight"]},{id:"people",label:"People",fields:["project","opportunity_owner","customer","party_name","contact_person","raised_by","source","opportunity_from"]}],dk={Urgent:"error",High:"error",Medium:"warning",Low:"success"};function Va(n){return ik[n]??n.replace(/_/g," ").replace(/\b\w/g,o=>o.toUpperCase())}function fk(n){return Np.has(n)}function pk(n,o){return sk.has(n)?"boolean":lk.has(n)?"date":n in qa?"select":fk(n)?"textarea":typeof o=="number"?"number":"text"}function hk(n){const o=Object.entries(n).filter(([$,A])=>!rk.has($)&&A!==null&&A!==void 0&&A!==""&&typeof A!="object"),i=new Map(o),l=new Set,u=o.find(([$])=>$==="subject"||$==="title"),d=i.has("name")?String(i.get("name")):null,f=i.has("status")?String(i.get("status")):null,h=i.has("priority")?String(i.get("priority")):null,v=i.has("project")?String(i.get("project")):null,_=i.has("progress")?Number(i.get("progress")):null,z=i.has("is_milestone")?Number(i.get("is_milestone")):null;for(const $ of ak)l.add($);for(const $ of uk)l.add($);const S=o.find(([$])=>Np.has($)),j=S?{key:S[0],value:S[1]}:null;S&&l.add(S[0]);const O=[];for(const $ of ck){const A=[];for(const pe of $.fields)i.has(pe)&&!l.has(pe)&&(A.push({key:pe,value:i.get(pe)}),l.add(pe));A.length>0&&O.push({id:$.id,label:$.label,fields:A})}const X=[];for(const[$,A]of o)l.has($)||X.push({key:$,value:A});return X.length>0&&O.push({id:"details",label:"Details",fields:X}),{titleField:u?{key:u[0],value:u[1]}:null,idValue:d,statusValue:f,priorityValue:h,projectValue:v,progressValue:_,milestoneValue:z,descriptionField:j,sections:O}}function mk({value:n,onChange:o}){const[i,l]=le.useState(!1),u=jp(dk[n]);return i?x.jsx("select",{value:n,onChange:d=>{o(d.target.value),l(!1)},onBlur:()=>l(!1),autoFocus:!0,style:{...at.input,padding:"2px 8px",fontSize:10,fontWeight:700,width:"auto",cursor:"pointer"},children:qa.priority.map(d=>x.jsx("option",{value:d,children:d},d))}):x.jsx("span",{role:"button",tabIndex:0,onClick:()=>l(!0),onKeyDown:d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),l(!0))},style:{...at.badge(u.color,u.bg),fontSize:10,padding:"2px 8px",borderRadius:3,fontWeight:700,letterSpacing:"0.03em",textTransform:"uppercase",cursor:"pointer"},title:"Click to change priority",children:n})}function gk({progressValue:n,editedFields:o,onFieldChange:i}){if(n===null)return null;const l=o.progress!==void 0?Number(o.progress):n??0;return x.jsx("div",{style:{padding:"6px 16px 8px",display:"flex",alignItems:"center",gap:10},children:x.jsxs("div",{style:{flex:1,display:"flex",alignItems:"center",gap:8},children:[x.jsx("span",{style:{fontSize:9,fontWeight:600,color:N.text.faint,textTransform:"uppercase",letterSpacing:"0.06em",flexShrink:0},children:"Progress"}),x.jsxs("div",{style:{flex:1,position:"relative",height:18,display:"flex",alignItems:"center"},children:[x.jsx("div",{style:{position:"absolute",left:0,right:0,height:4,background:N.bg.elevated,borderRadius:2},children:x.jsx("div",{style:{height:"100%",width:`${Math.min(100,Math.max(0,l))}%`,background:l>=100?N.success:N.accent,borderRadius:2,transition:"width 0.2s"}})}),x.jsx("input",{type:"range",min:0,max:100,value:l,onChange:u=>i("progress",u.target.value),style:{position:"absolute",left:0,right:0,width:"100%",height:18,opacity:0,cursor:"pointer",margin:0}})]}),x.jsxs("span",{style:{fontSize:11,fontWeight:700,fontFamily:Et.mono,color:l>=100?N.success:N.text.primary,flexShrink:0,minWidth:32,textAlign:"right"},children:[l,"%"]})]})})}function vk({field:n,editedFields:o,onFieldChange:i}){const l=n.key in o,u=l?o[n.key]:String(n.value);return x.jsxs("div",{style:{padding:"8px 16px"},children:[x.jsx("div",{style:{fontSize:9,fontWeight:600,color:N.text.faint,textTransform:"uppercase",letterSpacing:"0.06em",marginBottom:4},children:Va(n.key)}),x.jsx("textarea",{value:u,onChange:d=>i(n.key,d.target.value),rows:3,style:{...at.input,resize:"vertical",borderColor:l?N.accent:N.border,background:l?N.accentDim:N.bg.elevated,lineHeight:1.5,fontSize:13}})]})}function yk({fieldKey:n,value:o,editedFields:i,onFieldChange:l}){const u=ok.has(n),d=n in i,f=d?i[n]:String(o),h=pk(n,o),v={...at.input,padding:"5px 8px",fontSize:13};function _(S){return{...v,borderColor:S?N.accent:"transparent",background:S?N.accentDim:"transparent"}}function z(){if(u)return x.jsx("span",{style:{fontSize:13,color:N.text.primary,fontFamily:typeof o=="number"?Et.mono:Et.sans,fontWeight:n==="name"?500:400},children:String(o)});switch(h){case"boolean":return x.jsxs("label",{style:{display:"flex",alignItems:"center",gap:8,cursor:"pointer"},children:[x.jsx("input",{type:"checkbox",checked:d?f==="1":o===1,onChange:S=>l(n,S.target.checked?"1":"0"),style:{width:16,height:16,accentColor:"var(--accent)",cursor:"pointer"}}),x.jsx("span",{style:{fontSize:12,color:N.text.secondary},children:(d?f==="1":o===1)?"Yes":"No"})]});case"select":return x.jsx("select",{value:f,onChange:S=>l(n,S.target.value),style:{...v,borderColor:d?N.accent:"transparent",background:d?N.accentDim:"transparent",cursor:"pointer"},children:qa[n]?.map(S=>x.jsx("option",{value:S,children:S},S))});case"date":return x.jsx("input",{type:"date",value:f,onChange:S=>l(n,S.target.value),style:_(d)});case"number":return x.jsx("input",{type:"number",value:f,onChange:S=>l(n,S.target.value),style:{..._(d),fontFamily:Et.mono}});default:return x.jsx("input",{type:"text",value:f,onChange:S=>l(n,S.target.value),style:_(d)})}}return x.jsxs("div",{className:"detail-field-cell",style:{display:"flex",flexDirection:"column",gap:1,padding:"3px 4px"},children:[x.jsx("span",{style:{fontSize:10,fontWeight:600,color:d?N.accent:N.text.faint,textTransform:"uppercase",letterSpacing:"0.05em"},children:Va(n)}),z()]})}function _k({sections:n,editedFields:o,onFieldChange:i}){return x.jsx("div",{style:{display:"flex",flexDirection:"column"},children:n.map(l=>x.jsxs("div",{style:{padding:"2px 16px 0"},children:[x.jsx("div",{style:{fontSize:9,fontWeight:700,color:N.text.faint,textTransform:"uppercase",letterSpacing:"0.08em",padding:"4px 0 2px",borderBottom:`1px solid ${N.borderSubtle}`},children:l.label}),x.jsx("div",{style:{display:"grid",gridTemplateColumns:l.fields.length>=3?"1fr 1fr 1fr":"1fr 1fr",gap:"0 12px"},children:l.fields.map((u,d)=>{const f=l.fields.length>=3?3:2,h=d===l.fields.length-1,v=l.fields.length%f===1;return x.jsx("div",{style:h&&v?{gridColumn:"1 / -1"}:void 0,children:x.jsx(yk,{fieldKey:u.key,value:u.value,editedFields:o,onFieldChange:i})},u.key)})})]},l.id))})}function wk({detail:n,board:o,onClose:i,onMove:l,onSave:u,onNavigate:d}){const[f,h]=le.useState({}),[v,_]=le.useState(!1),[z,S]=le.useState(null),j=le.useRef(null);if(le.useEffect(()=>{if(!n.selectedCardId)return;j.current?.focus();function B(Se){Se.key==="Escape"&&i()}return document.addEventListener("keydown",B),()=>document.removeEventListener("keydown",B)},[n.selectedCardId,i]),le.useEffect(()=>{h({}),S(null)},[n.selectedCardId]),!n.selectedCardId)return null;const O=o.cards.find(B=>B.id===n.selectedCardId),X=O?.title??n.selectedCardId,$=O?Wa(o,O.columnId):[],A=Object.keys(f).length>0;function pe(B,Se){h(Ee=>{const nt=n.cardDetail?String(n.cardDetail[B]??""):"";if(Se===nt){const ut={...Ee};return delete ut[B],ut}return{...Ee,[B]:Se}}),S(null)}async function me(){if(!(!A||!u||!n.selectedCardId)){_(!0),S(null);try{await u(o.doctype,n.selectedCardId,f),S({text:"Saved",isError:!1}),h({})}catch(B){S({text:B instanceof Error?B.message:"Save failed",isError:!0})}finally{_(!1)}}}const ue=O?o.columns.find(B=>B.id===O.columnId)?.color:void 0,J=n.cardDetail?hk(n.cardDetail):null;return x.jsx("div",{className:"kanban-detail-backdrop",onClick:B=>{B.target===B.currentTarget&&i()},children:x.jsxs("div",{className:"kanban-detail-panel",role:"dialog","aria-modal":"true","aria-label":`Detail: ${X}`,children:[ue&&x.jsx("div",{"aria-hidden":"true",style:{height:3,background:ue,borderRadius:"12px 12px 0 0",flexShrink:0}}),x.jsxs("div",{style:{padding:"10px 16px 8px",display:"flex",alignItems:"flex-start",gap:10,borderBottom:`1px solid ${N.border}`},children:[x.jsxs("div",{style:{flex:1,minWidth:0},children:[J?.titleField?x.jsx("input",{type:"text","aria-label":Va(J.titleField.key),value:f[J.titleField.key]??String(J.titleField.value),onChange:B=>pe(J.titleField.key,B.target.value),style:{fontSize:15,fontWeight:700,color:N.text.primary,lineHeight:1.3,background:"transparent",border:"1px solid transparent",borderRadius:4,padding:"2px 4px",margin:"-2px -4px",width:"calc(100% + 8px)",fontFamily:Et.sans,outline:"none",transition:"border-color 0.15s"}}):x.jsx("div",{style:{fontSize:15,fontWeight:700,color:N.text.primary,lineHeight:1.3},children:X}),x.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:2,flexWrap:"wrap"},children:[x.jsx("span",{style:{fontFamily:Et.mono,fontSize:11,color:N.text.faint},children:n.selectedCardId}),J?.statusValue&&x.jsx("span",{style:{...at.badge(ue??N.text.muted,`${ue??N.text.muted}20`),fontSize:10},children:J.statusValue}),J?.priorityValue&&x.jsx(mk,{value:f.priority??J.priorityValue,onChange:B=>pe("priority",B)}),J?.projectValue&&x.jsx("span",{style:{fontSize:11,color:N.text.muted},children:J.projectValue}),J?.milestoneValue!==null&&J?.milestoneValue!==void 0&&(()=>{const B=f.is_milestone!==void 0?f.is_milestone==="1":J.milestoneValue===1;return x.jsxs("span",{role:"switch","aria-checked":B,"aria-label":"Milestone",tabIndex:0,onClick:()=>pe("is_milestone",B?"0":"1"),onKeyDown:Se=>{(Se.key==="Enter"||Se.key===" ")&&(Se.preventDefault(),pe("is_milestone",B?"0":"1"))},title:B?"Milestone (click to unset)":"Set as milestone",style:{display:"inline-flex",alignItems:"center",gap:3,cursor:"pointer",padding:"1px 6px",borderRadius:3,background:B?N.accentDim:"transparent",border:`1px solid ${B?N.accent:"transparent"}`,transition:"all 0.2s"},children:[x.jsx("span",{style:{fontSize:10,color:B?N.accent:N.text.faint,transition:"color 0.2s",lineHeight:1},children:"◆"}),x.jsx("span",{style:{fontSize:9,fontWeight:600,color:B?N.accent:N.text.faint,textTransform:"uppercase",letterSpacing:"0.04em",transition:"color 0.2s"},children:"Milestone"})]})})()]})]}),x.jsx("button",{ref:j,type:"button",onClick:i,"aria-label":"Close detail",style:{background:"transparent",border:"none",cursor:"pointer",padding:4,borderRadius:4,color:N.text.faint,fontSize:18,lineHeight:1,transition:"color 0.1s"},children:"✕"})]}),x.jsxs("div",{style:{maxHeight:"60vh",overflowY:"auto"},children:[n.detailLoading&&x.jsx("div",{style:{padding:20,display:"flex",flexDirection:"column",gap:10},children:[1,2,3,4,5,6].map(B=>x.jsxs("div",{style:{display:"flex",gap:12,alignItems:"center"},children:[x.jsx("div",{className:"skeleton",style:{width:120,height:14}}),x.jsx("div",{className:"skeleton",style:{flex:1,height:14}})]},B))}),n.detailError&&x.jsx("div",{style:{margin:16,padding:"10px 14px",background:N.errorDim,borderRadius:6,color:N.error,fontSize:12},children:n.detailError}),J?.descriptionField&&x.jsx("div",{style:{borderBottom:`1px solid ${N.borderSubtle}`},children:x.jsx(vk,{field:J.descriptionField,editedFields:f,onFieldChange:pe})}),J&&J.sections.length>0&&x.jsx(_k,{sections:J.sections,editedFields:f,onFieldChange:pe}),J&&x.jsx(gk,{progressValue:J.progressValue,editedFields:f,onFieldChange:pe})]}),x.jsxs("div",{style:{borderTop:`1px solid ${N.border}`,padding:"8px 16px",display:"flex",flexWrap:"wrap",gap:6,alignItems:"center",flexShrink:0},children:[u&&n.cardDetail&&x.jsxs(x.Fragment,{children:[x.jsx("button",{type:"button",onClick:me,disabled:!A||v,style:{...at.button,padding:"4px 12px",fontSize:11,fontWeight:600,background:A?N.accent:N.bg.elevated,color:A?"#fff":N.text.faint,borderColor:A?N.accent:N.border,opacity:v?.6:1,borderRadius:5},children:v?"Saving…":"Save"}),A&&x.jsx("button",{type:"button",onClick:()=>{h({}),S(null)},style:{...at.button,padding:"4px 10px",fontSize:11},children:"Discard"}),z&&x.jsx("span",{style:{fontSize:10,fontWeight:500,color:z.isError?N.error:N.success,padding:"1px 6px",borderRadius:3,background:z.isError?N.errorDim:N.successDim},children:z.text}),x.jsx("span",{style:{width:1,height:14,background:N.border,flexShrink:0}})]}),O&&$.length>0&&x.jsxs(x.Fragment,{children:[x.jsx("span",{style:{fontSize:10,fontWeight:600,color:N.text.faint,textTransform:"uppercase",letterSpacing:"0.06em"},children:"Move to"}),$.map(B=>x.jsxs("button",{type:"button",onClick:()=>{l(O,B.columnId,B.label),i()},style:{...at.button,padding:"4px 8px",fontSize:11,display:"inline-flex",alignItems:"center",gap:4},children:[B.color&&x.jsx("span",{"aria-hidden":"true",style:{width:6,height:6,borderRadius:"50%",background:B.color,flexShrink:0}}),B.label]},B.columnId))]}),d&&O&&$.length>0&&x.jsx("span",{style:{width:1,height:14,background:N.border,flexShrink:0}}),d&&n.selectedCardId&&x.jsxs(x.Fragment,{children:[x.jsx(Wi,{label:"Open in doclist",variant:"info",onClick:()=>d(`Show me a list view of ${o.doctype} ${n.selectedCardId}`)}),o.doctype==="Task"&&x.jsx(Wi,{label:"Timesheets",variant:"info",onClick:()=>d(`Show timesheets for task ${n.selectedCardId}`)}),o.doctype==="Opportunity"&&x.jsx(Wi,{label:"Quotations",variant:"info",onClick:()=>d(`Show quotations linked to opportunity ${n.selectedCardId}`)}),o.doctype==="Issue"&&x.jsx(Wi,{label:"Related tasks",variant:"info",onClick:()=>d(`Show tasks related to issue ${n.selectedCardId}`)})]})]})]})})}const Nt=new AS({name:"Kanban Viewer",version:"1.0.0"}),kf=15e3,_o=1e4;function Sk(){return{position:"absolute",width:1,height:1,padding:0,margin:-1,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",border:0}}const xr=nk;function xf(n){return n.data&&typeof n.data=="object"&&!Array.isArray(n.data)?n.data:n}function Wa(n,o){return n.allowedTransitions.filter(i=>i.allowed&&i.fromColumn===o&&i.toColumn!==o).map(i=>{const l=n.columns.find(u=>u.id===i.toColumn);return{columnId:i.toColumn,label:i.label??l?.label??i.toColumn,color:l?.color}})}function kk({children:n,style:o,...i}){const l=le.useRef(null),u=le.useRef({active:!1,startX:0,scrollLeft:0}),[d,f]=le.useState(!1),[h,v]=le.useState(!1),_=le.useCallback(()=>{const $=l.current;$&&(f($.scrollLeft>0),v($.scrollLeft<$.scrollWidth-$.clientWidth-1))},[]);le.useEffect(()=>{const $=l.current;if(!$)return;_();const A=new ResizeObserver(_);return A.observe($),()=>A.disconnect()},[_]);const z=le.useCallback($=>{const A=l.current;A&&(u.current={active:!0,startX:$.clientX,scrollLeft:A.scrollLeft},A.style.cursor="grabbing",A.style.userSelect="none")},[]),S=le.useCallback($=>{if(!u.current.active)return;const A=l.current;if(!A)return;const pe=$.clientX-u.current.startX;A.scrollLeft=u.current.scrollLeft-pe,_()},[_]),j=le.useCallback(()=>{u.current.active=!1;const $=l.current;$&&($.style.cursor="grab",$.style.userSelect="")},[]);function O(){if(d&&h)return"linear-gradient(to right, transparent, black 24px, black calc(100% - 24px), transparent)";if(h)return"linear-gradient(to right, black calc(100% - 24px), transparent)";if(d)return"linear-gradient(to right, transparent, black 24px)"}const X=O();return x.jsx("div",{ref:l,style:{...o,WebkitMaskImage:X,maskImage:X},onMouseDown:z,onMouseMove:S,onMouseUp:j,onMouseLeave:j,onScroll:_,className:"drag-scroll",...i,children:n})}function xk(){return x.jsx("div",{style:{padding:20},children:x.jsx("div",{style:{display:"flex",gap:12,alignItems:"flex-start",overflowX:"auto"},children:[1,2,3].map(n=>x.jsxs("div",{style:{minWidth:240,display:"flex",flexDirection:"column",gap:8},children:[x.jsx("div",{className:"skeleton",style:{height:36,width:"100%"}}),[1,2,3].map(o=>x.jsx("div",{className:"skeleton",style:{height:72,width:"100%"}},o))]},n))})})}function Ek(){return x.jsx("div",{style:{padding:"36px 20px",textAlign:"center",color:N.text.muted,fontFamily:Et.sans,fontSize:13},children:"No kanban data available"})}function bp({message:n}){return x.jsx("div",{style:{margin:16,...at.card,borderColor:N.error,color:N.error,fontSize:13},children:n})}function jp(n){switch(n){case"error":return{color:N.error,bg:N.errorDim};case"warning":return{color:N.warning,bg:N.warningDim};case"success":return{color:N.success,bg:N.successDim};case"info":return{color:N.info,bg:N.infoDim};default:return{color:N.text.secondary,bg:N.bg.elevated}}}function zk({email:n}){const o=n.charAt(0).toUpperCase(),i=n.indexOf("@"),l=i>0?n.slice(0,i):n;return x.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[x.jsx("span",{style:{width:14,height:14,borderRadius:"50%",background:N.accent,color:"#fff",fontSize:8,fontWeight:700,display:"inline-flex",alignItems:"center",justifyContent:"center",flexShrink:0},children:o}),x.jsx("span",{style:{fontSize:10,color:N.text.muted,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l})]})}function Op({card:n,allowedTargets:o,onMove:i,onDragStart:l,onDragEnd:u,onTitleClick:d,enableDrag:f=!0}){const h=f&&!n.pending,v=n.accent??N.accent,_={background:N.bg.surface,border:`1px solid ${n.pending?N.accent:N.border}`,borderRadius:8,padding:0,display:"flex",flexDirection:"column",opacity:n.pending?.72:1,boxShadow:n.pending?`0 0 0 1px ${N.accentDim}`:"0 1px 3px rgba(0,0,0,0.06)",cursor:h?"grab":void 0,overflow:"hidden",position:"relative"},z=(n.metrics?.length??0)>0,S=(n.badges?.length??0)>0,j={fontSize:13,fontWeight:600,color:N.text.primary,lineHeight:1.35,overflow:"hidden",textOverflow:"ellipsis",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical"};return x.jsxs("article",{style:_,draggable:h,onDragStart:h?O=>l(n,O):void 0,onDragEnd:h?u:void 0,className:n.pending?"animate-pulse":void 0,"aria-busy":n.pending,children:[x.jsx("div",{"aria-hidden":"true",style:{height:4,background:v,flexShrink:0,opacity:n.pending?.5:.85}}),x.jsxs("div",{style:{padding:"10px 12px 0",display:"flex",flexDirection:"column",gap:6},children:[x.jsxs("div",{style:{display:"flex",alignItems:"flex-start",gap:8},children:[x.jsxs("div",{style:{flex:1,minWidth:0},children:[d?x.jsx("span",{className:"kanban-card-title-link",role:"button",tabIndex:0,onClick:O=>{O.stopPropagation(),d(n)},onKeyDown:O=>{O.key==="Enter"&&d(n)},style:j,children:n.title}):x.jsx("div",{style:j,children:n.title}),n.subtitle&&x.jsx("div",{style:{fontSize:11,color:N.text.muted,marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:n.subtitle})]}),S&&x.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:4,flexShrink:0},children:n.badges?.map(O=>{const X=jp(O.tone);return x.jsx("span",{style:{...at.badge(X.color,X.bg),fontSize:10,padding:"1px 7px",borderRadius:3,fontWeight:700,letterSpacing:"0.03em",textTransform:"uppercase"},children:O.label},`${n.id}-${O.label}`)})})]}),n.description&&x.jsx("div",{style:{fontSize:11,fontStyle:"italic",color:N.text.muted,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",lineHeight:1.3},children:n.description}),n.assignee&&x.jsx("div",{style:{marginTop:-2},children:x.jsx(zk,{email:n.assignee})}),z&&x.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:12,padding:"4px 0 2px",borderTop:`1px solid ${N.borderSubtle}`},children:n.metrics?.map(O=>x.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:1},children:[x.jsx("span",{style:{fontSize:9,fontWeight:600,color:N.text.faint,textTransform:"uppercase",letterSpacing:"0.06em"},children:O.label}),x.jsx("span",{style:{fontSize:13,fontWeight:700,color:N.text.primary,fontFamily:Et.mono,letterSpacing:"-0.02em"},children:O.value})]},`${n.id}-${O.label}`))})]}),o.length>0&&x.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:0,borderTop:`1px solid ${N.borderSubtle}`,marginTop:z?0:6},children:o.map((O,X)=>x.jsxs("button",{type:"button",onClick:()=>i(n,O.columnId,O.label),disabled:n.pending,style:{flex:1,minWidth:0,padding:"7px 6px",fontSize:11,fontWeight:500,fontFamily:Et.sans,color:N.text.muted,background:"transparent",border:"none",borderRight:X<o.length-1?`1px solid ${N.borderSubtle}`:"none",cursor:n.pending?"default":"pointer",opacity:n.pending?.5:1,transition:"color 0.12s, background 0.12s",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",outlineOffset:-2,display:"flex",alignItems:"center",justifyContent:"center",gap:5},"aria-label":`Move ${n.title} to ${O.label}`,children:[O.color&&x.jsx("span",{"aria-hidden":"true",style:{width:6,height:6,borderRadius:"50%",background:O.color,flexShrink:0}}),O.label]},`${n.id}-${O.columnId}`))})]})}function Ck({column:n,cards:o,board:i,activeDropColumn:l,onMove:u,onDropCard:d,onDragStart:f,onDragEnd:h,onDragOverColumn:v,onTitleClick:_}){return x.jsxs("section",{style:{minWidth:260,maxWidth:320,display:"flex",flexDirection:"column",gap:10},onDragOver:z=>v(n.id,z),onDrop:z=>d(n.id,z),children:[x.jsxs("header",{style:{...at.card,padding:"10px 12px",display:"flex",alignItems:"center",gap:8,borderColor:l===n.id?N.accent:N.border,background:l===n.id?N.accentDim:N.bg.surface},children:[x.jsx("span",{"aria-hidden":"true",style:{width:10,height:10,borderRadius:"50%",background:n.color,flexShrink:0}}),x.jsx("span",{style:{fontSize:12,fontWeight:700,color:N.text.primary,flex:1},children:n.label}),x.jsx("span",{style:{...at.badge(n.color,`${n.color}20`)},children:n.count})]}),x.jsx("div",{style:{display:"flex",flexDirection:"column",gap:8},children:o.map(z=>x.jsx(Op,{card:z,allowedTargets:Wa(i,z.columnId),onMove:u,onDragStart:f,onDragEnd:h,onTitleClick:_},z.id))})]})}function Ef({direction:n,onClick:o}){return x.jsx("button",{type:"button",onClick:o,"aria-label":`Scroll ${n}`,style:{...at.button,padding:"6px 4px",fontSize:12,lineHeight:1,borderRadius:6,flexShrink:0,minWidth:22},children:n==="left"?"‹":"›"})}function Tk({columns:n,focusIndex:o,onSelect:i}){const l=le.useRef([]),[u,d]=le.useState(!1),[f,h]=le.useState(!1),v=le.useCallback(()=>{const _=l.current[0],z=l.current[n.length-1],S=_?.parentElement;!S||!_||!z||(d(S.scrollLeft>0),h(S.scrollLeft<S.scrollWidth-S.clientWidth-1))},[n.length]);return le.useEffect(v,[v]),le.useEffect(()=>{const _=l.current[o];if(!_)return;const z=_.parentElement;z&&(z.scrollTo({left:_.offsetLeft-40,behavior:"smooth"}),requestAnimationFrame(v))},[o,v]),x.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,minWidth:0},children:[u&&x.jsx(Ef,{direction:"left",onClick:()=>i(Math.max(0,o-1))}),x.jsx(kk,{onScroll:v,style:{display:"flex",gap:4,overflowX:"auto",minWidth:0,flex:1,cursor:"grab"},role:"tablist","aria-label":"Kanban columns",children:n.map((_,z)=>{const S=z===o;return x.jsxs("button",{ref:j=>{l.current[z]=j},type:"button",role:"tab","aria-selected":S,"aria-controls":`kanban-panel-${_.id}`,onClick:()=>i(z),style:{...at.button,padding:"7px 14px 6px",fontSize:12,fontWeight:S?700:500,color:S?N.text.primary:N.text.muted,background:S?N.bg.surface:"transparent",borderColor:S?"transparent":N.border,borderBottomWidth:2,borderBottomColor:S?_.color:"transparent",borderRadius:S?"6px 6px 0 0":"6px",display:"flex",alignItems:"center",gap:6,whiteSpace:"nowrap",flexShrink:0},children:[x.jsx("span",{"aria-hidden":"true",style:{width:8,height:8,borderRadius:"50%",background:_.color,flexShrink:0}}),_.label,x.jsx("span",{style:{...at.badge(S?N.text.primary:N.text.muted,S?`${_.color}30`:`${N.text.muted}15`),fontSize:10},children:_.count})]},_.id)})}),f&&x.jsx(Ef,{direction:"right",onClick:()=>i(Math.min(n.length-1,o+1))})]})}function Rk({board:n,inlineError:o,activeDropColumn:i,onMove:l,onDropCard:u,onDragStart:d,onDragEnd:f,onDragOverColumn:h,onTitleClick:v}){const[_,z]=le.useState(typeof window<"u"?window.innerWidth:1200),[S,j]=le.useState(0);le.useEffect(()=>{function A(){z(window.innerWidth)}return window.addEventListener("resize",A),()=>window.removeEventListener("resize",A)},[]);const O=ek(_,n.columns.length),X=tk(S,n.columns.length),$=O?n.columns[X]:null;return x.jsxs("div",{style:{display:"flex",flexDirection:"column",minHeight:600,background:N.bg.root,overflowX:"hidden",width:"100%"},children:[x.jsx(Bi,{}),x.jsxs("div",{style:{padding:"14px 16px",display:"flex",flexDirection:"column",gap:14,minWidth:0},children:[x.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4},children:[x.jsx("div",{style:{fontSize:14,fontWeight:700,color:N.text.primary},children:n.title}),x.jsx("div",{style:{fontSize:11,color:N.text.muted},children:HS(n)})]}),o&&x.jsx(bp,{message:o}),O?x.jsxs(x.Fragment,{children:[x.jsx(Tk,{columns:n.columns,focusIndex:X,onSelect:j}),$&&x.jsxs("div",{id:`kanban-panel-${$.id}`,role:"tabpanel","aria-label":$.label,style:{display:"flex",flexDirection:"column",gap:8,minWidth:0},children:[n.cards.filter(A=>A.columnId===$.id).map(A=>x.jsx(Op,{card:A,allowedTargets:Wa(n,A.columnId),onMove:l,onDragStart:d,onDragEnd:f,onTitleClick:v,enableDrag:!1},A.id)),n.cards.filter(A=>A.columnId===$.id).length===0&&x.jsxs("div",{style:{padding:"20px 12px",textAlign:"center",fontSize:12,color:N.text.muted},children:["No cards in ",$.label]})]})]}):x.jsx("div",{style:{display:"flex",gap:12,alignItems:"flex-start",overflowX:"auto",paddingBottom:8},children:n.columns.map(A=>x.jsx(Ck,{column:A,board:n,cards:n.cards.filter(pe=>pe.columnId===A.id),activeDropColumn:i,onMove:l,onDropCard:u,onDragStart:d,onDragEnd:f,onDragOverColumn:h,onTitleClick:v},A.id))})]})]})}function zf(n){return JSON.parse(n)}function Ik(){const{state:n,hydrateBoard:o,setError:i,startLoading:l,selectCard:u,hydrateDetail:d,closeDetail:f,setDetailError:h}=WS(),[v,_]=le.useState(""),[z,S]=le.useState(null),j=le.useRef([]),O=le.useRef({}),X=le.useRef(!1),$=le.useRef(null),A=le.useRef(null),pe=le.useRef(!1),me=le.useRef(null),ue=le.useRef(!1),J=le.useRef(!1),B=le.useRef(0),Se=le.useRef(null);function Ee(g){$.current=g,o(g)}function nt(g){const I=xr(g);if(!I)throw new Error("No text payload returned by tool call");return JSON.parse(I)}function ut(g){const I=xr(g);if(!I)return"Tool call failed";try{const Z=JSON.parse(I);return String(Z.errorMessage??Z.message??I)}catch{return I}}async function ct(g={}){const I=$.current,Z=YS(I,me.current);if(!GS({board:I,request:Z,visibilityState:typeof document>"u"?"visible":document.visibilityState,dragging:pe.current,processingMove:X.current,queuedMoves:j.current.length,refreshInFlight:ue.current,now:Date.now(),lastRefreshStartedAt:B.current,minIntervalMs:kf},g)||!Z||!Nt.getHostCapabilities()?.serverTools)return!1;ue.current=!0,B.current=Date.now();try{const V=await Nt.callServerTool({name:Z.toolName,arguments:Z.arguments},{timeout:_o});if(V.isError)return!1;const oe=xr(V);return oe?(Ee(zf(oe)),!0):!1}catch{return!1}finally{ue.current=!1}}async function Gt(){if(X.current)return;const{nextMove:g,restQueue:I}=JS(j.current);if(!g)return;if(!$.current){j.current=I;return}j.current=I,X.current=!0;const Z=g.queueId??g.cardId;if(!O.current[Z]){const V=wf($.current,g);O.current[Z]=V.snapshot,Ee(V.board)}try{if(!Nt.getHostCapabilities()?.serverTools)throw new Error("Host does not support proxied server tool calls");const V=await Nt.callServerTool({name:g.moveToolName,arguments:{doctype:g.doctype,card_id:g.cardId,from_column:g.fromColumn,to_column:g.toColumn}},{timeout:_o});if(V.isError){const oe=O.current[Z],ie=la(ut(V));oe&&Ee(aa(oe,{errorMessage:ie})),i(ie),_(ie)}else{const oe=nt(V);if(oe.ok!==!1){if($.current){const ce=BS($.current,{cardId:g.cardId,toColumn:g.toColumn,serverCard:oe.serverCard});Ee(ce),J.current=!0;const ee=ce.columns.find(_e=>_e.id===g.toColumn)?.label??g.toColumn;_(`Moved ${g.cardId} to ${ee}`)}}else{const ce=O.current[Z],ee=la(String(oe.errorMessage??"Move failed"));ce&&Ee(aa(ce,{errorMessage:ee})),i(ee),_(ee)}}}catch(V){const oe=O.current[Z],ie=la(V);oe&&Ee(aa(oe)),i(ie),_(ie)}finally{delete O.current[Z],X.current=!1,j.current.length>0?Gt():J.current&&(J.current=!1,ct({ignoreInterval:!0}))}}function mt(g,I,Z){const V=$.current;if(!V||g.pending||g.columnId===I)return;if(!V.allowedTransitions.find(ee=>ee.allowed&&ee.fromColumn===g.columnId&&ee.toColumn===I)){const ee=`Move to ${Z} is not allowed`;i(ee),_(ee);return}const ie={queueId:crypto.randomUUID(),doctype:V.doctype,moveToolName:V.moveToolName,cardId:g.id,fromColumn:g.columnId,toColumn:I};if(!X.current&&j.current.length===0){const ee=wf(V,ie);O.current[ie.queueId??ie.cardId]=ee.snapshot,Ee(ee.board),_(`Moving ${g.title} to ${Z}`)}else _(`${g.title} queued for ${Z}`);j.current=QS(j.current,ie),Gt()}le.useEffect(()=>{Nt.connect().catch(()=>{i("Failed to connect MCP App host")}),Nt.ontoolinput=g=>{const I=Nt.getHostContext()?.toolInfo?.tool.name;I&&g.arguments&&(me.current={toolName:I,arguments:g.arguments}),$.current||l()},Nt.ontoolresult=g=>{const I=xr(g);if(!I){i("No kanban payload received from tool result");return}try{Ee(zf(I))}catch(Z){i(Z instanceof Error?Z.message:"Failed to parse kanban payload")}},Nt.ontoolinputpartial=()=>{$.current||l()}},[]),le.useEffect(()=>{const g=window.setInterval(()=>{ct()},kf);function I(){ct({ignoreInterval:!0})}function Z(){document.visibilityState==="visible"&&ct({ignoreInterval:!0})}return window.addEventListener("focus",I),document.addEventListener("visibilitychange",Z),()=>{window.clearInterval(g),window.removeEventListener("focus",I),document.removeEventListener("visibilitychange",Z)}},[]),le.useEffect(()=>{$.current=n.board},[n.board]);function dt(g,I){A.current=g.id,pe.current=!0,I.dataTransfer.effectAllowed="move",I.dataTransfer.setData("application/json",JSON.stringify({cardId:g.id,fromColumn:g.columnId,title:g.title}))}function Ct(){A.current=null,pe.current=!1,S(null)}function Ot(g,I){const Z=$.current,V=A.current;if(!Z||!V||!KS(Z,V,g)){S(null);return}I.preventDefault(),S(g)}function rt(g,I){I.preventDefault(),S(null);try{const Z=I.dataTransfer.getData("application/json");if(!Z||!$.current)return;const V=JSON.parse(Z),oe=$.current.cards.find(ce=>ce.id===V.cardId),ie=$.current.columns.find(ce=>ce.id===g)?.label??g;oe&&mt(oe,g,ie)}catch{i("Failed to read dragged kanban card")}}function je(g){if(!$.current)return;const I=g.id;Se.current=I,u(I),(async()=>{try{const Z=await Nt.callServerTool({name:"erpnext_doc_get",arguments:{doctype:$.current.doctype,name:I}},{timeout:_o});if(Se.current!==I)return;if(Z.isError){h(ut(Z));return}const V=xr(Z);if(!V){h("No detail payload returned");return}d(xf(JSON.parse(V)))}catch(Z){if(Se.current!==I)return;h(Z instanceof Error?Z.message:"Failed to fetch detail")}})()}async function U(g){try{await Nt.sendMessage({role:"user",content:[{type:"text",text:g}]})}catch{}}async function re(g,I,Z){const V={},oe=n.detail.cardDetail;for(const[ee,_e]of Object.entries(Z))if(typeof oe?.[ee]=="number"){const $n=Number(_e);V[ee]=Number.isFinite($n)?$n:_e}else V[ee]=_e;const ie=await Nt.callServerTool({name:"erpnext_doc_update",arguments:{doctype:g,name:I,data:V}},{timeout:_o});if(ie.isError)throw new Error(ut(ie));const ce=await Nt.callServerTool({name:"erpnext_doc_get",arguments:{doctype:g,name:I}},{timeout:_o});if(!ce.isError){const ee=xr(ce);ee&&d(xf(JSON.parse(ee)))}ct({ignoreInterval:!0})}if(n.loading)return x.jsxs("div",{style:{minHeight:600,background:N.bg.root},children:[x.jsx(Bi,{}),x.jsx(xk,{})]});const q=US(n);return q.blockingError?x.jsxs("div",{style:{minHeight:600,background:N.bg.root},children:[x.jsx(Bi,{}),x.jsx(bp,{message:q.blockingError})]}):n.board?x.jsxs(x.Fragment,{children:[x.jsx("div",{"aria-live":"polite",style:Sk(),children:v}),x.jsx(Rk,{board:n.board,inlineError:q.inlineError,activeDropColumn:z,onMove:mt,onDropCard:rt,onDragStart:dt,onDragEnd:Ct,onDragOverColumn:Ot,onTitleClick:je}),n.detail.selectedCardId&&n.board&&x.jsx(wk,{detail:n.detail,board:n.board,onClose:f,onMove:mt,onSave:re,onNavigate:U})]}):x.jsxs("div",{style:{minHeight:600,background:N.bg.root},children:[x.jsx(Bi,{}),x.jsx(Ek,{})]})}Fm.createRoot(document.getElementById("app")).render(x.jsx(Ik,{}));</script>
123
- <style rel="stylesheet" crossorigin>:root{--accent: #0089FF;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
- </head>
125
- <body>
126
- <div id="app"></div>
127
- </body>
123
+ <style rel="stylesheet" crossorigin>:root{--accent: #0089ff;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
+ </head>
125
+ <body>
126
+ <div id="app"></div>
127
+ </body>
128
128
  </html>
@@ -1,10 +1,10 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>KPI - mcp-erpnext</title>
7
- <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))a(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const d of f.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&a(d)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function a(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();var Jl={exports:{}},mo={},Kl={exports:{}},ee={};/**
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>KPI - mcp-erpnext</title>
7
+ <script type="module" crossorigin>(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))a(u);new MutationObserver(u=>{for(const f of u)if(f.type==="childList")for(const d of f.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&a(d)}).observe(document,{childList:!0,subtree:!0});function i(u){const f={};return u.integrity&&(f.integrity=u.integrity),u.referrerPolicy&&(f.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?f.credentials="include":u.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function a(u){if(u.ep)return;u.ep=!0;const f=i(u);fetch(u.href,f)}})();var Jl={exports:{}},mo={},Kl={exports:{}},ee={};/**
8
8
  * @license React
9
9
  * react.production.min.js
10
10
  *
@@ -120,9 +120,9 @@ Boolean requesting whether a visible border and background is provided by the ho
120
120
  - "model": Tool visible to and callable by the agent
121
121
  - "app": Tool callable by the app from this server only`)});T({mimeTypes:G(z()).optional().describe('Array of supported MIME types for UI resources.\nMust include `"text/html;profile=mcp-app"` for MCP Apps support.')});T({method:S("ui/download-file"),params:T({contents:G(ie([up,cp])).describe("Resource contents to download — embedded (inline data) or linked (host fetches). Uses standard MCP resource types.")})});T({method:S("ui/message"),params:T({role:S("user").describe('Message role, currently only "user" is supported.'),content:G(Co).describe("Message content blocks (text, image, etc.).")})});T({method:S("ui/notifications/sandbox-resource-ready"),params:T({html:z().describe("HTML content to load into the inner iframe."),sandbox:z().optional().describe("Optional override for the inner iframe's sandbox attribute."),csp:ja.optional().describe("CSP configuration from resource metadata."),permissions:Da.optional().describe("Sandbox permissions from resource metadata.")})});var vk=T({method:S("ui/notifications/tool-result"),params:ts.describe("Standard MCP tool execution result.")}),hp=T({toolInfo:T({id:ko.optional().describe("JSON-RPC id of the tools/call request."),tool:La.describe("Tool definition including name, inputSchema, etc.")}).optional().describe("Metadata of the tool call that instantiated this App."),theme:tk.optional().describe("Current color theme preference."),styles:dk.optional().describe("Style configuration for theming the app."),displayMode:_o.optional().describe("How the UI is currently displayed."),availableDisplayModes:G(_o).optional().describe("Display modes the host supports."),containerDimensions:ie([T({height:ne().describe("Fixed container height in pixels.")}),T({maxHeight:ie([ne(),oa()]).optional().describe("Maximum container height in pixels.")})]).and(ie([T({width:ne().describe("Fixed container width in pixels.")}),T({maxWidth:ie([ne(),oa()]).optional().describe("Maximum container width in pixels.")})])).optional().describe(`Container dimensions. Represents the dimensions of the iframe or other
122
122
  container holding the app. Specify either width or maxWidth, and either height or maxHeight.`),locale:z().optional().describe("User's language and region preference in BCP 47 format."),timeZone:z().optional().describe("User's timezone in IANA format."),userAgent:z().optional().describe("Host application identifier."),platform:ie([S("web"),S("desktop"),S("mobile")]).optional().describe("Platform type for responsive design decisions."),deviceCapabilities:T({touch:ke().optional().describe("Whether the device supports touch input."),hover:ke().optional().describe("Whether the device supports hover interactions.")}).optional().describe("Device input capabilities."),safeAreaInsets:T({top:ne().describe("Top safe area inset in pixels."),right:ne().describe("Right safe area inset in pixels."),bottom:ne().describe("Bottom safe area inset in pixels."),left:ne().describe("Left safe area inset in pixels.")}).optional().describe("Mobile safe area boundaries in pixels.")}).passthrough(),yk=T({method:S("ui/notifications/host-context-changed"),params:hp.describe("Partial context update containing only changed fields.")});T({method:S("ui/update-model-context"),params:T({content:G(Co).optional().describe("Context content blocks (text, image, etc.)."),structuredContent:ve(z(),ye().describe("Structured content for machine-readable context data.")).optional().describe("Structured content for machine-readable context data.")})});T({method:S("ui/initialize"),params:T({appInfo:Xi.describe("App identification (name and version)."),appCapabilities:hk.describe("Features and capabilities this app provides."),protocolVersion:z().describe("Protocol version this app supports.")})});var _k=T({protocolVersion:z().describe('Negotiated protocol version string (e.g., "2025-11-21").'),hostInfo:Xi.describe("Host application identification and version."),hostCapabilities:pk.describe("Features and capabilities provided by the host."),hostContext:hp.describe("Rich context about the host environment.")}).passthrough();class wk extends Gw{_appInfo;_capabilities;options;_hostCapabilities;_hostInfo;_hostContext;constructor(o,i={},a={autoResize:!0}){super(a),this._appInfo=o,this._capabilities=i,this.options=a,this.setRequestHandler(es,u=>(console.log("Received ping:",u.params),{})),this.onhostcontextchanged=()=>{}}getHostCapabilities(){return this._hostCapabilities}getHostVersion(){return this._hostInfo}getHostContext(){return this._hostContext}set ontoolinput(o){this.setNotificationHandler(lk,i=>o(i.params))}set ontoolinputpartial(o){this.setNotificationHandler(ak,i=>o(i.params))}set ontoolresult(o){this.setNotificationHandler(vk,i=>o(i.params))}set ontoolcancelled(o){this.setNotificationHandler(uk,i=>o(i.params))}set onhostcontextchanged(o){this.setNotificationHandler(yk,i=>{this._hostContext={...this._hostContext,...i.params},o(i.params)})}set onteardown(o){this.setRequestHandler(fk,(i,a)=>o(i.params,a))}set oncalltool(o){this.setRequestHandler(fp,(i,a)=>o(i.params,a))}set onlisttools(o){this.setRequestHandler(dp,(i,a)=>o(i.params,a))}assertCapabilityForMethod(o){}assertRequestHandlerCapability(o){switch(o){case"tools/call":case"tools/list":if(!this._capabilities.tools)throw Error(`Client does not support tool capability (required for ${o})`);return;case"ping":case"ui/resource-teardown":return;default:throw Error(`No handler for method ${o} registered`)}}assertNotificationCapability(o){}assertTaskCapability(o){throw Error("Tasks are not supported in MCP Apps")}assertTaskHandlerCapability(o){throw Error("Task handlers are not supported in MCP Apps")}async callServerTool(o,i){if(typeof o=="string")throw Error(`callServerTool() expects an object as its first argument, but received a string ("${o}"). Did you mean: callServerTool({ name: "${o}", arguments: { ... } })?`);return await this.request({method:"tools/call",params:o},ts,i)}async readServerResource(o,i){return await this.request({method:"resources/read",params:o},ap,i)}async listServerResources(o,i){return await this.request({method:"resources/list",params:o},lp,i)}sendMessage(o,i){return this.request({method:"ui/message",params:o},sk,i)}sendLog(o){return this.notification({method:"notifications/message",params:o})}updateModelContext(o,i){return this.request({method:"ui/update-model-context",params:o},wa,i)}openLink(o,i){return this.request({method:"ui/open-link",params:o},ok,i)}sendOpenLink=this.openLink;downloadFile(o,i){return this.request({method:"ui/download-file",params:o},ik,i)}requestDisplayMode(o,i){return this.request({method:"ui/request-display-mode",params:o},mk,i)}sendSizeChanged(o){return this.notification({method:"ui/notifications/size-changed",params:o})}setupSizeChangedNotifications(){let o=!1,i=0,a=0,u=()=>{o||(o=!0,requestAnimationFrame(()=>{o=!1;let d=document.documentElement,h=d.style.width,v=d.style.height;d.style.width="fit-content",d.style.height="max-content";let k=d.getBoundingClientRect();d.style.width=h,d.style.height=v;let C=window.innerWidth-d.clientWidth,R=Math.ceil(k.width+C),$=Math.ceil(k.height);(R!==i||$!==a)&&(i=R,a=$,this.sendSizeChanged({width:R,height:$}))}))};u();let f=new ResizeObserver(u);return f.observe(document.documentElement),f.observe(document.body),()=>f.disconnect()}async connect(o=new ek(window.parent,window.parent),i){if(this.transport)throw Error("App is already connected. Call close() before connecting again.");await super.connect(o);try{let a=await this.request({method:"ui/initialize",params:{appCapabilities:this._capabilities,appInfo:this._appInfo,protocolVersion:Yw}},_k,i);if(a===void 0)throw Error(`Server sent invalid initialize result: ${a}`);this._hostCapabilities=a.hostCapabilities,this._hostInfo=a.hostInfo,this._hostContext=a.hostContext,await this.notification({method:"ui/notifications/initialized"}),this.options?.autoResize&&this.setupSizeChangedNotifications()}catch(a){throw this.close(),a}}}function Bn(n){return`var(${n})`}const wr={bg:{surface:Bn("--bg-surface")},text:{muted:Bn("--text-muted"),faint:Bn("--text-faint")},accent:Bn("--accent"),border:Bn("--border")},En={sans:Bn("--font-sans"),mono:Bn("--font-mono")};function la(n,o=2){return n.toLocaleString("en-US",{minimumFractionDigits:o,maximumFractionDigits:o})}function kk(n,o="USD"){return n.toLocaleString("en-US",{style:"currency",currency:o,minimumFractionDigits:2,maximumFractionDigits:2})}function Sk(){return te.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[te.jsx("rect",{x:"1",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.9"}),te.jsx("rect",{x:"9",y:"1",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),te.jsx("rect",{x:"1",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.6"}),te.jsx("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.5",fill:"currentColor",opacity:"0.35"})]})}function xk(){const n={display:"flex",alignItems:"center",gap:7,padding:"0 14px",height:30,background:wr.bg.surface,borderBottom:`1px solid ${wr.border}`,flexShrink:0},o={fontFamily:En.sans,fontSize:11,fontWeight:700,letterSpacing:"0.08em",textTransform:"uppercase",color:wr.accent},i={width:3,height:3,borderRadius:"50%",background:wr.text.faint,marginLeft:2,marginRight:2,flexShrink:0},a={fontFamily:En.sans,fontSize:10,color:wr.text.muted,letterSpacing:"0.03em"};return te.jsxs("div",{style:n,children:[te.jsx("div",{style:{color:wr.accent},children:te.jsx(Sk,{})}),te.jsx("span",{style:o,children:"ERPNext"}),te.jsx("div",{style:i}),te.jsx("span",{style:a,children:"gestion ERP"})]})}function zk(n,o={}){return!n.request||n.visibilityState!=="visible"||n.refreshInFlight?!1:o.ignoreInterval?!0:n.now-n.lastRefreshStartedAt>=n.minIntervalMs}function df(n,o){return n?.refreshRequest??o}function Ek(n){return n instanceof Error&&/timed? out/i.test(n.message)?"Refresh timed out":"Refresh failed"}function Tk(n){return n.structuredContent?JSON.stringify(n.structuredContent):n.content?.find(o=>o.type==="text")?.text??null}const Wn=new wk({name:"KPI Viewer",version:"1.0.0"}),Ck=15e3,Pk=1e4;function Rk({data:n,color:o}){if(n.length<2)return null;const i=60,a=24,u=2,f=Math.min(...n),h=Math.max(...n)-f||1,v=n.map((k,C)=>{const R=u+C/(n.length-1)*(i-u*2),$=u+(1-(k-f)/h)*(a-u*2);return`${R},${$}`}).join(" ");return te.jsx("svg",{width:i,height:a,viewBox:`0 0 ${i} ${a}`,style:{flexShrink:0},"aria-hidden":"true",children:te.jsx("polyline",{points:v,fill:"none",stroke:o,strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function Nk({delta:n,deltaLabel:o,trend:i,trendIsGood:a}){const u=i??(n>0?"up":n<0?"down":"flat"),f=u==="up"?"▲":u==="down"?"▼":"◆";let d,h;if(u==="flat")d="var(--text-muted)",h="var(--bg-hover)";else if(a===void 0)d="var(--info)",h="var(--info-dim)";else{const C=u==="up",R=a?C:!C;d=R?"var(--success)":"var(--error)",h=R?"var(--success-dim)":"var(--error-dim)"}const k=`${n>0?"+":""}${la(Math.abs(n),Math.abs(n)<10?1:0)}`;return te.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"2px 8px",fontSize:11,fontWeight:600,fontFamily:En.mono,borderRadius:4,color:d,background:h,letterSpacing:"0.02em"},children:[te.jsx("span",{style:{fontSize:8},children:f}),k,"%",o&&te.jsx("span",{style:{fontWeight:400,fontFamily:En.sans,opacity:.75,marginLeft:2},children:o})]})}function Ik(){return te.jsx("div",{style:{padding:16},children:te.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:10},children:[te.jsx("div",{className:"skeleton",style:{height:12,width:"35%"}}),te.jsx("div",{className:"skeleton",style:{height:36,width:"55%"}}),te.jsx("div",{className:"skeleton",style:{height:16,width:"40%"}})]})})}function Ok({data:n,error:o,refreshing:i,onRefresh:a}){const u=n.color??"var(--accent)",f=Wn.getHostCapabilities()?.serverTools;async function d(k){try{await Wn.sendMessage({role:"user",content:[{type:"text",text:k}]})}catch{}}let h;if(n.formattedValue)h=n.formattedValue;else if(n.currency)h=kk(n.value,n.currency);else if(n.unit==="%")h=`${la(n.value,n.value%1===0?0:1)}%`;else{const k=n.value%1===0?0:2;h=la(n.value,k),n.unit&&(h+=` ${n.unit}`)}const v=n.color??"#60a5fa";return te.jsxs("div",{style:{fontFamily:En.sans,background:"var(--bg-root)",overflow:"hidden"},children:[te.jsx(xk,{}),te.jsx("div",{style:{padding:"12px 16px 14px"},children:te.jsxs("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between"},children:[te.jsxs("div",{style:{flex:1,minWidth:0},children:[te.jsx("div",{style:{fontSize:11,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.06em",color:"var(--text-muted)",marginBottom:6},children:n.label}),te.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:6},children:[te.jsx("button",{onClick:a,disabled:i,style:{border:"1px solid var(--border)",background:"var(--bg-elevated)",color:"var(--text-secondary)",borderRadius:6,padding:"4px 8px",fontSize:11,fontFamily:En.sans,cursor:i?"default":"pointer"},children:i?"Refreshing":"Refresh"}),te.jsx("div",{"aria-live":"polite",style:{fontSize:11,color:o?"var(--error)":i?"var(--text-muted)":"var(--text-faint)"},children:o??(i?"Refreshing…":"Auto-refresh on focus")})]}),te.jsx("div",{onClick:f&&n._drillDown?()=>d(n._drillDown):void 0,style:{fontSize:32,fontWeight:700,fontFamily:En.mono,color:u,lineHeight:1.1,marginBottom:8,cursor:f&&n._drillDown?"pointer":"default",transition:"opacity 0.15s"},onMouseEnter:k=>{n._drillDown&&(k.currentTarget.style.opacity="0.75")},onMouseLeave:k=>{k.currentTarget.style.opacity="1"},title:n._drillDown?"Click to drill down":void 0,children:h}),n.delta!==void 0&&te.jsx(Nk,{delta:n.delta,deltaLabel:n.deltaLabel,trend:n.trend,trendIsGood:n.trendIsGood})]}),n.sparkline&&n.sparkline.length>=2&&te.jsx("div",{style:{paddingTop:20,paddingLeft:12,cursor:f&&n._trendDrillDown?"pointer":"default"},onClick:f&&n._trendDrillDown?()=>d(n._trendDrillDown):void 0,title:n._trendDrillDown?"Click to see trend details":void 0,children:te.jsx(Rk,{data:n.sparkline,color:v})})]})})]})}function $k(){const[n,o]=Qt.useState(null),[i,a]=Qt.useState(!0),[u,f]=Qt.useState(!1),[d,h]=Qt.useState(null),v=Qt.useRef(null),k=Qt.useRef(null),C=Qt.useRef(!1),R=Qt.useRef(0);function $(V){v.current=V,k.current=df(V,k.current),o(V)}function j(V){const K=Tk(V);if(!K)return!1;try{const Re=JSON.parse(K);return $(Re),h(null),a(!1),!0}catch(Re){return console.error("Parse error:",Re),h("Failed to parse KPI payload"),a(!1),!1}}async function X(V={}){const K=df(v.current,k.current);if(!zk({request:K,visibilityState:typeof document>"u"?"visible":document.visibilityState,refreshInFlight:C.current,now:Date.now(),lastRefreshStartedAt:R.current,minIntervalMs:Ck},V)||!K||!Wn.getHostCapabilities()?.serverTools)return!1;C.current=!0,R.current=Date.now(),f(!0);try{const Re=await Wn.callServerTool({name:K.toolName,arguments:K.arguments},{timeout:Pk});return Re.isError?(h("Refresh failed"),!1):j(Re)?!0:(h("Refresh returned no data"),!1)}catch(Re){return h(Ek(Re)),!1}finally{C.current=!1,f(!1)}}return Qt.useEffect(()=>{Wn.connect().catch(()=>{}),Wn.ontoolresult=V=>{j(V)},Wn.ontoolinputpartial=()=>{v.current||a(!0)}},[]),Qt.useEffect(()=>{function V(){X({ignoreInterval:!0})}function K(){document.visibilityState==="visible"&&X({ignoreInterval:!0})}return window.addEventListener("focus",V),document.addEventListener("visibilitychange",K),()=>{window.removeEventListener("focus",V),document.removeEventListener("visibilitychange",K)}},[]),i?te.jsx(Ik,{}):n?te.jsx(Ok,{data:n,error:d,refreshing:u,onRefresh:()=>void X({ignoreInterval:!0})}):te.jsx("div",{style:{padding:32,textAlign:"center",color:"var(--text-muted)",fontSize:13,fontFamily:En.sans},children:"No KPI data — run an analytics KPI tool"})}_m.createRoot(document.getElementById("app")).render(te.jsx($k,{}));</script>
123
- <style rel="stylesheet" crossorigin>:root{--accent: #0089FF;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
- </head>
125
- <body>
126
- <div id="app"></div>
127
- </body>
123
+ <style rel="stylesheet" crossorigin>:root{--accent: #0089ff;--accent-dim: rgba(0, 137, 255, .15);--accent-border: rgba(0, 137, 255, .3);--success: #16a34a;--success-dim: rgba(22, 163, 74, .1);--error: #dc2626;--error-dim: rgba(220, 38, 38, .1);--warning: #d97706;--warning-dim: rgba(217, 119, 6, .1);--info: #2563eb;--info-dim: rgba(37, 99, 235, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;--font-mono: "SF Mono", "Cascadia Code", "Fira Code", monospace;--bg-root: #ffffff;--bg-surface: #f9fafb;--bg-elevated: #f3f4f6;--bg-hover: #e5e7eb;--bg-active: #d1d5db;--text-primary: #111827;--text-secondary: #4b5563;--text-muted: #6b7280;--text-faint: #9ca3af;--border: #e5e7eb;--border-subtle: #f3f4f6;--shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);--shadow-md: 0 2px 8px rgba(0, 0, 0, .08)}@media(prefers-color-scheme:dark){:root{--bg-root: #08080a;--bg-surface: #111113;--bg-elevated: #18181b;--bg-hover: #1f1f23;--bg-active: #27272a;--text-primary: #e7e5e4;--text-secondary: #a8a29e;--text-muted: #78716c;--text-faint: #57534e;--border: #27272a;--border-subtle: #1f1f23;--success: #4ade80;--success-dim: rgba(74, 222, 128, .12);--error: #f87171;--error-dim: rgba(248, 113, 113, .12);--warning: #fbbf24;--warning-dim: rgba(251, 191, 36, .12);--info: #60a5fa;--info-dim: rgba(96, 165, 250, .12);--shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);--shadow-md: 0 2px 8px rgba(0, 0, 0, .4)}}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{border-radius:var(--radius-lg);overflow:hidden}html,body{background:var(--bg-root);color:var(--text-primary);font-family:var(--font-sans);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-faint)}@keyframes pulse{0%,to{opacity:.4}50%{opacity:.15}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.animate-pulse{animation:pulse 1.5s ease-in-out infinite}.skeleton{background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-hover) 50%,var(--bg-elevated) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:var(--radius-sm)}.drag-scroll::-webkit-scrollbar{display:none}.drag-scroll{scrollbar-width:none}article button:hover:not(:disabled){background:var(--bg-hover)!important;color:var(--text-primary)!important}article[draggable=true]:active{cursor:grabbing;opacity:.85}.kanban-detail-backdrop{position:fixed;inset:0;z-index:100;background:#00000073;display:flex;align-items:flex-start;justify-content:center;padding:20px 12px;overflow-y:auto;backdrop-filter:blur(2px)}.kanban-detail-panel{background:var(--bg-root);border:1px solid var(--border);border-radius:10px;max-width:520px;width:100%;box-shadow:0 8px 32px #0000001f,0 2px 8px #0000000f;position:relative;display:flex;flex-direction:column}.kanban-detail-panel .detail-field-row{transition:background .1s}.kanban-detail-panel .detail-field-row:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell{transition:background .1s;border-radius:4px}.kanban-detail-panel .detail-field-cell:hover{background:var(--bg-surface)}.kanban-detail-panel .detail-field-cell:hover input,.kanban-detail-panel .detail-field-cell:hover select{border-color:var(--border)!important;background:var(--bg-elevated)!important}.kanban-detail-panel select:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel input:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}.kanban-detail-panel textarea:focus{border-color:var(--accent)!important;box-shadow:0 0 0 2px var(--accent-dim);outline:none}@media(prefers-color-scheme:dark){.kanban-detail-backdrop{background:#000000a6}.kanban-detail-panel{box-shadow:0 8px 32px #0006,0 2px 8px #0000004d}}.kanban-card-title-link{cursor:pointer;text-decoration:none;color:inherit}.kanban-card-title-link:hover{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}</style>
124
+ </head>
125
+ <body>
126
+ <div id="app"></div>
127
+ </body>
128
128
  </html>