@miiflow/assistant-ui 0.9.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +0,0 @@
1
- import {$getRoot,KEY_ENTER_COMMAND,COMMAND_PRIORITY_HIGH,DecoratorNode,$isTextNode,$createTextNode,$isElementNode}from'lexical';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {useLexicalComposerContext}from'@lexical/react/LexicalComposerContext';import {LexicalTypeaheadMenuPlugin,MenuOption}from'@lexical/react/LexicalTypeaheadMenuPlugin';import {forwardRef,useMemo,useRef,useEffect,useCallback,useImperativeHandle,useState,useLayoutEffect}from'react';import {createPortal}from'react-dom';import {LexicalComposer}from'@lexical/react/LexicalComposer';import {ContentEditable}from'@lexical/react/LexicalContentEditable';import {LexicalErrorBoundary}from'@lexical/react/LexicalErrorBoundary';import {HistoryPlugin}from'@lexical/react/LexicalHistoryPlugin';import {OnChangePlugin}from'@lexical/react/LexicalOnChangePlugin';import {RichTextPlugin}from'@lexical/react/LexicalRichTextPlugin';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';var Z="color-mix(in srgb, currentColor 16%, transparent)",j="color-mix(in srgb, currentColor 8%, transparent)",ee="color-mix(in srgb, currentColor 6%, transparent)",te="color-mix(in srgb, currentColor 12%, transparent)",W={flexShrink:0,display:"inline-flex",alignItems:"center",fontSize:10,fontWeight:700,letterSpacing:.5,textTransform:"uppercase",padding:"2px 5px",borderRadius:3,background:Z,lineHeight:1};function N({id:t,kind:e,label:n,description:l,icon:r,tag:i,variant:u="chip",selected:c=false,onMouseEnter:f,onMouseDown:C,htmlId:m}){let g=n??t,x=i!==void 0?jsx("span",{style:{display:"inline-flex",flexShrink:0,alignItems:"center"},children:i}):jsx("span",{style:W,children:e});return u==="chip"?jsxs("span",{"data-chat-command-chip":"true","data-command-id":t,"data-command-kind":e,title:`${e}: ${t}`,style:{display:"inline-flex",alignItems:"center",gap:5,verticalAlign:"middle",background:j,borderRadius:999,padding:"2px 9px 2px 4px",margin:"0 1px",whiteSpace:"nowrap",fontWeight:500,lineHeight:1},children:[x,r&&jsx("span",{style:{display:"inline-flex",flexShrink:0},children:r}),jsx("span",{children:g})]}):jsxs("div",{role:"option","aria-selected":c,id:m,onMouseEnter:f,onMouseDown:C,"data-command-id":t,"data-command-kind":e,style:{display:"flex",alignItems:"center",gap:8,padding:"6px 8px",borderRadius:6,cursor:"pointer",background:c?te:"transparent",transition:"background 80ms ease"},onMouseOver:a=>{c||(a.currentTarget.style.background=ee);},onMouseOut:a=>{c||(a.currentTarget.style.background="transparent");},children:[jsx("span",{style:W,children:e}),r&&jsx("span",{style:{display:"inline-flex",flexShrink:0},children:r}),jsxs("div",{style:{flex:1,minWidth:0,lineHeight:1.3},children:[jsx("div",{style:{fontSize:12,fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:g}),l&&jsx("div",{style:{fontSize:11,opacity:.65,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l})]})]})}var $="data-chat-command-token",L="/",_=class t extends DecoratorNode{constructor(e,n,l,r=L,i){super(i),this.__id=e,this.__kind=n,this.__label=l,this.__prefix=r;}static getType(){return "command-token"}static clone(e){return new t(e.__id,e.__kind,e.__label,e.__prefix,e.__key)}static importJSON(e){return new t(e.commandId,e.commandKind,e.commandLabel,e.commandPrefix??L)}exportJSON(){return {...super.exportJSON(),commandId:this.__id,commandKind:this.__kind,commandLabel:this.__label,commandPrefix:this.__prefix,type:"command-token",version:2}}getCommandId(){return this.__id}getCommandKind(){return this.__kind}getCommandLabel(){return this.__label}getCommandPrefix(){return this.__prefix}getEncodedText(){return `${this.__prefix}${this.__id}:${this.__kind}`}createDOM(){let e=document.createElement("span");return e.setAttribute($,"true"),e}updateDOM(){return false}exportDOM(){let e=document.createElement("span");return e.setAttribute($,"true"),e.setAttribute("data-command-id",this.__id),e.setAttribute("data-command-kind",this.__kind),e.setAttribute("data-command-prefix",this.__prefix),e.textContent=this.getEncodedText(),{element:e}}static importDOM(){return {span:e=>e.hasAttribute($)?{conversion:oe,priority:1}:null}}decorate(){return jsx("span",{contentEditable:false,style:{userSelect:"none"},children:jsx(N,{id:this.__id,kind:this.__kind,label:this.__label,variant:"chip"})})}isInline(){return true}isKeyboardSelectable(){return true}getTextContent(){return this.getEncodedText()}};function oe(t){let e=t.getAttribute("data-command-id"),n=t.getAttribute("data-command-kind");if(!e||!n)return null;let l=t.getAttribute("data-command-prefix")??L,r=t.textContent?.replace(new RegExp(`^[\\${l}]`),"")??e;return {node:I(e,n,r,l)}}function I(t,e,n,l=L){return new _(t,e,n,l)}function S(t){return t instanceof _}var H=/(^|\s|\(|\[)([/@])([^\n:]+?):([\w-]+)(?=$|[\s.,!?)\]])/g;function re(t){let e=[];H.lastIndex=0;let n;for(;(n=H.exec(t))!==null;){let l=n[1]??"",r=n[2],i=n[3],u=n[4],c=n.index+l.length,f=n[0].slice(l.length);e.push({id:i,kind:u,prefix:r,raw:f,index:c,endIndex:c+f.length});}return e}var ge="/",xe=75,K=class extends MenuOption{constructor(e){super(`${e.kind}:${e.id}`),this.command=e;}};function Ce(t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|\\s|\\()(${e}((?:[^${e}\\s]){0,${xe}}))$`)}function z({commandProvider:t,menuRenderer:e,onMenuStateChange:n}){let[l]=useLexicalComposerContext(),[r,i]=useState(null),[u,c]=useState([]),f=t?.trigger??ge,C=useMemo(()=>Ce(f),[f]);useEffect(()=>{n?.(r!=null);},[r,n]),useEffect(()=>{if(!t||r==null){c([]);return}let s=false;return Promise.resolve(t.fetch(r)).then(d=>{s||c(d);}),()=>{s=true;}},[t,r]);let m=useMemo(()=>u.map(s=>new K(s)),[u]),g=useCallback(s=>{let d=C.exec(s);if(!d)return null;let o=d[1]??"",p=d[3]??"";return {leadOffset:d.index+o.length,matchingString:p,replaceableString:d[2]??""}},[C]),x=t?.singletonKinds,a=useCallback((s,d,o)=>{l.update(()=>{let p=s.command.kind;if(x?.includes(p)??false){let w=[],R=h=>{if(S(h)&&h.getCommandKind()===p){w.push({node:h,index:0});return}if($isElementNode(h))for(let v of h.getChildren())R(v);};R($getRoot());for(let h of w){let v=h.node.getNextSibling();if(h.node.remove(),v&&$isTextNode(v)){let G=v.getTextContent();if(G.startsWith(" ")){let V=G.slice(1);V.length===0?v.remove():v.setTextContent(V);}}}}let E=I(s.command.id,p,s.command.label,f),k=$createTextNode(" ");d&&d.replace(E).insertAfter(k),k.select(),o();});},[l,f,x]);return t?jsx(LexicalTypeaheadMenuPlugin,{onQueryChange:i,onSelectOption:a,triggerFn:g,options:m,menuRenderFn:(s,{selectedIndex:d,selectOptionAndCleanUp:o,setHighlightedIndex:p})=>e?jsx(Fragment,{children:e({anchorElement:s.current,options:u,selectedIndex:d??0,setSelectedIndex:p,selectOption:b=>{let E=m.find(k=>k.command.id===b.id&&k.command.kind===b.kind);E&&o(E);},closeMenu:()=>i(null)})}):jsx(he,{anchorElement:s.current,options:m,selectedIndex:d??0,setHighlightedIndex:p,selectOptionAndCleanUp:o,visible:u.length>0||r!=null,queryString:r})}):null}function he({anchorElement:t,options:e,selectedIndex:n,setHighlightedIndex:l,selectOptionAndCleanUp:r,visible:i,queryString:u}){let c=useRef(null),[f,C]=useState(false),m=6;if(useEffect(()=>{let a=c.current;if(!a||e.length===0)return;let s=a.querySelector(`#command-typeahead-item-${n}`);if(!s)return;let d=a.getBoundingClientRect(),o=s.getBoundingClientRect();o.top<d.top?a.scrollTop-=d.top-o.top:o.bottom>d.bottom&&(a.scrollTop+=o.bottom-d.bottom);},[n,e.length]),useLayoutEffect(()=>{if(!t||!i||!c.current)return;let a=()=>{let s=c.current;if(!s)return;let d=t.getBoundingClientRect(),o=s.offsetHeight,b=window.innerHeight-d.top,k=d.top-d.height,w=o+m>b,R=o+m<=k;C(w&&R);};return a(),window.addEventListener("resize",a),window.addEventListener("scroll",a,true),()=>{window.removeEventListener("resize",a),window.removeEventListener("scroll",a,true);}},[t,i,e.length]),!t||!i)return null;let g=t.offsetHeight||20,x=f?`translateY(calc(-100% - ${g+m}px))`:"none";return createPortal(jsx("div",{ref:c,role:"listbox",style:{position:"absolute",top:0,left:0,transform:x,zIndex:99999,minWidth:320,maxWidth:520,maxHeight:280,overflowY:"auto",borderRadius:8,border:"1px solid rgba(0,0,0,0.1)",background:"#ffffff",boxShadow:"0 8px 24px rgba(0,0,0,0.15)",padding:4,fontSize:12,color:"#1f2937"},children:e.length===0?jsxs("div",{style:{padding:"6px 10px",fontSize:11,color:"#6b7280"},children:["No matching commands",u?` for "${u}"`:""]}):e.map((a,s)=>{let d=s===n,o=a.command;return jsx(N,{variant:"row",id:o.id,kind:o.kind,label:o.label,description:o.description,icon:o.icon,selected:d,htmlId:`command-typeahead-item-${s}`,onMouseEnter:()=>l(s),onMouseDown:p=>{p.preventDefault(),p.stopPropagation(),l(s),r(a);}},a.key)})}),t)}function O(...t){return twMerge(clsx(t))}var He={paragraph:"chat-composer-paragraph"};function q(t){let e="",n=[];return t.getEditorState().read(()=>{let l=$getRoot();e=l.getTextContent();let r=i=>{if(S(i)&&n.push({id:i.getCommandId(),kind:i.getCommandKind(),label:i.getCommandLabel()}),$isElementNode(i))for(let u of i.getChildren())r(u);};r(l);}),{text:e,tokens:n}}var De=forwardRef(function({placeholder:e="Type a message...",disabled:n=false,className:l,inputClassName:r,children:i,onChange:u,onSubmit:c,commandProvider:f,commandProviders:C},m){let g=useMemo(()=>({namespace:"ChatComposer",theme:He,nodes:[_],editable:!n,onError:x=>{console.error("[chat-ui composer]",x);}}),[]);return jsx(LexicalComposer,{initialConfig:g,children:jsx(Ae,{placeholder:e,disabled:n,className:l,inputClassName:r,onChange:u,onSubmit:c,commandProvider:f,commandProviders:C,imperativeHandle:m,children:i})})});function Ae({placeholder:t,disabled:e,className:n,inputClassName:l,children:r,onChange:i,onSubmit:u,commandProvider:c,commandProviders:f,imperativeHandle:C}){let[m]=useLexicalComposerContext(),g=useRef(u);g.current=u;let x=useRef(false);useEffect(()=>{m.setEditable(!e);},[m,e]);let a=useCallback(()=>{let o=q(m);o.text.trim().length===0&&o.tokens.length===0||g.current(o);},[m]);useImperativeHandle(C,()=>({clear:()=>{m.update(()=>{$getRoot().clear();});},submit:a,focus:()=>m.focus()}),[m,a]),useEffect(()=>m.registerCommand(KEY_ENTER_COMMAND,o=>{if(x.current)return false;let p=o;return p?.shiftKey?false:(p?.preventDefault(),a(),true)},COMMAND_PRIORITY_HIGH),[m,a]);let s=useCallback(o=>{x.current=o;},[]),d=useCallback(o=>{if(!i)return;let p=q(m);i(p);},[m,i]);return jsxs("div",{className:O("relative w-full",n),children:[jsx(RichTextPlugin,{contentEditable:jsx(ContentEditable,{className:O("outline-none w-full text-sm leading-relaxed","min-h-[24px] max-h-[200px] overflow-y-auto","text-gray-900 dark:text-zinc-100",e&&"opacity-50 cursor-not-allowed",l)}),placeholder:jsx("div",{className:O("pointer-events-none absolute top-0 left-0 text-sm text-gray-400 dark:text-zinc-500","select-none"),children:t}),ErrorBoundary:LexicalErrorBoundary}),jsx(OnChangePlugin,{onChange:d}),jsx(HistoryPlugin,{}),(f&&f.length>0?f:c?[c]:[]).map((p,b)=>jsx(z,{commandProvider:p,onMenuStateChange:s},`${p.trigger??"/"}-${b}`)),r]})}export{O as a,N as b,_ as c,I as d,S as e,H as f,re as g,z as h,De as i};//# sourceMappingURL=chunk-IUCKTDTZ.js.map
2
- //# sourceMappingURL=chunk-IUCKTDTZ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/composer/CommandTokenView.tsx","../src/composer/CommandTokenNode.tsx","../src/composer/CommandTokenPlugin.tsx","../src/utils/cn.ts","../src/composer/LexicalChatInput.tsx"],"names":["TAG_BG","CHIP_BG","ROW_HOVER_BG","ROW_SELECTED_BG","tagStyle","CommandTokenView","id","kind","label","description","icon","tag","variant","selected","onMouseEnter","onMouseDown","htmlId","display","tagNode","jsx","jsxs","e","TOKEN_DATA_ATTR","DEFAULT_PREFIX","CommandTokenNode","_CommandTokenNode","DecoratorNode","prefix","key","node","serialized","span","element","domNode","convertCommandTokenElement","$createCommandTokenNode","$isCommandTokenNode","COMMAND_TOKEN_REGEX","findInlineCommandTokens","text","matches","m","leading","start","raw","DEFAULT_TRIGGER","QUERY_LENGTH_LIMIT","CommandTypeaheadOption","MenuOption","command","buildTriggerRegex","trigger","escaped","CommandTokenPlugin","commandProvider","menuRenderer","onMenuStateChange","editor","useLexicalComposerContext","queryString","setQueryString","useState","results","setResults","triggerRegex","useMemo","useEffect","cancelled","cmds","options","cmd","checkForMatch","useCallback","match","matchingString","singletonKinds","onSelectOption","selectedOption","nodeToReplace","closeMenu","stale","walk","n","$isElementNode","c","$getRoot","entry","next","$isTextNode","nextText","trimmed","tokenNode","trailingSpace","$createTextNode","LexicalTypeaheadMenuPlugin","anchorElementRef","selectedIndex","selectOptionAndCleanUp","setHighlightedIndex","Fragment","option","o","DefaultCommandMenu","anchorElement","visible","menuRef","useRef","flipped","setFlipped","VERTICAL_GAP","menu","selectedEl","menuRect","itemRect","useLayoutEffect","reposition","menuEl","anchorRect","menuHeight","spaceBelow","spaceAbove","wouldOverflowBottom","fitsAbove","anchorHeight","transform","createPortal","i","isSelected","cn","inputs","twMerge","clsx","EDITOR_THEME","readPayload","tokens","root","collect","child","LexicalChatInput","forwardRef","placeholder","disabled","className","inputClassName","children","onChange","onSubmit","commandProviders","ref","initialConfig","error","LexicalComposer","ChatInputBody","imperativeHandle","onSubmitRef","commandMenuOpenRef","submit","payload","useImperativeHandle","KEY_ENTER_COMMAND","event","keyboard","COMMAND_PRIORITY_HIGH","handleCommandMenuStateChange","isOpen","handleChange","_state","RichTextPlugin","ContentEditable","LexicalErrorBoundary","OnChangePlugin","HistoryPlugin"],"mappings":"67BAyCA,IAAMA,CAAAA,CAAS,mDAAA,CACTC,CAAAA,CAAU,kDAAA,CACVC,EAAAA,CAAe,kDAAA,CACfC,EAAAA,CAAkB,mDAAA,CAElBC,CAAAA,CAA0B,CAC9B,UAAA,CAAY,CAAA,CACZ,OAAA,CAAS,aAAA,CACT,UAAA,CAAY,QAAA,CACZ,QAAA,CAAU,EAAA,CACV,UAAA,CAAY,GAAA,CACZ,aAAA,CAAe,EAAA,CACf,aAAA,CAAe,WAAA,CACf,OAAA,CAAS,SAAA,CACT,YAAA,CAAc,CAAA,CACd,UAAA,CAAYJ,CAAAA,CACZ,UAAA,CAAY,CACd,CAAA,CAEO,SAASK,CAAAA,CAAiB,CAC/B,EAAA,CAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,GAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CAAU,MAAA,CACV,SAAAC,CAAAA,CAAW,KAAA,CACX,YAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,MAAA,CAAAC,CACF,CAAA,CAA0B,CACxB,IAAMC,CAAAA,CAAUT,CAAAA,EAASF,CAAAA,CAKnBY,CAAAA,CACJP,CAAAA,GAAQ,MAAA,CACNQ,GAAAA,CAAC,MAAA,CAAA,CAAK,KAAA,CAAO,CAAE,OAAA,CAAS,aAAA,CAAe,UAAA,CAAY,CAAA,CAAG,UAAA,CAAY,QAAS,CAAA,CAAI,QAAA,CAAAR,CAAAA,CAAI,CAAA,CAEnFQ,GAAAA,CAAC,QAAK,KAAA,CAAOf,CAAAA,CAAW,QAAA,CAAAG,CAAAA,CAAK,CAAA,CAGjC,OAAIK,CAAAA,GAAY,MAAA,CAEZQ,IAAAA,CAAC,MAAA,CAAA,CACC,wBAAA,CAAuB,MAAA,CACvB,iBAAA,CAAiBd,CAAAA,CACjB,mBAAA,CAAmBC,CAAAA,CACnB,KAAA,CAAO,CAAA,EAAGA,CAAI,CAAA,EAAA,EAAKD,CAAE,CAAA,CAAA,CACrB,KAAA,CAAO,CACL,OAAA,CAAS,aAAA,CACT,UAAA,CAAY,QAAA,CACZ,GAAA,CAAK,CAAA,CACL,aAAA,CAAe,QAAA,CACf,WAAYL,CAAAA,CACZ,YAAA,CAAc,GAAA,CACd,OAAA,CAAS,iBAAA,CACT,MAAA,CAAQ,OAAA,CACR,UAAA,CAAY,QAAA,CACZ,UAAA,CAAY,GAAA,CACZ,UAAA,CAAY,CACd,CAAA,CAEC,QAAA,CAAA,CAAAiB,CAAAA,CACAR,CAAAA,EACCS,GAAAA,CAAC,MAAA,CAAA,CAAK,KAAA,CAAO,CAAE,OAAA,CAAS,aAAA,CAAe,UAAA,CAAY,CAAE,CAAA,CAAI,QAAA,CAAAT,CAAAA,CAAK,CAAA,CAEhES,GAAAA,CAAC,MAAA,CAAA,CAAM,QAAA,CAAAF,CAAAA,CAAQ,CAAA,CAAA,CACjB,CAAA,CAMFG,IAAAA,CAAC,KAAA,CAAA,CACC,IAAA,CAAK,QAAA,CACL,eAAA,CAAeP,CAAAA,CACf,EAAA,CAAIG,CAAAA,CACJ,YAAA,CAAcF,CAAAA,CACd,WAAA,CAAaC,CAAAA,CACb,iBAAA,CAAiBT,CAAAA,CACjB,mBAAA,CAAmBC,CAAAA,CACnB,KAAA,CAAO,CACL,OAAA,CAAS,MAAA,CACT,UAAA,CAAY,QAAA,CACZ,GAAA,CAAK,CAAA,CACL,OAAA,CAAS,SAAA,CACT,YAAA,CAAc,CAAA,CACd,MAAA,CAAQ,UACR,UAAA,CAAYM,CAAAA,CAAWV,EAAAA,CAAkB,aAAA,CACzC,UAAA,CAAY,sBACd,CAAA,CACA,WAAA,CAAckB,CAAAA,EAAM,CACbR,CAAAA,GACFQ,CAAAA,CAAE,aAAA,CAAiC,KAAA,CAAM,UAAA,CAAanB,EAAAA,EAE3D,CAAA,CACA,UAAA,CAAamB,CAAAA,EAAM,CACZR,CAAAA,GACFQ,CAAAA,CAAE,aAAA,CAAiC,KAAA,CAAM,UAAA,CAAa,aAAA,EAE3D,CAAA,CAEA,QAAA,CAAA,CAAAF,GAAAA,CAAC,MAAA,CAAA,CAAK,KAAA,CAAOf,CAAAA,CAAW,SAAAG,CAAAA,CAAK,CAAA,CAC5BG,CAAAA,EACCS,GAAAA,CAAC,MAAA,CAAA,CAAK,KAAA,CAAO,CAAE,OAAA,CAAS,aAAA,CAAe,UAAA,CAAY,CAAE,CAAA,CAAI,QAAA,CAAAT,CAAAA,CAAK,CAAA,CAEhEU,IAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,IAAA,CAAM,CAAA,CAAG,QAAA,CAAU,CAAA,CAAG,UAAA,CAAY,GAAI,CAAA,CAClD,QAAA,CAAA,CAAAD,GAAAA,CAAC,KAAA,CAAA,CACC,KAAA,CAAO,CACL,QAAA,CAAU,GACV,UAAA,CAAY,GAAA,CACZ,QAAA,CAAU,QAAA,CACV,YAAA,CAAc,UAAA,CACd,UAAA,CAAY,QACd,CAAA,CAEC,QAAA,CAAAF,CAAAA,CACH,CAAA,CACCR,CAAAA,EACCU,GAAAA,CAAC,KAAA,CAAA,CACC,KAAA,CAAO,CACL,QAAA,CAAU,EAAA,CACV,OAAA,CAAS,GAAA,CACT,QAAA,CAAU,QAAA,CACV,YAAA,CAAc,UAAA,CACd,UAAA,CAAY,QACd,CAAA,CAEC,QAAA,CAAAV,CAAAA,CACH,CAAA,CAAA,CAEJ,CAAA,CAAA,CACF,CAEJ,CCtJA,IAAMa,CAAAA,CAAkB,yBAAA,CAClBC,CAAAA,CAAiB,GAAA,CAEVC,CAAAA,CAAN,MAAMC,CAAAA,SAAyBC,aAAyB,CAM7D,WAAA,CACEpB,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAmB,CAAAA,CAAiBJ,CAAAA,CACjBK,CAAAA,CACA,CACA,KAAA,CAAMA,CAAG,CAAA,CACT,IAAA,CAAK,IAAA,CAAOtB,CAAAA,CACZ,IAAA,CAAK,MAAA,CAASC,CAAAA,CACd,KAAK,OAAA,CAAUC,CAAAA,CACf,IAAA,CAAK,QAAA,CAAWmB,EAClB,CAEA,OAAO,OAAA,EAAkB,CACvB,OAAO,eACT,CAEA,OAAO,KAAA,CAAME,CAAAA,CAA0C,CACrD,OAAO,IAAIJ,CAAAA,CACTI,CAAAA,CAAK,IAAA,CACLA,CAAAA,CAAK,MAAA,CACLA,CAAAA,CAAK,OAAA,CACLA,CAAAA,CAAK,QAAA,CACLA,CAAAA,CAAK,KACP,CACF,CAEA,OAAO,WAAWC,CAAAA,CAA0D,CAC1E,OAAO,IAAIL,CAAAA,CACTK,CAAAA,CAAW,SAAA,CACXA,CAAAA,CAAW,WAAA,CACXA,CAAAA,CAAW,YAAA,CACXA,CAAAA,CAAW,aAAA,EAAiBP,CAC9B,CACF,CAEA,UAAA,EAAyC,CACvC,OAAO,CACL,GAAG,KAAA,CAAM,UAAA,EAAW,CACpB,SAAA,CAAW,IAAA,CAAK,IAAA,CAChB,WAAA,CAAa,IAAA,CAAK,MAAA,CAClB,YAAA,CAAc,IAAA,CAAK,QACnB,aAAA,CAAe,IAAA,CAAK,QAAA,CACpB,IAAA,CAAM,eAAA,CACN,OAAA,CAAS,CACX,CACF,CAEA,YAAA,EAAuB,CACrB,OAAO,IAAA,CAAK,IACd,CAEA,cAAA,EAAyB,CACvB,OAAO,IAAA,CAAK,MACd,CAEA,eAAA,EAA0B,CACxB,OAAO,IAAA,CAAK,OACd,CAEA,gBAAA,EAA2B,CACzB,OAAO,IAAA,CAAK,QACd,CAGA,cAAA,EAAyB,CACvB,OAAO,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,MAAM,CAAA,CACpD,CAEA,SAAA,EAAyB,CACvB,IAAMQ,CAAAA,CAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA,CAC1C,OAAAA,CAAAA,CAAK,YAAA,CAAaT,CAAAA,CAAiB,MAAM,CAAA,CAClCS,CACT,CAEA,SAAA,EAAmB,CACjB,OAAO,MACT,CAEA,SAAA,EAA6B,CAC3B,IAAMC,CAAAA,CAAU,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA,CAC7C,OAAAA,CAAAA,CAAQ,YAAA,CAAaV,CAAAA,CAAiB,MAAM,CAAA,CAC5CU,CAAAA,CAAQ,YAAA,CAAa,iBAAA,CAAmB,IAAA,CAAK,IAAI,CAAA,CACjDA,CAAAA,CAAQ,YAAA,CAAa,mBAAA,CAAqB,IAAA,CAAK,MAAM,CAAA,CACrDA,CAAAA,CAAQ,YAAA,CAAa,qBAAA,CAAuB,IAAA,CAAK,QAAQ,CAAA,CACzDA,CAAAA,CAAQ,WAAA,CAAc,IAAA,CAAK,cAAA,EAAe,CACnC,CAAE,OAAA,CAAAA,CAAQ,CACnB,CAEA,OAAO,SAAA,EAAqC,CAC1C,OAAO,CACL,IAAA,CAAOC,CAAAA,EACAA,CAAAA,CAAQ,YAAA,CAAaX,CAAe,CAAA,CAClC,CAAE,UAAA,CAAYY,EAAAA,CAA4B,QAAA,CAAU,CAAE,CAAA,CADV,IAGvD,CACF,CAEA,QAAA,EAAsB,CACpB,OACEf,GAAAA,CAAC,MAAA,CAAA,CAAK,eAAA,CAAiB,KAAA,CAAO,KAAA,CAAO,CAAE,UAAA,CAAY,MAAO,CAAA,CACxD,QAAA,CAAAA,GAAAA,CAACd,CAAAA,CAAA,CACC,EAAA,CAAI,IAAA,CAAK,IAAA,CACT,IAAA,CAAM,IAAA,CAAK,MAAA,CACX,KAAA,CAAO,IAAA,CAAK,OAAA,CACZ,OAAA,CAAQ,MAAA,CACV,CAAA,CACF,CAEJ,CAEA,QAAA,EAAoB,CAClB,OAAO,KACT,CAEA,oBAAA,EAAgC,CAC9B,OAAO,KACT,CAGA,cAAA,EAAyB,CACvB,OAAO,IAAA,CAAK,cAAA,EACd,CACF,EAEA,SAAS6B,EAAAA,CAA2BD,CAAAA,CAAkD,CACpF,IAAM3B,CAAAA,CAAK2B,CAAAA,CAAQ,YAAA,CAAa,iBAAiB,CAAA,CAC3C1B,CAAAA,CAAO0B,CAAAA,CAAQ,YAAA,CAAa,mBAAmB,CAAA,CACrD,GAAI,CAAC3B,CAAAA,EAAM,CAACC,CAAAA,CAAM,OAAO,IAAA,CACzB,IAAMoB,CAAAA,CAASM,CAAAA,CAAQ,YAAA,CAAa,qBAAqB,CAAA,EAAKV,CAAAA,CACxDf,CAAAA,CACJyB,CAAAA,CAAQ,WAAA,EAAa,OAAA,CAAQ,IAAI,MAAA,CAAO,CAAA,IAAA,EAAON,CAAM,CAAA,CAAA,CAAG,CAAA,CAAG,EAAE,CAAA,EAAKrB,CAAAA,CACpE,OAAO,CAAE,IAAA,CAAM6B,CAAAA,CAAwB7B,CAAAA,CAAIC,CAAAA,CAAMC,CAAAA,CAAOmB,CAAM,CAAE,CAClE,CAEO,SAASQ,CAAAA,CACd7B,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAmB,CAAAA,CAAiBJ,CAAAA,CACC,CAClB,OAAO,IAAIC,CAAAA,CAAiBlB,CAAAA,CAAIC,CAAAA,CAAMC,CAAAA,CAAOmB,CAAM,CACrD,CAEO,SAASS,CAAAA,CACdP,CAAAA,CAC0B,CAC1B,OAAOA,CAAAA,YAAgBL,CACzB,CAcO,IAAMa,CAAAA,CACX,0DAqBK,SAASC,EAAAA,CAAwBC,CAAAA,CAAyC,CAC/E,IAAMC,CAAAA,CAAqC,EAAC,CAC5CH,CAAAA,CAAoB,SAAA,CAAY,CAAA,CAChC,IAAII,CAAAA,CACJ,KAAA,CAAQA,CAAAA,CAAIJ,CAAAA,CAAoB,IAAA,CAAKE,CAAI,CAAA,IAAO,IAAA,EAAM,CACpD,IAAMG,CAAAA,CAAUD,CAAAA,CAAE,CAAC,CAAA,EAAK,EAAA,CAClBd,CAAAA,CAASc,CAAAA,CAAE,CAAC,CAAA,CACZnC,CAAAA,CAAKmC,CAAAA,CAAE,CAAC,CAAA,CACRlC,CAAAA,CAAOkC,CAAAA,CAAE,CAAC,CAAA,CACVE,CAAAA,CAAQF,CAAAA,CAAE,KAAA,CAAQC,CAAAA,CAAQ,MAAA,CAC1BE,CAAAA,CAAMH,CAAAA,CAAE,CAAC,CAAA,CAAE,KAAA,CAAMC,CAAAA,CAAQ,MAAM,CAAA,CACrCF,CAAAA,CAAQ,IAAA,CAAK,CACX,EAAA,CAAAlC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,MAAA,CAAAoB,CAAAA,CACA,GAAA,CAAAiB,CAAAA,CACA,KAAA,CAAOD,CAAAA,CACP,QAAA,CAAUA,CAAAA,CAAQC,CAAAA,CAAI,MACxB,CAAC,EACH,CACA,OAAOJ,CACT,CCtNA,IAAMK,EAAAA,CAAkB,GAAA,CAClBC,EAAAA,CAAqB,EAAA,CAErBC,CAAAA,CAAN,cAAqCC,UAAW,CAG9C,WAAA,CAAYC,CAAAA,CAA8B,CACxC,KAAA,CAAM,CAAA,EAAGA,EAAQ,IAAI,CAAA,CAAA,EAAIA,CAAAA,CAAQ,EAAE,CAAA,CAAE,CAAA,CACrC,IAAA,CAAK,OAAA,CAAUA,EACjB,CACF,CAAA,CAEA,SAASC,EAAAA,CAAkBC,CAAAA,CAAyB,CAElD,IAAMC,CAAAA,CAAUD,CAAAA,CAAQ,OAAA,CAAQ,qBAAA,CAAuB,MAAM,CAAA,CAG7D,OAAO,IAAI,MAAA,CACT,CAAA,YAAA,EAAeC,CAAO,CAAA,MAAA,EAASA,CAAO,CAAA,QAAA,EAAWN,EAAkB,CAAA,IAAA,CACrE,CACF,CAwBO,SAASO,CAAAA,CAAmB,CACjC,eAAA,CAAAC,CAAAA,CACA,YAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CACF,CAAA,CAAsD,CACpD,GAAM,CAACC,CAAM,CAAA,CAAIC,yBAAAA,EAA0B,CACrC,CAACC,CAAAA,CAAaC,CAAc,CAAA,CAAIC,QAAAA,CAAwB,IAAI,CAAA,CAC5D,CAACC,CAAAA,CAASC,CAAU,CAAA,CAAIF,QAAAA,CAAgC,EAAE,CAAA,CAE1DV,CAAAA,CAAUG,CAAAA,EAAiB,OAAA,EAAWT,EAAAA,CACtCmB,CAAAA,CAAeC,OAAAA,CAAQ,IAAMf,EAAAA,CAAkBC,CAAO,CAAA,CAAG,CAACA,CAAO,CAAC,CAAA,CAExEe,SAAAA,CAAU,IAAM,CACdV,CAAAA,GAAoBG,CAAAA,EAAe,IAAI,EACzC,CAAA,CAAG,CAACA,CAAAA,CAAaH,CAAiB,CAAC,CAAA,CAEnCU,SAAAA,CAAU,IAAM,CACd,GAAI,CAACZ,CAAAA,EAAmBK,CAAAA,EAAe,IAAA,CAAM,CAC3CI,CAAAA,CAAW,EAAE,CAAA,CACb,MACF,CACA,IAAII,CAAAA,CAAY,KAAA,CAChB,OAAA,OAAA,CAAQ,OAAA,CAAQb,CAAAA,CAAgB,KAAA,CAAMK,CAAW,CAAC,CAAA,CAAE,IAAA,CAAMS,CAAAA,EAAS,CAC5DD,CAAAA,EAAWJ,CAAAA,CAAWK,CAAI,EACjC,CAAC,CAAA,CACM,IAAM,CACXD,CAAAA,CAAY,KACd,CACF,CAAA,CAAG,CAACb,CAAAA,CAAiBK,CAAW,CAAC,CAAA,CAEjC,IAAMU,CAAAA,CAAUJ,OAAAA,CACd,IAAMH,CAAAA,CAAQ,GAAA,CAAKQ,CAAAA,EAAQ,IAAIvB,CAAAA,CAAuBuB,CAAG,CAAC,CAAA,CAC1D,CAACR,CAAO,CACV,CAAA,CAEMS,CAAAA,CAAgBC,WAAAA,CACnBjC,CAAAA,EAAuC,CACtC,IAAMkC,CAAAA,CAAQT,CAAAA,CAAa,IAAA,CAAKzB,CAAI,EACpC,GAAI,CAACkC,CAAAA,CAAO,OAAO,IAAA,CACnB,IAAM/B,CAAAA,CAAU+B,CAAAA,CAAM,CAAC,CAAA,EAAK,EAAA,CACtBC,CAAAA,CAAiBD,CAAAA,CAAM,CAAC,CAAA,EAAK,EAAA,CACnC,OAAO,CACL,UAAA,CAAYA,CAAAA,CAAM,KAAA,CAAQ/B,CAAAA,CAAQ,MAAA,CAClC,cAAA,CAAAgC,CAAAA,CACA,iBAAA,CAAmBD,CAAAA,CAAM,CAAC,CAAA,EAAK,EACjC,CACF,CAAA,CACA,CAACT,CAAY,CACf,CAAA,CAEMW,CAAAA,CAAiBrB,CAAAA,EAAiB,cAAA,CAElCsB,CAAAA,CAAiBJ,WAAAA,CACrB,CACEK,CAAAA,CACAC,CAAAA,CACAC,CAAAA,GACG,CACHtB,CAAAA,CAAO,MAAA,CAAO,IAAM,CAClB,IAAMlD,CAAAA,CAAOsE,CAAAA,CAAe,OAAA,CAAQ,IAAA,CAGpC,GAFoBF,CAAAA,EAAgB,QAAA,CAASpE,CAAI,CAAA,EAAK,KAAA,CAErC,CAIf,IAAMyE,CAAAA,CAA+E,GAC/EC,CAAAA,CAAQC,CAAAA,EAAmB,CAC/B,GAAI9C,CAAAA,CAAoB8C,CAAC,CAAA,EAAKA,CAAAA,CAAE,cAAA,EAAe,GAAM3E,CAAAA,CAAM,CACzDyE,CAAAA,CAAM,IAAA,CAAK,CAAE,IAAA,CAAME,CAAAA,CAAG,KAAA,CAAO,CAAE,CAAC,CAAA,CAChC,MACF,CACA,GAAIC,cAAAA,CAAeD,CAAC,CAAA,CAClB,IAAA,IAAWE,CAAAA,IAAMF,CAAAA,CAAkB,WAAA,EAAY,CAAGD,EAAKG,CAAC,EAE5D,CAAA,CACAH,CAAAA,CAAKI,QAAAA,EAAU,CAAA,CACf,IAAA,IAAWC,CAAAA,IAASN,CAAAA,CAAO,CAGzB,IAAMO,CAAAA,CAAOD,CAAAA,CAAM,IAAA,CAAK,cAAA,EAAe,CAEvC,GADAA,CAAAA,CAAM,IAAA,CAAK,MAAA,EAAO,CACdC,CAAAA,EAAQC,WAAAA,CAAYD,CAAI,CAAA,CAAG,CAC7B,IAAME,CAAAA,CAAWF,CAAAA,CAAK,cAAA,EAAe,CACrC,GAAIE,CAAAA,CAAS,UAAA,CAAW,GAAG,CAAA,CAAG,CAC5B,IAAMC,CAAAA,CAAUD,CAAAA,CAAS,KAAA,CAAM,CAAC,CAAA,CAC5BC,CAAAA,CAAQ,MAAA,GAAW,CAAA,CAAGH,CAAAA,CAAK,MAAA,EAAO,CACjCA,CAAAA,CAAK,cAAA,CAAeG,CAAO,EAClC,CACF,CACF,CACF,CAEA,IAAMC,CAAAA,CAAYxD,CAAAA,CAChB0C,CAAAA,CAAe,OAAA,CAAQ,EAAA,CACvBtE,EACAsE,CAAAA,CAAe,OAAA,CAAQ,KAAA,CACvB1B,CACF,CAAA,CACMyC,CAAAA,CAAgBC,eAAAA,CAAgB,GAAG,CAAA,CACrCf,CAAAA,EACFA,CAAAA,CAAc,OAAA,CAAQa,CAAS,CAAA,CAAE,WAAA,CAAYC,CAAa,CAAA,CAE5DA,CAAAA,CAAc,MAAA,EAAO,CACrBb,CAAAA,GACF,CAAC,EACH,CAAA,CACA,CAACtB,CAAAA,CAAQN,CAAAA,CAASwB,CAAc,CAClC,CAAA,CAEA,OAAKrB,EAGHnC,GAAAA,CAAC2E,0BAAAA,CAAA,CACC,aAAA,CAAelC,CAAAA,CACf,cAAA,CAAgBgB,CAAAA,CAChB,SAAA,CAAWL,CAAAA,CACX,OAAA,CAASF,CAAAA,CACT,YAAA,CAAc,CACZ0B,CAAAA,CACA,CAAE,aAAA,CAAAC,CAAAA,CAAe,sBAAA,CAAAC,CAAAA,CAAwB,mBAAA,CAAAC,CAAoB,CAAA,GAEzD3C,CAAAA,CAEApC,GAAAA,CAAAgF,QAAAA,CAAA,CACG,QAAA,CAAA5C,CAAAA,CAAa,CACZ,aAAA,CAAewC,CAAAA,CAAiB,OAAA,CAChC,QAASjC,CAAAA,CACT,aAAA,CAAekC,CAAAA,EAAiB,CAAA,CAChC,gBAAA,CAAkBE,CAAAA,CAClB,YAAA,CAAeE,CAAAA,EAAW,CACxB,IAAM3B,CAAAA,CAAQJ,CAAAA,CAAQ,IAAA,CACnBgC,CAAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,EAAA,GAAOD,CAAAA,CAAO,EAAA,EAAMC,CAAAA,CAAE,OAAA,CAAQ,IAAA,GAASD,CAAAA,CAAO,IACjE,CAAA,CACI3B,CAAAA,EAAOwB,CAAAA,CAAuBxB,CAAK,EACzC,CAAA,CACA,SAAA,CAAW,IAAMb,CAAAA,CAAe,IAAI,CACtC,CAAC,CAAA,CACH,CAAA,CAIFzC,GAAAA,CAACmF,EAAAA,CAAA,CACC,aAAA,CAAeP,CAAAA,CAAiB,OAAA,CAChC,OAAA,CAAS1B,CAAAA,CACT,aAAA,CAAe2B,CAAAA,EAAiB,CAAA,CAChC,mBAAA,CAAqBE,CAAAA,CACrB,sBAAA,CAAwBD,CAAAA,CACxB,OAAA,CAASnC,CAAAA,CAAQ,MAAA,CAAS,CAAA,EAAKH,CAAAA,EAAe,IAAA,CAC9C,WAAA,CAAaA,CAAAA,CACf,CAAA,CAGN,CAAA,CA3C2B,IA6C/B,CAEA,SAAS2C,EAAAA,CAAmB,CAC1B,aAAA,CAAAC,CAAAA,CACA,OAAA,CAAAlC,CAAAA,CACA,aAAA,CAAA2B,CAAAA,CACA,mBAAA,CAAAE,CAAAA,CACA,sBAAA,CAAAD,CAAAA,CACA,OAAA,CAAAO,CAAAA,CACA,WAAA,CAAA7C,CACF,CAAA,CAQG,CACD,IAAM8C,CAAAA,CAAUC,MAAAA,CAAuB,IAAI,CAAA,CACrC,CAACC,CAAAA,CAASC,CAAU,CAAA,CAAI/C,QAAAA,CAAS,KAAK,CAAA,CACtCgD,CAAAA,CAAe,EA6CrB,GA3CA3C,SAAAA,CAAU,IAAM,CACd,IAAM4C,CAAAA,CAAOL,CAAAA,CAAQ,OAAA,CACrB,GAAI,CAACK,CAAAA,EAAQzC,CAAAA,CAAQ,MAAA,GAAW,CAAA,CAAG,OACnC,IAAM0C,CAAAA,CAAaD,CAAAA,CAAK,aAAA,CACtB,CAAA,wBAAA,EAA2Bd,CAAa,CAAA,CAC1C,CAAA,CACA,GAAI,CAACe,CAAAA,CAAY,OACjB,IAAMC,CAAAA,CAAWF,CAAAA,CAAK,qBAAA,EAAsB,CACtCG,EAAWF,CAAAA,CAAW,qBAAA,EAAsB,CAC9CE,CAAAA,CAAS,GAAA,CAAMD,CAAAA,CAAS,GAAA,CAC1BF,CAAAA,CAAK,SAAA,EAAaE,CAAAA,CAAS,GAAA,CAAMC,CAAAA,CAAS,GAAA,CACjCA,CAAAA,CAAS,MAAA,CAASD,CAAAA,CAAS,MAAA,GACpCF,CAAAA,CAAK,SAAA,EAAaG,CAAAA,CAAS,MAAA,CAASD,CAAAA,CAAS,MAAA,EAEjD,CAAA,CAAG,CAAChB,CAAAA,CAAe3B,CAAAA,CAAQ,MAAM,CAAC,CAAA,CAElC6C,eAAAA,CAAgB,IAAM,CACpB,GAAI,CAACX,CAAAA,EAAiB,CAACC,CAAAA,EAAW,CAACC,CAAAA,CAAQ,OAAA,CAAS,OACpD,IAAMU,CAAAA,CAAa,IAAM,CACvB,IAAMC,CAAAA,CAASX,CAAAA,CAAQ,OAAA,CACvB,GAAI,CAACW,CAAAA,CAAQ,OACb,IAAMC,CAAAA,CAAad,CAAAA,CAAc,qBAAA,EAAsB,CACjDe,CAAAA,CAAaF,CAAAA,CAAO,YAAA,CAKpBG,CAAAA,CAJiB,MAAA,CAAO,YAIMF,CAAAA,CAAW,GAAA,CAEzCG,CAAAA,CADYH,CAAAA,CAAW,GAAA,CAAMA,CAAAA,CAAW,MAAA,CAExCI,CAAAA,CAAsBH,CAAAA,CAAaT,CAAAA,CAAeU,CAAAA,CAClDG,CAAAA,CAAYJ,CAAAA,CAAaT,CAAAA,EAAgBW,CAAAA,CAC/CZ,CAAAA,CAAWa,CAAAA,EAAuBC,CAAS,EAC7C,CAAA,CACA,OAAAP,CAAAA,EAAW,CACX,MAAA,CAAO,gBAAA,CAAiB,QAAA,CAAUA,CAAU,CAAA,CAC5C,MAAA,CAAO,gBAAA,CAAiB,QAAA,CAAUA,CAAAA,CAAY,IAAI,CAAA,CAC3C,IAAM,CACX,MAAA,CAAO,mBAAA,CAAoB,QAAA,CAAUA,CAAU,CAAA,CAC/C,MAAA,CAAO,mBAAA,CAAoB,QAAA,CAAUA,CAAAA,CAAY,IAAI,EACvD,CACF,CAAA,CAAG,CAACZ,CAAAA,CAAeC,CAAAA,CAASnC,CAAAA,CAAQ,MAAM,CAAC,CAAA,CAEvC,CAACkC,CAAAA,EAAiB,CAACC,CAAAA,CAAS,OAAO,IAAA,CAEvC,IAAMmB,CAAAA,CAAepB,CAAAA,CAAc,cAAgB,EAAA,CAC7CqB,CAAAA,CAAYjB,CAAAA,CACd,CAAA,wBAAA,EAA2BgB,CAAAA,CAAed,CAAY,CAAA,IAAA,CAAA,CACtD,MAAA,CAEJ,OAAOgB,YAAAA,CACL1G,GAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKsF,CAAAA,CACL,IAAA,CAAK,SAAA,CACL,KAAA,CAAO,CACL,QAAA,CAAU,UAAA,CACV,GAAA,CAAK,CAAA,CACL,IAAA,CAAM,CAAA,CACN,SAAA,CAAAmB,CAAAA,CACA,MAAA,CAAQ,KAAA,CACR,QAAA,CAAU,GAAA,CACV,QAAA,CAAU,GAAA,CACV,UAAW,GAAA,CACX,SAAA,CAAW,MAAA,CACX,YAAA,CAAc,CAAA,CACd,MAAA,CAAQ,2BAAA,CACR,UAAA,CAAY,SAAA,CACZ,SAAA,CAAW,6BAAA,CACX,OAAA,CAAS,CAAA,CACT,QAAA,CAAU,EAAA,CACV,KAAA,CAAO,SACT,CAAA,CAEC,QAAA,CAAAvD,CAAAA,CAAQ,MAAA,GAAW,CAAA,CAClBjD,IAAAA,CAAC,KAAA,CAAA,CAAI,KAAA,CAAO,CAAE,OAAA,CAAS,UAAA,CAAY,QAAA,CAAU,EAAA,CAAI,KAAA,CAAO,SAAU,EAAG,QAAA,CAAA,CAAA,sBAAA,CAC9CuC,CAAAA,CAAc,CAAA,MAAA,EAASA,CAAW,CAAA,CAAA,CAAA,CAAM,EAAA,CAAA,CAC/D,CAAA,CAEAU,CAAAA,CAAQ,GAAA,CAAI,CAAC+B,CAAAA,CAAQ0B,CAAAA,GAAM,CACzB,IAAMC,CAAAA,CAAaD,CAAAA,GAAM9B,CAAAA,CACnB1B,CAAAA,CAAM8B,CAAAA,CAAO,OAAA,CACnB,OACEjF,GAAAA,CAACd,CAAAA,CAAA,CAEC,OAAA,CAAQ,KAAA,CACR,EAAA,CAAIiE,CAAAA,CAAI,EAAA,CACR,IAAA,CAAMA,CAAAA,CAAI,IAAA,CACV,MAAOA,CAAAA,CAAI,KAAA,CACX,WAAA,CAAaA,CAAAA,CAAI,WAAA,CACjB,IAAA,CAAMA,CAAAA,CAAI,IAAA,CACV,QAAA,CAAUyD,CAAAA,CACV,MAAA,CAAQ,CAAA,uBAAA,EAA0BD,CAAC,CAAA,CAAA,CACnC,YAAA,CAAc,IAAM5B,CAAAA,CAAoB4B,CAAC,CAAA,CACzC,WAAA,CAAczG,CAAAA,EAAM,CAClBA,CAAAA,CAAE,cAAA,EAAe,CACjBA,CAAAA,CAAE,eAAA,EAAgB,CAClB6E,CAAAA,CAAoB4B,CAAC,CAAA,CACrB7B,CAAAA,CAAuBG,CAAM,EAC/B,CAAA,CAAA,CAfKA,CAAAA,CAAO,GAgBd,CAEJ,CAAC,CAAA,CAEL,CAAA,CACAG,CACF,CACF,CC1VO,SAASyB,CAAAA,CAAAA,GAAMC,CAAAA,CAAsB,CAC1C,OAAOC,OAAAA,CAAQC,IAAAA,CAAKF,CAAM,CAAC,CAC7B,CCsBA,IAAMG,EAAAA,CAAe,CACnB,SAAA,CAAW,yBACb,CAAA,CAwCA,SAASC,CAAAA,CAAY5E,EAAkD,CACrE,IAAIlB,CAAAA,CAAO,EAAA,CACL+F,CAAAA,CAA8B,EAAC,CACrC,OAAA7E,CAAAA,CAAO,cAAA,EAAe,CAAE,IAAA,CAAK,IAAM,CACjC,IAAM8E,CAAAA,CAAOlD,QAAAA,EAAS,CACtB9C,CAAAA,CAAOgG,CAAAA,CAAK,cAAA,EAAe,CAC3B,IAAMC,CAAAA,CAAW3G,CAAAA,EAAsB,CAQrC,GAPIO,CAAAA,CAAoBP,CAAI,CAAA,EAC1ByG,CAAAA,CAAO,IAAA,CAAK,CACV,EAAA,CAAIzG,CAAAA,CAAK,YAAA,EAAa,CACtB,IAAA,CAAMA,CAAAA,CAAK,cAAA,EAAe,CAC1B,KAAA,CAAOA,CAAAA,CAAK,eAAA,EACd,CAAC,CAAA,CAECsD,cAAAA,CAAetD,CAAI,CAAA,CACrB,IAAA,IAAW4G,CAAAA,IAAS5G,CAAAA,CAAK,WAAA,EAAY,CAAG2G,CAAAA,CAAQC,CAAK,EAEzD,CAAA,CACAD,CAAAA,CAAQD,CAAI,EACd,CAAC,CAAA,CACM,CAAE,KAAAhG,CAAAA,CAAM,MAAA,CAAA+F,CAAO,CACxB,CAEO,IAAMI,EAAAA,CAAmBC,UAAAA,CAC9B,SACE,CACE,WAAA,CAAAC,CAAAA,CAAc,mBAAA,CACd,QAAA,CAAAC,CAAAA,CAAW,KAAA,CACX,SAAA,CAAAC,CAAAA,CACA,cAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,eAAA,CAAA5F,CAAAA,CACA,gBAAA,CAAA6F,CACF,CAAA,CACAC,CAAAA,CACA,CACA,IAAMC,CAAAA,CAAgBpF,OAAAA,CACpB,KAAO,CACL,SAAA,CAAW,cAAA,CACX,KAAA,CAAOmE,EAAAA,CACP,KAAA,CAAO,CAAC5G,CAAgB,CAAA,CACxB,QAAA,CAAU,CAACqH,CAAAA,CACX,OAAA,CAAUS,CAAAA,EAAiB,CAEzB,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAsBA,CAAK,EAC3C,CACF,CAAA,CAAA,CAGA,EACF,CAAA,CAEA,OACEnI,GAAAA,CAACoI,eAAAA,CAAA,CAAgB,aAAA,CAAeF,CAAAA,CAC9B,QAAA,CAAAlI,GAAAA,CAACqI,EAAAA,CAAA,CACC,WAAA,CAAaZ,CAAAA,CACb,QAAA,CAAUC,CAAAA,CACV,SAAA,CAAWC,CAAAA,CACX,cAAA,CAAgBC,CAAAA,CAChB,QAAA,CAAUE,CAAAA,CACV,QAAA,CAAUC,CAAAA,CACV,eAAA,CAAiB5F,CAAAA,CACjB,gBAAA,CAAkB6F,CAAAA,CAClB,gBAAA,CAAkBC,CAAAA,CAEjB,QAAA,CAAAJ,CAAAA,CACH,CAAA,CACF,CAEJ,CACF,EAEA,SAASQ,EAAAA,CAAc,CACrB,WAAA,CAAAZ,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,SAAA,CAAAC,CAAAA,CACA,cAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,eAAA,CAAA5F,CAAAA,CACA,gBAAA,CAAA6F,CAAAA,CACA,gBAAA,CAAAM,CACF,CAAA,CAEG,CACD,GAAM,CAAChG,CAAM,CAAA,CAAIC,yBAAAA,EAA0B,CACrCgG,CAAAA,CAAchD,MAAAA,CAAOwC,CAAQ,CAAA,CACnCQ,CAAAA,CAAY,OAAA,CAAUR,CAAAA,CACtB,IAAMS,CAAAA,CAAqBjD,MAAAA,CAAO,KAAK,CAAA,CAEvCxC,SAAAA,CAAU,IAAM,CACdT,CAAAA,CAAO,WAAA,CAAY,CAACoF,CAAQ,EAC9B,CAAA,CAAG,CAACpF,CAAAA,CAAQoF,CAAQ,CAAC,CAAA,CAErB,IAAMe,CAAAA,CAASpF,WAAAA,CAAY,IAAM,CAC/B,IAAMqF,CAAAA,CAAUxB,CAAAA,CAAY5E,CAAM,CAAA,CAC9BoG,EAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAA,GAAW,CAAA,EAAKA,CAAAA,CAAQ,MAAA,CAAO,MAAA,GAAW,CAAA,EAC7DH,CAAAA,CAAY,OAAA,CAAQG,CAAO,EAClC,CAAA,CAAG,CAACpG,CAAM,CAAC,CAAA,CAEXqG,mBAAAA,CACEL,CAAAA,CACA,KAAO,CACL,KAAA,CAAO,IAAM,CACXhG,CAAAA,CAAO,MAAA,CAAO,IAAM,CACL4B,QAAAA,EAAS,CACjB,KAAA,GACP,CAAC,EACH,CAAA,CACA,MAAA,CAAAuE,CAAAA,CACA,KAAA,CAAO,IAAMnG,CAAAA,CAAO,KAAA,EACtB,CAAA,CAAA,CACA,CAACA,CAAAA,CAAQmG,CAAM,CACjB,CAAA,CAKA1F,SAAAA,CAAU,IACDT,CAAAA,CAAO,eAAA,CACZsG,iBAAAA,CACCC,CAAAA,EAAU,CACT,GAAIL,CAAAA,CAAmB,OAAA,CAAS,OAAO,MAAA,CACvC,IAAMM,CAAAA,CAAWD,CAAAA,CACjB,OAAIC,GAAU,QAAA,CAAiB,KAAA,EAC/BA,CAAAA,EAAU,cAAA,EAAe,CACzBL,CAAAA,EAAO,CACA,IAAA,CACT,CAAA,CACAM,qBACF,CAAA,CACC,CAACzG,CAAAA,CAAQmG,CAAM,CAAC,CAAA,CAEnB,IAAMO,CAAAA,CAA+B3F,WAAAA,CAAa4F,CAAAA,EAAoB,CACpET,CAAAA,CAAmB,OAAA,CAAUS,EAC/B,CAAA,CAAG,EAAE,CAAA,CAECC,CAAAA,CAAe7F,WAAAA,CAClB8F,CAAAA,EAAwB,CACvB,GAAI,CAACrB,CAAAA,CAAU,OACf,IAAMY,CAAAA,CAAUxB,CAAAA,CAAY5E,CAAM,CAAA,CAClCwF,CAAAA,CAASY,CAAO,EAClB,CAAA,CACA,CAACpG,CAAAA,CAAQwF,CAAQ,CACnB,CAAA,CAEA,OACE7H,IAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAW4G,CAAAA,CAAG,iBAAA,CAAmBc,CAAS,CAAA,CAC7C,QAAA,CAAA,CAAA3H,GAAAA,CAACoJ,cAAAA,CAAA,CACC,eAAA,CACEpJ,GAAAA,CAACqJ,eAAAA,CAAA,CACC,SAAA,CAAWxC,CAAAA,CACT,6CAAA,CACA,4CAAA,CACA,kCAAA,CACAa,CAAAA,EAAY,+BAAA,CACZE,CACF,CAAA,CACF,CAAA,CAEF,WAAA,CACE5H,GAAAA,CAAC,KAAA,CAAA,CACC,SAAA,CAAW6G,CAAAA,CACT,oFAAA,CACA,aACF,CAAA,CAEC,QAAA,CAAAY,CAAAA,CACH,CAAA,CAEF,aAAA,CAAe6B,oBAAAA,CACjB,CAAA,CACAtJ,GAAAA,CAACuJ,cAAAA,CAAA,CAAe,QAAA,CAAUL,CAAAA,CAAc,CAAA,CACxClJ,GAAAA,CAACwJ,aAAAA,CAAA,EAAc,CAAA,CAAA,CAOXxB,CAAAA,EAAoBA,CAAAA,CAAiB,MAAA,CAAS,CAAA,CAC1CA,CAAAA,CACA7F,CAAAA,CACA,CAACA,CAAe,CAAA,CAChB,EAAC,EACU,GAAA,CAAI,CAAC,CAAA,CAAGwE,CAAAA,GACvB3G,GAAAA,CAACkC,CAAAA,CAAA,CAEC,eAAA,CAAiB,CAAA,CACjB,iBAAA,CAAmB8G,CAAAA,CAAAA,CAFd,CAAA,EAAG,CAAA,CAAE,OAAA,EAAW,GAAG,CAAA,CAAA,EAAIrC,CAAC,CAAA,CAG/B,CACD,CAAA,CAEFkB,GACH,CAEJ","file":"chunk-IUCKTDTZ.js","sourcesContent":["import type { CSSProperties, ReactNode } from \"react\";\n\n/**\n * Single source of truth for slash-command token visuals.\n *\n * Used in three places:\n * - Typeahead popover row (variant=\"row\")\n * - Inline chip in the editor (variant=\"chip\", inside CommandTokenNode.decorate)\n * - Inline chip in message history (variant=\"chip\", inside MarkdownContent)\n *\n * Renders a kind tag + label so the user gets the same visual identity at\n * every step: pick → type → send → re-read. Adapts to the surrounding text\n * color via `currentColor` so it survives light bubbles, dark bubbles, and\n * any branded chat surface without bespoke palettes.\n */\nexport interface CommandTokenViewProps {\n /** Slug-style id (wire format `/<id>:<kind>`). */\n id: string;\n /** Token category, e.g. \"skill\", \"mode\". Rendered as the leading tag. */\n kind: string;\n /** Display name; falls back to `id` if not provided. */\n label?: string;\n /** Optional secondary line; only rendered for variant=\"row\". */\n description?: string;\n /** Optional leading icon (slotted before the label, after the tag). */\n icon?: ReactNode;\n /** Optional override for the leading tag (where `kind` renders by default).\n * When set, replaces the uppercase kind pill — e.g. swap \"AD-ACCOUNT\" for\n * the platform logo. */\n tag?: ReactNode;\n /** Compact inline pill (\"chip\") vs. full popover row (\"row\"). */\n variant?: \"chip\" | \"row\";\n /** When true, applies the row's \"selected\" styling. */\n selected?: boolean;\n /** Optional click handler (popover row uses it; chip doesn't by default). */\n onMouseEnter?: () => void;\n onMouseDown?: (e: React.MouseEvent) => void;\n /** Pass-through id for ARIA wiring (used by typeahead). */\n htmlId?: string;\n}\n\nconst TAG_BG = \"color-mix(in srgb, currentColor 16%, transparent)\";\nconst CHIP_BG = \"color-mix(in srgb, currentColor 8%, transparent)\";\nconst ROW_HOVER_BG = \"color-mix(in srgb, currentColor 6%, transparent)\";\nconst ROW_SELECTED_BG = \"color-mix(in srgb, currentColor 12%, transparent)\";\n\nconst tagStyle: CSSProperties = {\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.5,\n textTransform: \"uppercase\",\n padding: \"2px 5px\",\n borderRadius: 3,\n background: TAG_BG,\n lineHeight: 1,\n};\n\nexport function CommandTokenView({\n id,\n kind,\n label,\n description,\n icon,\n tag,\n variant = \"chip\",\n selected = false,\n onMouseEnter,\n onMouseDown,\n htmlId,\n}: CommandTokenViewProps) {\n const display = label ?? id;\n\n // When the caller supplies a tag node (e.g. a platform logo for an\n // ad-account chip), render it raw — no uppercase pill background. The\n // default kind text still uses tagStyle.\n const tagNode =\n tag !== undefined ? (\n <span style={{ display: \"inline-flex\", flexShrink: 0, alignItems: \"center\" }}>{tag}</span>\n ) : (\n <span style={tagStyle}>{kind}</span>\n );\n\n if (variant === \"chip\") {\n return (\n <span\n data-chat-command-chip=\"true\"\n data-command-id={id}\n data-command-kind={kind}\n title={`${kind}: ${id}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n verticalAlign: \"middle\",\n background: CHIP_BG,\n borderRadius: 999,\n padding: \"2px 9px 2px 4px\",\n margin: \"0 1px\",\n whiteSpace: \"nowrap\",\n fontWeight: 500,\n lineHeight: 1,\n }}\n >\n {tagNode}\n {icon && (\n <span style={{ display: \"inline-flex\", flexShrink: 0 }}>{icon}</span>\n )}\n <span>{display}</span>\n </span>\n );\n }\n\n // variant === \"row\"\n return (\n <div\n role=\"option\"\n aria-selected={selected}\n id={htmlId}\n onMouseEnter={onMouseEnter}\n onMouseDown={onMouseDown}\n data-command-id={id}\n data-command-kind={kind}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 8px\",\n borderRadius: 6,\n cursor: \"pointer\",\n background: selected ? ROW_SELECTED_BG : \"transparent\",\n transition: \"background 80ms ease\",\n }}\n onMouseOver={(e) => {\n if (!selected) {\n (e.currentTarget as HTMLDivElement).style.background = ROW_HOVER_BG;\n }\n }}\n onMouseOut={(e) => {\n if (!selected) {\n (e.currentTarget as HTMLDivElement).style.background = \"transparent\";\n }\n }}\n >\n <span style={tagStyle}>{kind}</span>\n {icon && (\n <span style={{ display: \"inline-flex\", flexShrink: 0 }}>{icon}</span>\n )}\n <div style={{ flex: 1, minWidth: 0, lineHeight: 1.3 }}>\n <div\n style={{\n fontSize: 12,\n fontWeight: 500,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {display}\n </div>\n {description && (\n <div\n style={{\n fontSize: 11,\n opacity: 0.65,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {description}\n </div>\n )}\n </div>\n </div>\n );\n}\n","import {\n DecoratorNode,\n type DOMConversionMap,\n type DOMConversionOutput,\n type DOMExportOutput,\n type LexicalNode,\n type NodeKey,\n type SerializedLexicalNode,\n type Spread,\n} from \"lexical\";\nimport type { ReactNode } from \"react\";\n\nimport { CommandTokenView } from \"./CommandTokenView\";\n\nexport type SerializedCommandTokenNode = Spread<\n {\n commandId: string;\n commandKind: string;\n commandLabel: string;\n /** Trigger character that produced the chip (e.g. \"/\" or \"@\"). Optional in\n * v1 payloads — defaulted to \"/\" on import for backwards compatibility. */\n commandPrefix?: string;\n type: \"command-token\";\n version: 1 | 2;\n },\n SerializedLexicalNode\n>;\n\nconst TOKEN_DATA_ATTR = \"data-chat-command-token\";\nconst DEFAULT_PREFIX = \"/\";\n\nexport class CommandTokenNode extends DecoratorNode<ReactNode> {\n __id: string;\n __kind: string;\n __label: string;\n __prefix: string;\n\n constructor(\n id: string,\n kind: string,\n label: string,\n prefix: string = DEFAULT_PREFIX,\n key?: NodeKey,\n ) {\n super(key);\n this.__id = id;\n this.__kind = kind;\n this.__label = label;\n this.__prefix = prefix;\n }\n\n static getType(): string {\n return \"command-token\";\n }\n\n static clone(node: CommandTokenNode): CommandTokenNode {\n return new CommandTokenNode(\n node.__id,\n node.__kind,\n node.__label,\n node.__prefix,\n node.__key,\n );\n }\n\n static importJSON(serialized: SerializedCommandTokenNode): CommandTokenNode {\n return new CommandTokenNode(\n serialized.commandId,\n serialized.commandKind,\n serialized.commandLabel,\n serialized.commandPrefix ?? DEFAULT_PREFIX,\n );\n }\n\n exportJSON(): SerializedCommandTokenNode {\n return {\n ...super.exportJSON(),\n commandId: this.__id,\n commandKind: this.__kind,\n commandLabel: this.__label,\n commandPrefix: this.__prefix,\n type: \"command-token\",\n version: 2,\n };\n }\n\n getCommandId(): string {\n return this.__id;\n }\n\n getCommandKind(): string {\n return this.__kind;\n }\n\n getCommandLabel(): string {\n return this.__label;\n }\n\n getCommandPrefix(): string {\n return this.__prefix;\n }\n\n /** Wire format. Backend parses `<prefix><id>:<kind>` from the message body. */\n getEncodedText(): string {\n return `${this.__prefix}${this.__id}:${this.__kind}`;\n }\n\n createDOM(): HTMLElement {\n const span = document.createElement(\"span\");\n span.setAttribute(TOKEN_DATA_ATTR, \"true\");\n return span;\n }\n\n updateDOM(): false {\n return false;\n }\n\n exportDOM(): DOMExportOutput {\n const element = document.createElement(\"span\");\n element.setAttribute(TOKEN_DATA_ATTR, \"true\");\n element.setAttribute(\"data-command-id\", this.__id);\n element.setAttribute(\"data-command-kind\", this.__kind);\n element.setAttribute(\"data-command-prefix\", this.__prefix);\n element.textContent = this.getEncodedText();\n return { element };\n }\n\n static importDOM(): DOMConversionMap | null {\n return {\n span: (domNode: HTMLElement) => {\n if (!domNode.hasAttribute(TOKEN_DATA_ATTR)) return null;\n return { conversion: convertCommandTokenElement, priority: 1 };\n },\n };\n }\n\n decorate(): ReactNode {\n return (\n <span contentEditable={false} style={{ userSelect: \"none\" }}>\n <CommandTokenView\n id={this.__id}\n kind={this.__kind}\n label={this.__label}\n variant=\"chip\"\n />\n </span>\n );\n }\n\n isInline(): boolean {\n return true;\n }\n\n isKeyboardSelectable(): boolean {\n return true;\n }\n\n /** Plain-text projection (clipboard, root.getTextContent, etc.). */\n getTextContent(): string {\n return this.getEncodedText();\n }\n}\n\nfunction convertCommandTokenElement(domNode: HTMLElement): DOMConversionOutput | null {\n const id = domNode.getAttribute(\"data-command-id\");\n const kind = domNode.getAttribute(\"data-command-kind\");\n if (!id || !kind) return null;\n const prefix = domNode.getAttribute(\"data-command-prefix\") ?? DEFAULT_PREFIX;\n const label =\n domNode.textContent?.replace(new RegExp(`^[\\\\${prefix}]`), \"\") ?? id;\n return { node: $createCommandTokenNode(id, kind, label, prefix) };\n}\n\nexport function $createCommandTokenNode(\n id: string,\n kind: string,\n label: string,\n prefix: string = DEFAULT_PREFIX,\n): CommandTokenNode {\n return new CommandTokenNode(id, kind, label, prefix);\n}\n\nexport function $isCommandTokenNode(\n node: LexicalNode | null | undefined,\n): node is CommandTokenNode {\n return node instanceof CommandTokenNode;\n}\n\n/**\n * Matches `<prefix><id>:<kind>` substrings emitted by `CommandTokenNode.getEncodedText()`,\n * where `<prefix>` is `/` (skill / mode chips) or `@` (ad-account chips).\n *\n * Bounded by start-of-string, whitespace, or an opening bracket on the left,\n * and end-of-string, whitespace, or punctuation on the right — so it doesn't\n * fire on URLs like `https://example.com/path:foo` or emails like\n * `user@host.com:port`.\n *\n * The id capture allows spaces (skill names may have them); the kind capture\n * allows word chars and hyphens (e.g. `ad-account`).\n */\nexport const COMMAND_TOKEN_REGEX =\n /(^|\\s|\\(|\\[)([/@])([^\\n:]+?):([\\w-]+)(?=$|[\\s.,!?)\\]])/g;\n\nexport interface InlineCommandTokenMatch {\n id: string;\n kind: string;\n /** Trigger character that introduced the chip (`/` or `@`). */\n prefix: string;\n /** The full matched substring including the leading prefix (no leading boundary). */\n raw: string;\n /** Index in the original string where the leading prefix sits. */\n index: number;\n /** End index (exclusive) of the matched token. */\n endIndex: number;\n}\n\n/**\n * Find all `<prefix><id>:<kind>` tokens in a plain-text string.\n *\n * Returns matches in document order. Use this when rendering message\n * history to replace token substrings with a visual chip.\n */\nexport function findInlineCommandTokens(text: string): InlineCommandTokenMatch[] {\n const matches: InlineCommandTokenMatch[] = [];\n COMMAND_TOKEN_REGEX.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = COMMAND_TOKEN_REGEX.exec(text)) !== null) {\n const leading = m[1] ?? \"\";\n const prefix = m[2];\n const id = m[3];\n const kind = m[4];\n const start = m.index + leading.length;\n const raw = m[0].slice(leading.length);\n matches.push({\n id,\n kind,\n prefix,\n raw,\n index: start,\n endIndex: start + raw.length,\n });\n }\n return matches;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n LexicalTypeaheadMenuPlugin,\n MenuOption,\n type MenuTextMatch,\n} from \"@lexical/react/LexicalTypeaheadMenuPlugin\";\nimport {\n $createTextNode,\n $getRoot,\n $isElementNode,\n $isTextNode,\n type ElementNode,\n type LexicalNode,\n type TextNode,\n} from \"lexical\";\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { $createCommandTokenNode, $isCommandTokenNode } from \"./CommandTokenNode\";\nimport { CommandTokenView } from \"./CommandTokenView\";\nimport type { ChatComposerCommand, CommandProvider } from \"./types\";\n\nconst DEFAULT_TRIGGER = \"/\";\nconst QUERY_LENGTH_LIMIT = 75;\n\nclass CommandTypeaheadOption extends MenuOption {\n command: ChatComposerCommand;\n\n constructor(command: ChatComposerCommand) {\n super(`${command.kind}:${command.id}`);\n this.command = command;\n }\n}\n\nfunction buildTriggerRegex(trigger: string): RegExp {\n // Escape the trigger char for use in a character class.\n const escaped = trigger.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n // Match: leading boundary (start, whitespace, or open-paren), the trigger,\n // then up to QUERY_LENGTH_LIMIT chars that are not whitespace.\n return new RegExp(\n `(^|\\\\s|\\\\()(${escaped}((?:[^${escaped}\\\\s]){0,${QUERY_LENGTH_LIMIT}}))$`,\n );\n}\n\nexport interface CommandTokenPluginProps {\n /** The data source for the typeahead. When null, the plugin is inert. */\n commandProvider?: CommandProvider | null;\n /**\n * Optional override for the typeahead UI. When supplied, replaces the\n * default Tailwind popover (use this to render an MUI/host-themed menu).\n */\n menuRenderer?: (params: {\n anchorElement: HTMLElement | null;\n options: ChatComposerCommand[];\n selectedIndex: number;\n setSelectedIndex: (index: number) => void;\n selectOption: (option: ChatComposerCommand) => void;\n closeMenu: () => void;\n }) => React.ReactNode;\n /**\n * Notified whenever the typeahead menu opens or closes. Use this to gate\n * keyboard handlers (e.g. don't submit on Enter while the menu is open).\n */\n onMenuStateChange?: (isOpen: boolean) => void;\n}\n\nexport function CommandTokenPlugin({\n commandProvider,\n menuRenderer,\n onMenuStateChange,\n}: CommandTokenPluginProps): React.JSX.Element | null {\n const [editor] = useLexicalComposerContext();\n const [queryString, setQueryString] = useState<string | null>(null);\n const [results, setResults] = useState<ChatComposerCommand[]>([]);\n\n const trigger = commandProvider?.trigger ?? DEFAULT_TRIGGER;\n const triggerRegex = useMemo(() => buildTriggerRegex(trigger), [trigger]);\n\n useEffect(() => {\n onMenuStateChange?.(queryString != null);\n }, [queryString, onMenuStateChange]);\n\n useEffect(() => {\n if (!commandProvider || queryString == null) {\n setResults([]);\n return;\n }\n let cancelled = false;\n Promise.resolve(commandProvider.fetch(queryString)).then((cmds) => {\n if (!cancelled) setResults(cmds);\n });\n return () => {\n cancelled = true;\n };\n }, [commandProvider, queryString]);\n\n const options = useMemo(\n () => results.map((cmd) => new CommandTypeaheadOption(cmd)),\n [results],\n );\n\n const checkForMatch = useCallback(\n (text: string): MenuTextMatch | null => {\n const match = triggerRegex.exec(text);\n if (!match) return null;\n const leading = match[1] ?? \"\";\n const matchingString = match[3] ?? \"\";\n return {\n leadOffset: match.index + leading.length,\n matchingString,\n replaceableString: match[2] ?? \"\",\n };\n },\n [triggerRegex],\n );\n\n const singletonKinds = commandProvider?.singletonKinds;\n\n const onSelectOption = useCallback(\n (\n selectedOption: CommandTypeaheadOption,\n nodeToReplace: TextNode | null,\n closeMenu: () => void,\n ) => {\n editor.update(() => {\n const kind = selectedOption.command.kind;\n const isSingleton = singletonKinds?.includes(kind) ?? false;\n\n if (isSingleton) {\n // Remove any existing chip of the same kind. Walking once with a\n // collected list (rather than mutating during traversal) keeps the\n // tree stable while we iterate.\n const stale: { node: ReturnType<typeof $createCommandTokenNode>; index: number }[] = [];\n const walk = (n: LexicalNode) => {\n if ($isCommandTokenNode(n) && n.getCommandKind() === kind) {\n stale.push({ node: n, index: 0 });\n return;\n }\n if ($isElementNode(n)) {\n for (const c of (n as ElementNode).getChildren()) walk(c);\n }\n };\n walk($getRoot());\n for (const entry of stale) {\n // If the chip is followed by a single space, drop that too so\n // we don't leave an orphan space where the chip used to sit.\n const next = entry.node.getNextSibling();\n entry.node.remove();\n if (next && $isTextNode(next)) {\n const nextText = next.getTextContent();\n if (nextText.startsWith(\" \")) {\n const trimmed = nextText.slice(1);\n if (trimmed.length === 0) next.remove();\n else next.setTextContent(trimmed);\n }\n }\n }\n }\n\n const tokenNode = $createCommandTokenNode(\n selectedOption.command.id,\n kind,\n selectedOption.command.label,\n trigger,\n );\n const trailingSpace = $createTextNode(\" \");\n if (nodeToReplace) {\n nodeToReplace.replace(tokenNode).insertAfter(trailingSpace);\n }\n trailingSpace.select();\n closeMenu();\n });\n },\n [editor, trigger, singletonKinds],\n );\n\n if (!commandProvider) return null;\n\n return (\n <LexicalTypeaheadMenuPlugin<CommandTypeaheadOption>\n onQueryChange={setQueryString}\n onSelectOption={onSelectOption}\n triggerFn={checkForMatch}\n options={options}\n menuRenderFn={(\n anchorElementRef,\n { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex },\n ) => {\n if (menuRenderer) {\n return (\n <>\n {menuRenderer({\n anchorElement: anchorElementRef.current,\n options: results,\n selectedIndex: selectedIndex ?? 0,\n setSelectedIndex: setHighlightedIndex,\n selectOption: (option) => {\n const match = options.find(\n (o) => o.command.id === option.id && o.command.kind === option.kind,\n );\n if (match) selectOptionAndCleanUp(match);\n },\n closeMenu: () => setQueryString(null),\n })}\n </>\n );\n }\n return (\n <DefaultCommandMenu\n anchorElement={anchorElementRef.current}\n options={options}\n selectedIndex={selectedIndex ?? 0}\n setHighlightedIndex={setHighlightedIndex}\n selectOptionAndCleanUp={selectOptionAndCleanUp}\n visible={results.length > 0 || queryString != null}\n queryString={queryString}\n />\n );\n }}\n />\n );\n}\n\nfunction DefaultCommandMenu({\n anchorElement,\n options,\n selectedIndex,\n setHighlightedIndex,\n selectOptionAndCleanUp,\n visible,\n queryString,\n}: {\n anchorElement: HTMLElement | null;\n options: CommandTypeaheadOption[];\n selectedIndex: number;\n setHighlightedIndex: (index: number) => void;\n selectOptionAndCleanUp: (option: CommandTypeaheadOption) => void;\n visible: boolean;\n queryString: string | null;\n}) {\n const menuRef = useRef<HTMLDivElement>(null);\n const [flipped, setFlipped] = useState(false);\n const VERTICAL_GAP = 6;\n\n useEffect(() => {\n const menu = menuRef.current;\n if (!menu || options.length === 0) return;\n const selectedEl = menu.querySelector<HTMLElement>(\n `#command-typeahead-item-${selectedIndex}`,\n );\n if (!selectedEl) return;\n const menuRect = menu.getBoundingClientRect();\n const itemRect = selectedEl.getBoundingClientRect();\n if (itemRect.top < menuRect.top) {\n menu.scrollTop -= menuRect.top - itemRect.top;\n } else if (itemRect.bottom > menuRect.bottom) {\n menu.scrollTop += itemRect.bottom - menuRect.bottom;\n }\n }, [selectedIndex, options.length]);\n\n useLayoutEffect(() => {\n if (!anchorElement || !visible || !menuRef.current) return;\n const reposition = () => {\n const menuEl = menuRef.current;\n if (!menuEl) return;\n const anchorRect = anchorElement.getBoundingClientRect();\n const menuHeight = menuEl.offsetHeight;\n const viewportHeight = window.innerHeight;\n // Lexical positions the anchor right below the cursor; anchorRect.top is\n // where the menu would render by default. anchorRect.height is the\n // cursor-line height (~20px), so the cursor's top is anchorRect.top - height.\n const spaceBelow = viewportHeight - anchorRect.top;\n const cursorTop = anchorRect.top - anchorRect.height;\n const spaceAbove = cursorTop;\n const wouldOverflowBottom = menuHeight + VERTICAL_GAP > spaceBelow;\n const fitsAbove = menuHeight + VERTICAL_GAP <= spaceAbove;\n setFlipped(wouldOverflowBottom && fitsAbove);\n };\n reposition();\n window.addEventListener(\"resize\", reposition);\n window.addEventListener(\"scroll\", reposition, true);\n return () => {\n window.removeEventListener(\"resize\", reposition);\n window.removeEventListener(\"scroll\", reposition, true);\n };\n }, [anchorElement, visible, options.length]);\n\n if (!anchorElement || !visible) return null;\n\n const anchorHeight = anchorElement.offsetHeight || 20;\n const transform = flipped\n ? `translateY(calc(-100% - ${anchorHeight + VERTICAL_GAP}px))`\n : \"none\";\n\n return createPortal(\n <div\n ref={menuRef}\n role=\"listbox\"\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n transform,\n zIndex: 99999,\n minWidth: 320,\n maxWidth: 520,\n maxHeight: 280,\n overflowY: \"auto\",\n borderRadius: 8,\n border: \"1px solid rgba(0,0,0,0.1)\",\n background: \"#ffffff\",\n boxShadow: \"0 8px 24px rgba(0,0,0,0.15)\",\n padding: 4,\n fontSize: 12,\n color: \"#1f2937\",\n }}\n >\n {options.length === 0 ? (\n <div style={{ padding: \"6px 10px\", fontSize: 11, color: \"#6b7280\" }}>\n No matching commands{queryString ? ` for \"${queryString}\"` : \"\"}\n </div>\n ) : (\n options.map((option, i) => {\n const isSelected = i === selectedIndex;\n const cmd = option.command;\n return (\n <CommandTokenView\n key={option.key}\n variant=\"row\"\n id={cmd.id}\n kind={cmd.kind}\n label={cmd.label}\n description={cmd.description}\n icon={cmd.icon}\n selected={isSelected}\n htmlId={`command-typeahead-item-${i}`}\n onMouseEnter={() => setHighlightedIndex(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHighlightedIndex(i);\n selectOptionAndCleanUp(option);\n }}\n />\n );\n })\n )}\n </div>,\n anchorElement,\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes with proper precedence.\n * Combines clsx for conditional classes with tailwind-merge for conflict resolution.\n *\n * @example\n * cn(\"px-4 py-2\", \"px-6\") // => \"py-2 px-6\"\n * cn(\"text-red-500\", isActive && \"text-blue-500\") // => \"text-blue-500\" when isActive\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { LexicalComposer } from \"@lexical/react/LexicalComposer\";\nimport { LexicalComposerContext, useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport {\n $getRoot,\n $isElementNode,\n COMMAND_PRIORITY_HIGH,\n KEY_ENTER_COMMAND,\n type EditorState,\n type LexicalEditor,\n type LexicalNode,\n} from \"lexical\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"../utils/cn\";\nimport { CommandTokenNode, $isCommandTokenNode } from \"./CommandTokenNode\";\nimport { CommandTokenPlugin } from \"./CommandTokenPlugin\";\nimport type {\n ChatComposerSubmitPayload,\n ChatComposerToken,\n CommandProvider,\n} from \"./types\";\n\nconst EDITOR_THEME = {\n paragraph: \"chat-composer-paragraph\",\n};\n\nexport interface LexicalChatInputHandle {\n /** Clear the editor contents and reset history. */\n clear: () => void;\n /** Programmatically submit the current editor contents. */\n submit: () => void;\n /** Focus the editor. */\n focus: () => void;\n}\n\nexport interface LexicalChatInputProps {\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n /** Tailwind classes applied to the inner ContentEditable element. */\n inputClassName?: string;\n /** Slot for additional Lexical plugins (mounted inside LexicalComposer). */\n children?: ReactNode;\n /**\n * Called whenever the editor's plain-text projection changes. Use this to\n * gate a parent-rendered submit button on `text.trim().length > 0`.\n */\n onChange?: (payload: ChatComposerSubmitPayload) => void;\n /** Called when the user presses Enter (without Shift). */\n onSubmit: (payload: ChatComposerSubmitPayload) => void | Promise<void>;\n /**\n * Optional slash-command typeahead. When omitted, the editor behaves like\n * a plain rich-text input.\n */\n commandProvider?: CommandProvider | null;\n /**\n * Multiple typeahead providers, one per trigger character (e.g. `/` for\n * skills + modes, `@` for ad accounts). When supplied, this takes\n * precedence over the singular `commandProvider`. Each provider mounts its\n * own `CommandTokenPlugin` instance.\n */\n commandProviders?: CommandProvider[];\n}\n\nfunction readPayload(editor: LexicalEditor): ChatComposerSubmitPayload {\n let text = \"\";\n const tokens: ChatComposerToken[] = [];\n editor.getEditorState().read(() => {\n const root = $getRoot();\n text = root.getTextContent();\n const collect = (node: LexicalNode) => {\n if ($isCommandTokenNode(node)) {\n tokens.push({\n id: node.getCommandId(),\n kind: node.getCommandKind(),\n label: node.getCommandLabel(),\n });\n }\n if ($isElementNode(node)) {\n for (const child of node.getChildren()) collect(child);\n }\n };\n collect(root);\n });\n return { text, tokens };\n}\n\nexport const LexicalChatInput = forwardRef<LexicalChatInputHandle, LexicalChatInputProps>(\n function LexicalChatInput(\n {\n placeholder = \"Type a message...\",\n disabled = false,\n className,\n inputClassName,\n children,\n onChange,\n onSubmit,\n commandProvider,\n commandProviders,\n },\n ref,\n ) {\n const initialConfig = useMemo(\n () => ({\n namespace: \"ChatComposer\",\n theme: EDITOR_THEME,\n nodes: [CommandTokenNode],\n editable: !disabled,\n onError: (error: Error) => {\n // eslint-disable-next-line no-console\n console.error(\"[chat-ui composer]\", error);\n },\n }),\n // The initial config can't change after mount; `disabled` is applied via editor.setEditable below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <ChatInputBody\n placeholder={placeholder}\n disabled={disabled}\n className={className}\n inputClassName={inputClassName}\n onChange={onChange}\n onSubmit={onSubmit}\n commandProvider={commandProvider}\n commandProviders={commandProviders}\n imperativeHandle={ref}\n >\n {children}\n </ChatInputBody>\n </LexicalComposer>\n );\n },\n);\n\nfunction ChatInputBody({\n placeholder,\n disabled,\n className,\n inputClassName,\n children,\n onChange,\n onSubmit,\n commandProvider,\n commandProviders,\n imperativeHandle,\n}: LexicalChatInputProps & {\n imperativeHandle: React.ForwardedRef<LexicalChatInputHandle>;\n}) {\n const [editor] = useLexicalComposerContext();\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const commandMenuOpenRef = useRef(false);\n\n useEffect(() => {\n editor.setEditable(!disabled);\n }, [editor, disabled]);\n\n const submit = useCallback(() => {\n const payload = readPayload(editor);\n if (payload.text.trim().length === 0 && payload.tokens.length === 0) return;\n void onSubmitRef.current(payload);\n }, [editor]);\n\n useImperativeHandle(\n imperativeHandle,\n () => ({\n clear: () => {\n editor.update(() => {\n const root = $getRoot();\n root.clear();\n });\n },\n submit,\n focus: () => editor.focus(),\n }),\n [editor, submit],\n );\n\n // Intercept Enter (without Shift) and trigger submit, unless the\n // command-token typeahead menu is open — in which case the typeahead's\n // own LOW-priority handler takes the key to select an option.\n useEffect(() => {\n return editor.registerCommand(\n KEY_ENTER_COMMAND,\n (event) => {\n if (commandMenuOpenRef.current) return false;\n const keyboard = event as KeyboardEvent | null;\n if (keyboard?.shiftKey) return false;\n keyboard?.preventDefault();\n submit();\n return true;\n },\n COMMAND_PRIORITY_HIGH,\n );\n }, [editor, submit]);\n\n const handleCommandMenuStateChange = useCallback((isOpen: boolean) => {\n commandMenuOpenRef.current = isOpen;\n }, []);\n\n const handleChange = useCallback(\n (_state: EditorState) => {\n if (!onChange) return;\n const payload = readPayload(editor);\n onChange(payload);\n },\n [editor, onChange],\n );\n\n return (\n <div className={cn(\"relative w-full\", className)}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n className={cn(\n \"outline-none w-full text-sm leading-relaxed\",\n \"min-h-[24px] max-h-[200px] overflow-y-auto\",\n \"text-gray-900 dark:text-zinc-100\",\n disabled && \"opacity-50 cursor-not-allowed\",\n inputClassName,\n )}\n />\n }\n placeholder={\n <div\n className={cn(\n \"pointer-events-none absolute top-0 left-0 text-sm text-gray-400 dark:text-zinc-500\",\n \"select-none\",\n )}\n >\n {placeholder}\n </div>\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <OnChangePlugin onChange={handleChange} />\n <HistoryPlugin />\n {(() => {\n // Plural takes precedence; fall back to singular for back-compat.\n // We mount one plugin per provider so different triggers (e.g. `/`\n // and `@`) can each fire their own typeahead. The menu-open ref is\n // shared so submit-on-Enter is gated whichever menu is open.\n const providers =\n commandProviders && commandProviders.length > 0\n ? commandProviders\n : commandProvider\n ? [commandProvider]\n : [];\n return providers.map((p, i) => (\n <CommandTokenPlugin\n key={`${p.trigger ?? \"/\"}-${i}`}\n commandProvider={p}\n onMenuStateChange={handleCommandMenuStateChange}\n />\n ));\n })()}\n {children}\n </div>\n );\n}\n\n// Re-export so consumers that mount their own LexicalComposer can grab the\n// editor instance for advanced wiring.\nexport { useLexicalComposerContext, LexicalComposerContext };\n"]}