@saywright/studio 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/THIRD_PARTY_NOTICES.md +0 -6
  2. package/dist/bridge.js +1109 -179
  3. package/dist/cli.mjs +1966 -375
  4. package/dist/client/assets/CommandPalette-VEQNxJ4K.js +1 -0
  5. package/dist/client/assets/CommandPalette-VEQNxJ4K.js.br +0 -0
  6. package/dist/client/assets/CommandPalette-VEQNxJ4K.js.gz +0 -0
  7. package/dist/client/assets/HelpDialog-CnCVSSNP.js +1 -0
  8. package/dist/client/assets/HelpDialog-CnCVSSNP.js.br +0 -0
  9. package/dist/client/assets/HelpDialog-CnCVSSNP.js.gz +0 -0
  10. package/dist/client/assets/ReportView-BwBy4JIG.js +4 -0
  11. package/dist/client/assets/ReportView-BwBy4JIG.js.br +0 -0
  12. package/dist/client/assets/ReportView-BwBy4JIG.js.gz +0 -0
  13. package/dist/client/assets/SettingsDialog-CS5w9CxJ.js +1 -0
  14. package/dist/client/assets/SettingsDialog-CS5w9CxJ.js.br +0 -0
  15. package/dist/client/assets/SettingsDialog-CS5w9CxJ.js.gz +0 -0
  16. package/dist/client/assets/arrow-left-BpsxETMA.js +1 -0
  17. package/dist/client/assets/brand-BSL9G2NW.js +57 -0
  18. package/dist/client/assets/brand-BSL9G2NW.js.br +0 -0
  19. package/dist/client/assets/brand-BSL9G2NW.js.gz +0 -0
  20. package/dist/client/assets/footprints-Bc2dzReV.js +1 -0
  21. package/dist/client/assets/index-BrM0s_jp.css +2 -0
  22. package/dist/client/assets/index-BrM0s_jp.css.br +0 -0
  23. package/dist/client/assets/index-BrM0s_jp.css.gz +0 -0
  24. package/dist/client/assets/index-C3xqQUPf.js +19 -0
  25. package/dist/client/assets/index-C3xqQUPf.js.br +0 -0
  26. package/dist/client/assets/index-C3xqQUPf.js.gz +0 -0
  27. package/dist/client/assets/refresh-cw-DocKnJID.js +1 -0
  28. package/dist/client/index.html +3 -5
  29. package/dist/client/index.html.br +0 -0
  30. package/dist/client/index.html.gz +0 -0
  31. package/dist/sample/package.json +1 -1
  32. package/dist/sample/src/App.tsx +3 -2
  33. package/dist/sample/src/lib/route.ts +3 -2
  34. package/dist/sample/src/pages/Account.tsx +88 -0
  35. package/dist/sample/src/styles.css +5 -0
  36. package/package.json +1 -2
  37. package/dist/client/assets/Calibration-xY4YDLzU.js +0 -1
  38. package/dist/client/assets/Calibration-xY4YDLzU.js.br +0 -0
  39. package/dist/client/assets/Calibration-xY4YDLzU.js.gz +0 -0
  40. package/dist/client/assets/CommandPalette-BA3akF-p.js +0 -1
  41. package/dist/client/assets/CommandPalette-BA3akF-p.js.br +0 -0
  42. package/dist/client/assets/CommandPalette-BA3akF-p.js.gz +0 -0
  43. package/dist/client/assets/HelpDialog-C6qmdEwi.js +0 -1
  44. package/dist/client/assets/HelpDialog-C6qmdEwi.js.br +0 -0
  45. package/dist/client/assets/HelpDialog-C6qmdEwi.js.gz +0 -0
  46. package/dist/client/assets/ReportView-Bj9xxLCi.js +0 -4
  47. package/dist/client/assets/ReportView-Bj9xxLCi.js.br +0 -0
  48. package/dist/client/assets/ReportView-Bj9xxLCi.js.gz +0 -0
  49. package/dist/client/assets/SettingsDialog-VrACcdUX.js +0 -1
  50. package/dist/client/assets/SettingsDialog-VrACcdUX.js.br +0 -0
  51. package/dist/client/assets/SettingsDialog-VrACcdUX.js.gz +0 -0
  52. package/dist/client/assets/button-B2NFEpCs.js +0 -18
  53. package/dist/client/assets/button-B2NFEpCs.js.br +0 -0
  54. package/dist/client/assets/button-B2NFEpCs.js.gz +0 -0
  55. package/dist/client/assets/camera-BD9K1f5I.js +0 -1
  56. package/dist/client/assets/confirm-D1U-bFIL.js +0 -41
  57. package/dist/client/assets/confirm-D1U-bFIL.js.br +0 -0
  58. package/dist/client/assets/confirm-D1U-bFIL.js.gz +0 -0
  59. package/dist/client/assets/footprints-DiYtIryA.js +0 -1
  60. package/dist/client/assets/index-BakNwOFF.css +0 -2
  61. package/dist/client/assets/index-BakNwOFF.css.br +0 -0
  62. package/dist/client/assets/index-BakNwOFF.css.gz +0 -0
  63. package/dist/client/assets/index-DUAtV_Av.js +0 -18
  64. package/dist/client/assets/index-DUAtV_Av.js.br +0 -0
  65. package/dist/client/assets/index-DUAtV_Av.js.gz +0 -0
  66. package/dist/client/assets/preload-helper-BLdHbfdN.js +0 -1
  67. package/dist/client/assets/preload-helper-BLdHbfdN.js.br +0 -0
  68. package/dist/client/assets/preload-helper-BLdHbfdN.js.gz +0 -0
  69. package/dist/client/assets/refresh-cw-Dobx2YmO.js +0 -1
  70. package/dist/client/assets/tracker.worker-DWwj76VA.js +0 -41
  71. package/dist/client/assets/tracker.worker-DWwj76VA.js.br +0 -0
  72. package/dist/client/assets/tracker.worker-DWwj76VA.js.gz +0 -0
  73. package/dist/client/assets/vision_bundle-ByYCzljp.js +0 -41
  74. package/dist/client/assets/vision_bundle-ByYCzljp.js.br +0 -0
  75. package/dist/client/assets/vision_bundle-ByYCzljp.js.gz +0 -0
@@ -1 +0,0 @@
1
- import{i as e,o as t,r as n,t as r}from"./cn-Wq33h1G4.js";import{A as i,B as a,D as o,F as s,G as c,H as l,I as u,L as d,O as f,R as p,U as m,V as h,W as g,X as _,Z as v,a as y,b,d as x,f as S,j as C,k as ee,l as w,m as T,n as E,o as D,p as te,q as O,r as ne,u as k,v as re,x as ie,y as A,z as ae}from"./confirm-D1U-bFIL.js";import{$ as j,At as oe,J as se,K as M,Mt as ce,Nt as N,Q as P,Tt as F,_t as le,a as ue,at as de,et as fe,i as pe,it as me,jt as he,kt as I,n as ge,nt as _e,r as ve,rt as L,t as R,tt as ye,vt as be,wt as xe,xt as Se}from"./button-B2NFEpCs.js";import{n as Ce,t as we}from"./refresh-cw-Dobx2YmO.js";import{Ct as Te,G as Ee,H as De,J as Oe,P as ke,Q as Ae,X as je,_ as Me,a as Ne,g as z,n as Pe,pt as Fe,q as Ie,t as Le,v as Re,y as ze,z as Be}from"./index-DUAtV_Av.js";var B=t(e(),1),Ve=t(v(),1),V=n(),He=Object.defineProperty,H=(e,t)=>He(e,`name`,{value:t,configurable:!0}),Ue={ItemAligned:`item-aligned`,Popper:`popper`},We={LTR:`ltr`,RTL:`rtl`},Ge=[` `,`Enter`,`ArrowUp`,`ArrowDown`],Ke=[` `,`Enter`],qe=`Select`,[Je,Ye,Xe]=l(qe),[U,Ze]=g(qe,[Xe,ie]),Qe=ie(),[$e,W]=U(qe),[et,tt]=U(qe);function nt(e){let{__scopeSelect:t,children:n,open:r,defaultOpen:i,onOpenChange:o,value:s,defaultValue:c,onValueChange:l,dir:u,name:f,autoComplete:m,disabled:h,required:g,form:_,internal_do_not_use_render:v}=e,y=Qe(t),[b,x]=B.useState(null),[S,C]=B.useState(null),[ee,w]=B.useState(!1),T=d(u),[E,D]=a({prop:r,defaultProp:i??!1,onChange:o,caller:qe}),[te,O]=a({prop:s,defaultProp:c,onChange:l,caller:qe}),ne=B.useRef(null),k=B.useRef(!1),[ie,A]=B.useState(null),ae=H(e=>{A({value:e,hasConsumerStoppedPropagation:k.current}),O(e)},`handleUserSelect`),j=B.useRef(te);B.useEffect(()=>{let e=_?b?.ownerDocument.getElementById(_):b?.form;if(e instanceof HTMLFormElement){let t=H(()=>O(j.current),`reset`);return e.addEventListener(`reset`,t),()=>e.removeEventListener(`reset`,t)}},[_,b,O]);let oe=!b||!!_||!!b.closest(`form`),[se,M]=B.useState(new Set),ce=p(),N=Array.from(se).map(e=>e.props.value).join(`;`),P=B.useCallback(e=>{M(t=>new Set(t).add(e))},[]),F=B.useCallback(e=>{M(t=>{let n=new Set(t);return n.delete(e),n})},[]),le={required:g,trigger:b,onTriggerChange:x,valueNode:S,onValueNodeChange:C,valueNodeHasChildren:ee,onValueNodeHasChildrenChange:w,contentId:ce,value:te,onValueChange:O,hasConsumerStoppedPropagationRef:k,userSelection:ie,onUserSelect:ae,open:E,onOpenChange:D,dir:T,triggerPointerDownPosRef:ne,disabled:h,name:f,autoComplete:m,form:_,nativeOptions:se,nativeSelectKey:N,isFormControl:oe};return(0,V.jsx)(re,{...y,children:(0,V.jsx)($e,{scope:t,...le,children:(0,V.jsx)(Je.Provider,{scope:t,children:(0,V.jsx)(et,{scope:t,onNativeOptionAdd:P,onNativeOptionRemove:F,children:It(v)?v(le):n})})})})}H(nt,`SelectProvider`);var rt=H(e=>{let{__scopeSelect:t,children:n,...r}=e;return(0,V.jsx)(nt,{__scopeSelect:t,...r,internal_do_not_use_render:({isFormControl:e})=>(0,V.jsxs)(V.Fragment,{children:[n,e?(0,V.jsx)(Ft,{__scopeSelect:t}):null]})})},`Select`),it=`SelectTrigger`,at=B.forwardRef(H(function(e,t){let{__scopeSelect:n,disabled:r=!1,...i}=e,a=Qe(n),o=W(it,n),s=o.disabled||r,l=_(t,o.onTriggerChange),u=Ye(n),d=B.useRef(`touch`),[f,p,m]=Rt(e=>{let t=u().filter(e=>!e.disabled),n=zt(t,e,t.find(e=>e.value===o.value));n!==void 0&&o.onUserSelect(n.value)}),g=H(e=>{s||(o.onOpenChange(!0),m()),e&&(o.triggerPointerDownPosRef.current={x:Math.round(e.pageX),y:Math.round(e.pageY)})},`handleOpen`);return(0,V.jsx)(A,{asChild:!0,...a,children:(0,V.jsx)(c.button,{type:`button`,role:`combobox`,"aria-controls":o.open?o.contentId:void 0,"aria-expanded":o.open,"aria-required":o.required,"aria-autocomplete":`none`,dir:o.dir,"data-state":o.open?`open`:`closed`,disabled:s,"data-disabled":s?``:void 0,"data-placeholder":Lt(o.value)?``:void 0,...i,ref:l,onClick:h(i.onClick,e=>{e.currentTarget.focus(),d.current!==`mouse`&&g(e)}),onPointerDown:h(i.onPointerDown,e=>{d.current=e.pointerType;let t=e.target;t.hasPointerCapture(e.pointerId)&&t.releasePointerCapture(e.pointerId),e.button===0&&e.ctrlKey===!1&&e.pointerType===`mouse`&&(g(e),e.preventDefault())}),onKeyDown:h(i.onKeyDown,e=>{let t=f.current!==``;!(e.ctrlKey||e.altKey||e.metaKey)&&e.key.length===1&&(o.hasConsumerStoppedPropagationRef.current=e.isPropagationStopped(),p(e.key)),!(t&&e.key===` `)&&Ge.includes(e.key)&&(g(),e.preventDefault())})})})},`SelectTrigger`)),ot=`SelectValue`,st=B.forwardRef(H(function(e,t){let{__scopeSelect:n,className:r,style:i,children:a,placeholder:o=``,...s}=e,l=W(ot,n),{onValueNodeHasChildrenChange:u}=l,d=a!==void 0,f=_(t,l.onValueNodeChange);m(()=>{u(d)},[u,d]);let p=Lt(l.value);return(0,V.jsx)(c.span,{...s,asChild:!p&&s.asChild,ref:f,style:{pointerEvents:`none`},children:(0,V.jsx)(B.Fragment,{children:p?o:a},p?`placeholder`:`value`)})},`SelectValue`)),ct=B.forwardRef(H(function(e,t){let{__scopeSelect:n,children:r,...i}=e;return(0,V.jsx)(c.span,{"aria-hidden":!0,...i,ref:t,children:r||`▼`})},`SelectIcon`)),[lt,ut]=U(`SelectPortal`,{forceMount:void 0}),dt=H(e=>{let{__scopeSelect:t,forceMount:n,...r}=e;return(0,V.jsx)(lt,{scope:e.__scopeSelect,forceMount:n,children:(0,V.jsx)(i,{asChild:!0,...r})})},`SelectPortal`),G=`SelectContent`,ft=B.forwardRef(H(function(e,t){let n=ut(G,e.__scopeSelect),{forceMount:r=n.forceMount,...i}=e,a=W(G,e.__scopeSelect),[o,s]=B.useState();return m(()=>{s(new DocumentFragment)},[]),(0,V.jsx)(ae,{present:r||a.open,children:({present:e})=>e?(0,V.jsx)(_t,{...i,ref:t}):(0,V.jsx)(pt,{...i,fragment:o})})},`SelectContent`)),pt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,children:r,fragment:i}=e;return i?Ve.createPortal((0,V.jsx)(mt,{scope:n,children:(0,V.jsx)(Je.Slot,{scope:n,children:(0,V.jsx)(`div`,{ref:t,children:r})})}),i):null},`SelectContentFragment`)),K=10,[mt,ht]=U(G),gt=O(`SelectContent.RemoveScroll`),_t=B.forwardRef(H(function(e,t){let{__scopeSelect:n}=e,{position:r=Ue.ItemAligned,onCloseAutoFocus:i,onEscapeKeyDown:a,onPointerDownOutside:c,side:l,sideOffset:u,align:d,alignOffset:p,arrowPadding:m,collisionBoundary:g,collisionPadding:v,sticky:y,hideWhenDetached:b,avoidCollisions:x,...S}=e,w=W(G,n),[T,E]=B.useState(null),[D,te]=B.useState(null),O=_(t,E),[ne,k]=B.useState(null),[re,ie]=B.useState(null),A=Ye(n),[ae,j]=B.useState(!1),oe=B.useRef(!1),se=B.useRef(!1),M=B.useRef(!1);B.useEffect(()=>{if(T)return o(T)},[T]),ee();let ce=B.useCallback(e=>{let[t,...n]=A().map(e=>e.ref.current),[r]=n.slice(-1),i=document.activeElement;for(let n of e)if(n===i||(n?.scrollIntoView({block:`nearest`}),n===t&&D&&(D.scrollTop=0),n===r&&D&&(D.scrollTop=D.scrollHeight),n?.focus(),document.activeElement!==i))return},[A,D]),N=B.useCallback(()=>ce([ne,T]),[ce,ne,T]);B.useEffect(()=>{ae&&N()},[ae,N]);let{onOpenChange:P,triggerPointerDownPosRef:F}=w;B.useEffect(()=>{if(T){let e={x:0,y:0},t=H(t=>{e={x:Math.abs(Math.round(t.pageX)-(F.current?.x??0)),y:Math.abs(Math.round(t.pageY)-(F.current?.y??0))}},`handlePointerMove`),n=H(n=>{e.x<=10&&e.y<=10?n.preventDefault():n.composedPath().includes(T)||P(!1),document.removeEventListener(`pointermove`,t),F.current=null},`handlePointerUp`);return F.current!==null&&(document.addEventListener(`pointermove`,t),document.addEventListener(`pointerup`,n,{capture:!0,once:!0})),()=>{document.removeEventListener(`pointermove`,t),document.removeEventListener(`pointerup`,n,{capture:!0})}}},[T,P,F]),B.useEffect(()=>{let e=H(()=>P(!1),`close`);return window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),()=>{window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e)}},[P]);let[le,ue]=Rt(e=>{let t=A().filter(e=>!e.disabled),n=zt(t,e,t.find(e=>e.ref.current===document.activeElement));n&&setTimeout(()=>n.ref.current?.focus())}),de=B.useCallback((e,t,n)=>{let r=!se.current;r&&(se.current=!0);let i=!oe.current&&!n;w.value!==void 0&&w.value===t||i?(k(e),i&&(oe.current=!0)):r&&k(e)},[w.value]),fe=B.useCallback(()=>T?.focus(),[T]),pe=B.useCallback((e,t,n)=>{if(!e)return;let r=!M.current;r&&(M.current=!0);let i=!oe.current&&!n;(w.value!==void 0&&w.value===t||i||r)&&ie(e)},[w.value]),me=r===Ue.Popper?yt:vt,he=me===yt?{side:l,sideOffset:u,align:d,alignOffset:p,arrowPadding:m,collisionBoundary:g,collisionPadding:v,sticky:y,hideWhenDetached:b,avoidCollisions:x}:{};return(0,V.jsx)(mt,{scope:n,content:T,viewport:D,onViewportChange:te,itemRefCallback:de,selectedItem:ne,onItemLeave:fe,itemTextRefCallback:pe,focusSelectedItem:N,selectedItemText:re,position:r,isPositioned:ae,searchRef:le,children:(0,V.jsx)(f,{as:gt,allowPinchZoom:!0,children:(0,V.jsx)(C,{asChild:!0,trapped:w.open,onMountAutoFocus:e=>{e.preventDefault()},onUnmountAutoFocus:h(i,e=>{w.trigger?.focus({preventScroll:!0}),e.preventDefault()}),children:(0,V.jsx)(s,{asChild:!0,disableOutsidePointerEvents:!0,onEscapeKeyDown:a,onPointerDownOutside:c,onFocusOutside:e=>e.preventDefault(),onDismiss:()=>w.onOpenChange(!1),children:(0,V.jsx)(me,{role:`listbox`,id:w.contentId,"data-state":w.open?`open`:`closed`,dir:w.dir,onContextMenu:e=>e.preventDefault(),...S,...he,onPlaced:()=>j(!0),ref:O,style:{display:`flex`,flexDirection:`column`,outline:`none`,...S.style},onKeyDown:h(S.onKeyDown,e=>{let t=e.ctrlKey||e.altKey||e.metaKey;if(e.key===`Tab`&&e.preventDefault(),!t&&e.key.length===1&&ue(e.key),[`ArrowUp`,`ArrowDown`,`Home`,`End`].includes(e.key)){let t=A().filter(e=>!e.disabled).map(e=>e.ref.current);if([`ArrowUp`,`End`].includes(e.key)&&(t=t.slice().reverse()),[`ArrowUp`,`ArrowDown`].includes(e.key)){let n=e.target,r=t.indexOf(n);t=t.slice(r+1)}setTimeout(()=>ce(t)),e.preventDefault()}})})})})})})},`SelectContentImpl`)),vt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,onPlaced:r,...i}=e,a=W(G,n),o=ht(G,n),[s,l]=B.useState(null),[u,d]=B.useState(null),f=_(t,d),p=Ye(n),h=B.useRef(!1),g=B.useRef(!0),{viewport:v,selectedItem:y,selectedItemText:b,focusSelectedItem:x}=o,S=B.useCallback(()=>{if(a.trigger&&a.valueNode&&s&&u&&v&&y&&b){let e=a.trigger.getBoundingClientRect(),t=u.getBoundingClientRect(),n=a.valueNode.getBoundingClientRect(),i=b.getBoundingClientRect();if(a.dir!==We.RTL){let r=i.left-t.left,a=n.left-r,o=e.left-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-K,d=Fe(a,[K,Math.max(K,u-l)]);s.style.minWidth=c+`px`,s.style.left=d+`px`}else{let r=t.right-i.right,a=window.innerWidth-n.right-r,o=window.innerWidth-e.right-a,c=e.width+o,l=Math.max(c,t.width),u=window.innerWidth-K,d=Fe(a,[K,Math.max(K,u-l)]);s.style.minWidth=c+`px`,s.style.right=d+`px`}let o=p(),c=window.innerHeight-K*2,l=v.scrollHeight,d=window.getComputedStyle(u),f=parseInt(d.borderTopWidth,10),m=parseInt(d.paddingTop,10),g=parseInt(d.borderBottomWidth,10),_=parseInt(d.paddingBottom,10),x=f+m+l+_+g,S=Math.min(y.offsetHeight*5,x),C=window.getComputedStyle(v),ee=parseInt(C.paddingTop,10),w=parseInt(C.paddingBottom,10),T=e.top+e.height/2-K,E=c-T,D=y.offsetHeight/2,te=y.offsetTop+D,O=f+m+te,ne=x-O;if(O<=T){let e=o.length>0&&y===o[o.length-1].ref.current;s.style.bottom=`0px`;let t=u.clientHeight-v.offsetTop-v.offsetHeight,n=O+Math.max(E,D+(e?w:0)+t+g);s.style.height=n+`px`}else{let e=o.length>0&&y===o[0].ref.current;s.style.top=`0px`;let t=Math.max(T,f+v.offsetTop+(e?ee:0)+D)+ne;s.style.height=t+`px`,v.scrollTop=O-T+v.offsetTop}s.style.margin=`${K}px 0`,s.style.minHeight=S+`px`,s.style.maxHeight=c+`px`,r?.(),requestAnimationFrame(()=>h.current=!0)}},[p,a.trigger,a.valueNode,s,u,v,y,b,a.dir,r]);m(()=>S(),[S]);let[C,ee]=B.useState();m(()=>{u&&ee(window.getComputedStyle(u).zIndex)},[u]);let w=B.useCallback(e=>{e&&g.current===!0&&(S(),x?.(),g.current=!1)},[S,x]);return(0,V.jsx)(bt,{scope:n,contentWrapper:s,shouldExpandOnScrollRef:h,onScrollButtonChange:w,children:(0,V.jsx)(`div`,{ref:l,style:{display:`flex`,flexDirection:`column`,position:`fixed`,zIndex:C},children:(0,V.jsx)(c.div,{...i,ref:f,style:{boxSizing:`border-box`,maxHeight:`100%`,...i.style}})})})},`SelectItemAlignedPosition`)),yt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,align:r=`start`,collisionPadding:i=K,...a}=e,o=Qe(n);return(0,V.jsx)(b,{...o,...a,ref:t,align:r,collisionPadding:i,style:{boxSizing:`border-box`,...a.style,"--radix-select-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-select-content-available-width":`var(--radix-popper-available-width)`,"--radix-select-content-available-height":`var(--radix-popper-available-height)`,"--radix-select-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-select-trigger-height":`var(--radix-popper-anchor-height)`}})},`SelectPopperPosition`)),[bt,xt]=U(G,{}),St=`SelectViewport`,Ct=B.forwardRef(H(function(e,t){let{__scopeSelect:n,nonce:r,...i}=e,a=ht(St,n),o=xt(St,n),s=_(t,a.onViewportChange),l=B.useRef(0);return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`style`,{dangerouslySetInnerHTML:{__html:`[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`},nonce:r}),(0,V.jsx)(Je.Slot,{scope:n,children:(0,V.jsx)(c.div,{"data-radix-select-viewport":``,role:`presentation`,...i,ref:s,style:{position:`relative`,flex:1,overflow:`hidden auto`,...i.style},onScroll:h(i.onScroll,e=>{let t=e.currentTarget,{contentWrapper:n,shouldExpandOnScrollRef:r}=o;if(r?.current&&n){let e=Math.abs(l.current-t.scrollTop);if(e>0){let r=window.innerHeight-K*2,i=parseFloat(n.style.minHeight),a=parseFloat(n.style.height),o=Math.max(i,a);if(o<r){let i=o+e,a=Math.min(r,i),s=i-a;n.style.height=a+`px`,n.style.bottom===`0px`&&(t.scrollTop=s>0?s:0,n.style.justifyContent=`flex-end`)}}}l.current=t.scrollTop})})})]})},`SelectViewport`)),[wt,Tt]=U(`SelectGroup`),Et=`SelectItem`,[Dt,Ot]=U(Et),kt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,value:r,disabled:i=!1,textValue:a,...o}=e,s=W(Et,n),l=ht(Et,n),d=s.value===r,[f,m]=B.useState(a??``),[g,v]=B.useState(!1),y=u(e=>l.itemRefCallback?.(e,r,i)),b=_(t,y),x=p(),S=B.useRef(`touch`);function C(e){s.hasConsumerStoppedPropagationRef.current=e.isPropagationStopped(),s.onUserSelect(r),s.onOpenChange(!1)}return H(C,`handleSelect`),(0,V.jsx)(Dt,{scope:n,value:r,disabled:i,textId:x,isSelected:d,onItemTextChange:B.useCallback(e=>{m(t=>t||(e?.textContent??``).trim())},[]),children:(0,V.jsx)(Je.ItemSlot,{scope:n,value:r,disabled:i,textValue:f,children:(0,V.jsx)(c.div,{role:`option`,"aria-labelledby":x,"data-highlighted":g?``:void 0,"aria-selected":d&&g,"data-state":d?`checked`:`unchecked`,"aria-disabled":i||void 0,"data-disabled":i?``:void 0,tabIndex:i?void 0:-1,...o,ref:b,onFocus:h(o.onFocus,()=>v(!0)),onBlur:h(o.onBlur,()=>v(!1)),onClick:h(o.onClick,e=>{i||S.current!==`mouse`&&C(e)}),onPointerUp:h(o.onPointerUp,e=>{i||S.current===`mouse`&&C(e)}),onPointerDown:h(o.onPointerDown,e=>{S.current=e.pointerType}),onPointerMove:h(o.onPointerMove,e=>{S.current=e.pointerType,i?l.onItemLeave?.():S.current===`mouse`&&e.currentTarget.focus({preventScroll:!0})}),onPointerLeave:h(o.onPointerLeave,e=>{e.currentTarget===document.activeElement&&l.onItemLeave?.()}),onKeyDown:h(o.onKeyDown,e=>{i||e.target!==e.currentTarget||(l.searchRef?.current===``||e.key!==` `)&&(Ke.includes(e.key)&&C(e),e.key===` `&&e.preventDefault())})})})})},`SelectItem`)),At=`SelectItemText`,jt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,className:r,style:i,...a}=e,o=W(At,n),s=ht(At,n),l=Ot(At,n),d=tt(At,n),[f,p]=B.useState(null),h=u(e=>s.itemTextRefCallback?.(e,l.value,l.disabled)),g=_(t,p,l.onItemTextChange,h),v=f?.textContent,y=B.useMemo(()=>(0,V.jsx)(`option`,{value:l.value,disabled:l.disabled,children:v},l.value),[l.disabled,l.value,v]),{onNativeOptionAdd:b,onNativeOptionRemove:x}=d;return m(()=>(b(y),()=>x(y)),[b,x,y]),(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(c.span,{id:l.textId,...a,ref:g}),l.isSelected&&o.valueNode&&!o.valueNodeHasChildren&&!Lt(o.value)?Ve.createPortal(a.children,o.valueNode):null]})},`SelectItemText`)),Mt=`SelectItemIndicator`,Nt=B.forwardRef(H(function(e,t){let{__scopeSelect:n,...r}=e;return Ot(Mt,n).isSelected?(0,V.jsx)(c.span,{"aria-hidden":!0,...r,ref:t}):null},`SelectItemIndicator`)),Pt=`SelectBubbleInput`,Ft=B.forwardRef(H(function({__scopeSelect:e,...t},n){let r=W(Pt,e),{value:i,onValueChange:a,required:o,disabled:s,name:l,autoComplete:u,form:d,userSelection:f}=r,{nativeOptions:p,nativeSelectKey:m}=r,h=B.useRef(null),g=_(n,h),v=i??``,y=B.useRef(v),b=B.useRef(f),x=B.useRef(!1),S=Array.from(p).some(e=>(e.props.value??``)===``);return B.useEffect(()=>{let e=h.current;if(!e)return;let t=window.HTMLSelectElement.prototype,n=Object.getOwnPropertyDescriptor(t,`value`).set,r=f!==null&&f!==b.current;b.current=f;let i=y.current!==v;y.current=v;let a=r&&i;if(r&&!i&&f.value!==v&&!f.hasConsumerStoppedPropagation&&n){x.current=!0;try{n.call(e,f.value),e.dispatchEvent(new Event(`change`,{bubbles:!0}))}finally{x.current=!1,n.call(e,v)}return}let o=a&&!f.hasConsumerStoppedPropagation;if(i&&n){let t=new Event(`change`,{bubbles:o});n.call(e,v),e.dispatchEvent(t)}},[v,f]),(0,V.jsxs)(c.select,{"aria-hidden":!0,required:o,tabIndex:-1,name:l,autoComplete:u,disabled:s,form:d,onChange:e=>{x.current||a(e.target.value)},...t,style:{...Te,...t.style},ref:g,defaultValue:v,children:[Lt(i)&&!S?(0,V.jsx)(`option`,{value:``}):null,Array.from(p)]},m)},`SelectBubbleInput`));function It(e){return typeof e==`function`}H(It,`isFunction`);function Lt(e){return e===``||e===void 0}H(Lt,`shouldShowPlaceholder`);function Rt(e){let t=u(e),n=B.useRef(``),r=B.useRef(0),i=B.useCallback(e=>{let i=n.current+e;t(i);function a(e){n.current=e,window.clearTimeout(r.current),e!==``&&(r.current=window.setTimeout(()=>a(``),1e3))}H(a,`updateSearch`),a(i)},[t]),a=B.useCallback(()=>{n.current=``,window.clearTimeout(r.current)},[]);return B.useEffect(()=>()=>window.clearTimeout(r.current),[]),[n,i,a]}H(Rt,`useTypeaheadSearch`);function zt(e,t,n){let r=t.length>1&&Array.from(t).every(e=>e===t[0])?t[0]:t,i=n?e.indexOf(n):-1,a=Bt(e,Math.max(i,0));r.length===1&&(a=a.filter(e=>e!==n));let o=a.find(e=>e.textValue.toLowerCase().startsWith(r.toLowerCase()));return o===n?void 0:o}H(zt,`findNextItem`);function Bt(e,t){return e.map((n,r)=>e[(t+r)%e.length])}H(Bt,`wrapArray`);var Vt={name:`chart-line`,size:24,node:[[`path`,{d:`M3 3v16a2 2 0 0 0 2 2h16`,key:`c24i48`}],[`path`,{d:`m19 9-5 5-4-4-3 3`,key:`2osh9i`}]],aliases:[`line-chart`]};Vt.node;var Ht=ue(Vt),Ut={name:`file-braces`,size:24,node:[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1`,key:`1oajmo`}],[`path`,{d:`M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1`,key:`mpwhp6`}]],aliases:[`file-json`]};Ut.node;var Wt=ue(Ut),Gt={name:`keyboard`,size:24,node:[[`path`,{d:`M10 8h.01`,key:`1r9ogq`}],[`path`,{d:`M12 12h.01`,key:`1mp3jc`}],[`path`,{d:`M14 8h.01`,key:`1primd`}],[`path`,{d:`M16 12h.01`,key:`1l6xoz`}],[`path`,{d:`M18 8h.01`,key:`emo2bl`}],[`path`,{d:`M6 8h.01`,key:`x9i8wu`}],[`path`,{d:`M7 16h10`,key:`wp8him`}],[`path`,{d:`M8 12h.01`,key:`czm47f`}],[`rect`,{width:`20`,height:`16`,x:`2`,y:`4`,rx:`2`,key:`18n3k1`}]]};Gt.node;var Kt=ue(Gt),qt={name:`plug`,size:24,node:[[`path`,{d:`M12 22v-5`,key:`1ega77`}],[`path`,{d:`M15 8V2`,key:`18g5xt`}],[`path`,{d:`M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z`,key:`1xoxul`}],[`path`,{d:`M9 8V2`,key:`14iosj`}]]};qt.node;var Jt=ue(qt),Yt={name:`sliders-horizontal`,size:24,node:[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]};Yt.node;var Xt=ue(Yt);function Zt({value:e,onChange:t,options:n,className:i,placeholder:a}){return(0,V.jsxs)(rt,{value:e,onValueChange:e=>t(e),children:[(0,V.jsxs)(at,{"data-hand":!0,className:r(`inline-flex h-8 min-w-[160px] items-center justify-between gap-2 rounded-[8px] bg-raised px-2.5 text-[12.5px] text-fg ring-1 ring-inset ring-line-strong hover:bg-hover`,i),children:[(0,V.jsx)(st,{placeholder:a}),(0,V.jsx)(ct,{children:(0,V.jsx)(T,{className:`size-3.5 text-fg-3`})})]}),(0,V.jsx)(dt,{children:(0,V.jsx)(ft,{position:`popper`,sideOffset:4,className:`z-[80] min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-[10px] bg-raised p-1 shadow-pop`,children:(0,V.jsx)(Ct,{children:n.map(e=>(0,V.jsxs)(kt,{value:e.value,"data-hand":!0,className:`relative flex cursor-default select-none items-center gap-2 rounded-[6px] py-1.5 pl-7 pr-3 text-[12.5px] text-fg outline-none data-[highlighted]:bg-hover`,children:[(0,V.jsx)(Nt,{className:`absolute left-2`,children:(0,V.jsx)(pe,{className:`size-3.5 text-human`})}),(0,V.jsx)(jt,{children:e.label}),e.note&&(0,V.jsx)(`span`,{className:`ml-auto pl-4 text-[11.5px] text-fg-3`,children:e.note})]},e.value))})})})]})}var q=ce(()=>({state:null,loading:!1,error:null,busy:{},results:{}})),J=q.setState,Qt=q.getState;async function Y(e){try{return J({state:await e,error:null}),M.refreshStatus(),!0}catch(e){return J({error:e instanceof Error?e.message:String(e)}),!1}}function $t(e,t,n){J({busy:{...Qt().busy,[e]:t},...n===void 0?{}:{results:{...Qt().results,[e]:n}}})}var X={async load(e=!1){J({loading:!0}),await Y(N.get(`/ai${e?`?refresh=1`:``}`)),J({loading:!1})},async saveKey(e,t){$t(e,!0);let n=await Y(N.put(`/ai/key`,{connection:e,key:t}));if(n&&t){let t=await X.test(e,!1);return $t(e,!1,t),t.ok}return $t(e,!1,n?void 0:{ok:!1,message:Qt().error??`Couldn’t save the key.`}),n},async test(e,t=!0){t&&$t(e,!0);let n;try{n=await N.post(`/ai/test`,{connection:e})}catch(e){n={ok:!1,message:e instanceof Error?e.message:String(e)}}return t&&$t(e,!1,n),X.load(),n},add(e){return Y(N.post(`/ai/connections`,e))},remove(e){return Y(N.delete(`/ai/connections/${encodeURIComponent(e)}`))},setOff(e,t){return Y(N.put(`/ai/connections/${encodeURIComponent(e)}`,{off:t}))},addModel(e,t){return Y(N.put(`/ai/connections/${encodeURIComponent(e)}`,{model:t}))},setRoute(e,t){return Y(N.put(`/ai/routes`,{task:e,connection:t?.connection??null,model:t?.model??null}))},setEffort(e){return Y(N.put(`/ai/effort`,{effort:e}))},async setBudget(e){try{let t=await N.put(`/ai/budget`,e),n=Qt().state;n&&J({state:{...n,usage:t}})}catch(e){J({error:e instanceof Error?e.message:String(e)})}},async reset(e){try{let t=await N.post(`/ai/usage/reset`,{scope:e}),n=Qt().state;n&&J({state:{...n,usage:t}}),M.refreshStatus()}catch(e){J({error:e instanceof Error?e.message:String(e)})}}},en=[{id:`code`,label:`Changes and questions`,hint:`Edits code and answers questions about it. The most capable model pays off here.`},{id:`report`,label:`Reports and reviews`,hint:`Writes session reports and expert reviews from screenshots and evidence.`},{id:`light`,label:`Small jobs`,hint:`Translations and short texts. A fast, inexpensive model is plenty.`}];function tn({children:e,sub:t}){return(0,V.jsxs)(`div`,{className:`mb-4`,children:[(0,V.jsx)(`h2`,{className:`text-[15px] font-semibold tracking-[-0.01em] text-fg`,children:e}),t&&(0,V.jsx)(`p`,{className:`mt-1 max-w-[500px] text-[12.5px] leading-relaxed text-fg-3`,children:t})]})}function Z({title:e,sub:t,children:n,id:r}){return(0,V.jsxs)(`section`,{id:r,className:`mt-6 scroll-mt-4 first:mt-0`,children:[(0,V.jsx)(`h3`,{className:`text-[12px] font-semibold uppercase tracking-[0.04em] text-fg-3`,children:e}),t&&(0,V.jsx)(`p`,{className:`mt-1 max-w-[500px] text-[12px] leading-relaxed text-fg-3`,children:t}),(0,V.jsx)(`div`,{className:`mt-2 divide-y divide-line rounded-[10px] ring-1 ring-inset ring-line`,children:n})]})}var Q=`h-8 min-w-0 rounded-[8px] bg-sunken px-2.5 text-[12.5px] text-fg ring-1 ring-inset ring-line-strong outline-none placeholder:text-fg-3 focus:ring-human-line`;function nn(){let e=q(e=>e.state);return(0,B.useEffect)(()=>{X.load(!0)},[]),e}function rn({c:e}){if(e.disabled)return(0,V.jsx)(y,{children:`Off`});switch(e.status){case`ready`:return(0,V.jsxs)(y,{tone:`ok`,children:[(0,V.jsx)(D,{tone:`ok`,className:`mr-0.5`}),` Ready`]});case`needs-key`:return(0,V.jsx)(y,{children:`No key`});case`needs-login`:return(0,V.jsx)(y,{tone:`warn`,children:`Sign in needed`});case`missing`:return(0,V.jsx)(y,{children:`Not installed`});case`offline`:return(0,V.jsx)(y,{children:`Not running`});default:return(0,V.jsx)(y,{tone:`warn`,children:`Problem`})}}function an(e,t){return e.auth===`subscription`?`Included in your plan`:e.auth===`local`&&e.preset!==`custom`?`Free, on this computer`:t.price?`$${t.price.input} in · $${t.price.output} out per 1M tokens`:t.note??``}var on={"claude-code":`Claude plan`,codex:`ChatGPT plan`,"gemini-cli":`Gemini (Google account)`,anthropic:`Anthropic API`,openai:`OpenAI API`,gemini:`Gemini API`};function sn({state:e}){let t=e.connections.filter(e=>e.status===`ready`&&!e.disabled&&e.models.length);return(0,V.jsxs)(Z,{title:`Who does what`,sub:`Automatic picks your plan first (no extra cost), then an API key, then a model on this computer. Choose a model per job to balance quality and cost.`,children:[en.map(n=>{let r=e.routes[n.id],i=e.chosen[n.id],a=r?`${on[r.connection]??e.connections.find(e=>e.id===r.connection)?.label??r.connection} · ${e.connections.find(e=>e.id===r.connection)?.models.find(e=>e.id===r.model)?.label??r.model}`:`Nothing connected yet`,o=[{value:`auto`,label:`Automatic`,note:a},...t.flatMap(e=>e.models.map(t=>({value:`${e.id}::${t.id}`,label:`${on[e.id]??e.label} · ${t.label}`,note:an(e,t)})))];return(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-4 px-3 py-3`,"data-route":n.id,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:n.label}),(0,V.jsx)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:n.hint}),!i&&(0,V.jsxs)(`div`,{className:`mt-1 text-[11.5px] text-fg-3`,"data-route-now":!0,children:[`Now: `,a]})]}),(0,V.jsx)(Zt,{value:i&&r?.connection===i.connection&&r.model===i.model?`${i.connection}::${i.model}`:`auto`,onChange:e=>{if(e===`auto`)return void X.setRoute(n.id,null);let[t,...r]=e.split(`::`);X.setRoute(n.id,{connection:t,model:r.join(`::`)})},options:o,className:`w-[250px] shrink-0`})]},n.id)}),(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-4 px-3 py-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:`Effort`}),(0,V.jsx)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:`Higher effort thinks longer on hard requests, and uses more tokens.`})]}),(0,V.jsx)(Re,{value:e.effort,onChange:e=>void X.setEffort(e),options:[{value:`low`,label:`Low`},{value:`medium`,label:`Medium`},{value:`high`,label:`High`}]})]})]})}var cn={"claude-code":{install:`npm install -g @anthropic-ai/claude-code`,signIn:`claude`,site:`https://claude.com/claude-code`},codex:{install:`npm install -g @openai/codex`,signIn:`codex login`,site:`https://developers.openai.com/codex`},"gemini-cli":{install:`npm install -g @google/gemini-cli`,signIn:`gemini`,site:`https://github.com/google-gemini/gemini-cli`}},ln={anthropic:`https://console.anthropic.com/settings/keys`,openai:`https://platform.openai.com/api-keys`,gemini:`https://aistudio.google.com/apikey`};function un({text:e,label:t}){let[n,r]=(0,B.useState)(!1);return(0,V.jsx)(R,{size:`sm`,variant:`ghost`,"aria-label":t??`Copy`,onClick:()=>{navigator.clipboard?.writeText(e).then(()=>{r(!0),setTimeout(()=>r(!1),1200)})},children:n?(0,V.jsx)(pe,{}):(0,V.jsx)(Ae,{})})}function dn({text:e,label:t,shown:n}){return(0,V.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1.5`,children:[(0,V.jsx)(`code`,{className:`min-w-0 flex-1 truncate rounded-[6px] bg-sunken px-2 py-1 font-mono text-[11.5px] text-fg-2`,children:n??e}),(0,V.jsx)(un,{text:e,label:t})]})}function fn({c:e}){let t=cn[e.id],n=q(e=>e.loading);return(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-connection":e.id,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[e.label,` `,(0,V.jsx)(rn,{c:e})]}),e.detail&&(0,V.jsx)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:e.detail})]}),e.status===`ready`?(0,V.jsx)(z,{checked:!e.disabled,onCheckedChange:t=>void X.setOff(e.id,!t),"aria-label":`Use ${e.label}`}):(0,V.jsx)(R,{size:`sm`,variant:`ghost`,onClick:()=>void X.load(!0),disabled:n,icon:n?(0,V.jsx)(w,{}):(0,V.jsx)(we,{}),children:`Check again`})]}),t&&(e.status===`missing`||e.status===`needs-login`)&&(0,V.jsxs)(`div`,{className:`mt-2 space-y-1.5 text-[12px] text-fg-3`,children:[e.status===`missing`&&(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`div`,{children:`1. Install it:`}),(0,V.jsx)(dn,{text:t.install})]}),(0,V.jsxs)(`div`,{children:[e.status===`missing`?`2. `:``,`Sign in with your account (once, in a terminal):`]}),(0,V.jsx)(dn,{text:t.signIn}),(0,V.jsxs)(`a`,{className:`inline-flex items-center gap-1 text-human-fg hover:underline`,href:t.site,target:`_blank`,rel:`noreferrer`,children:[`About it `,(0,V.jsx)(Oe,{className:`size-3`})]})]})]})}function pn({c:e,file:t}){let[n,i]=(0,B.useState)(``),[a,o]=(0,B.useState)(!1),s=q(t=>!!t.busy[e.id]),c=q(t=>t.results[e.id]),l=e.status===`ready`||!!e.detail?.startsWith(`Key`);return(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-connection":e.id,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[e.label,` `,(0,V.jsx)(rn,{c:e})]}),(0,V.jsxs)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:[e.detail??`Billed per use by the provider.`,` `,ln[e.id]&&(0,V.jsxs)(`a`,{className:`inline-flex items-center gap-0.5 text-human-fg hover:underline`,href:ln[e.id],target:`_blank`,rel:`noreferrer`,children:[`Get a key `,(0,V.jsx)(Oe,{className:`size-3`})]})]})]}),e.status===`ready`&&(0,V.jsx)(z,{checked:!e.disabled,onCheckedChange:t=>void X.setOff(e.id,!t),"aria-label":`Use ${e.label}`})]}),(0,V.jsxs)(`form`,{className:`mt-2 flex gap-2`,onSubmit:t=>{t.preventDefault(),n.trim()&&X.saveKey(e.id,n.trim()).then(e=>e&&i(``))},children:[(0,V.jsxs)(`div`,{className:`relative min-w-0 flex-1`,children:[(0,V.jsx)(`input`,{"data-hand":!0,type:a?`text`:`password`,value:n,onChange:e=>i(e.target.value),placeholder:l?`Replace the key`:`Paste an API key`,autoComplete:`off`,spellCheck:!1,"aria-label":`${e.label} key`,className:r(Q,`w-full pr-8 font-mono`)}),(0,V.jsx)(`button`,{type:`button`,className:`absolute right-1.5 top-1.5 text-fg-3 hover:text-fg [&_svg]:size-[14px]`,onClick:()=>o(!a),"aria-label":a?`Hide key`:`Show key`,children:a?(0,V.jsx)(Ce,{}):(0,V.jsx)(Ie,{})})]}),(0,V.jsx)(R,{type:`submit`,size:`md`,variant:`primary`,disabled:!n.trim()||s,children:s?(0,V.jsx)(w,{}):`Save`}),l&&(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(R,{type:`button`,size:`md`,onClick:()=>void X.test(e.id),disabled:s,children:`Test`}),(0,V.jsx)(R,{type:`button`,size:`md`,variant:`ghost`,"aria-label":`Remove the ${e.label} key`,onClick:async()=>await E({title:`Remove the ${e.label} key?`,body:`It is deleted from this computer.`,action:`Remove`,danger:!0})&&void X.saveKey(e.id,null),children:(0,V.jsx)(k,{})})]})]}),c&&(0,V.jsx)(`p`,{className:r(`mt-1.5 text-[12px]`,c.ok?`text-ok`:`text-bad`),children:c.message}),(0,V.jsxs)(`p`,{className:`mt-1.5 text-[11.5px] text-fg-3`,children:[`Saved in `,(0,V.jsx)(`span`,{className:`font-mono`,children:t??`.env.local`}),`, readable only by you, never sent anywhere but `,e.label.replace(/ API$/,``),`.`]})]})}function mn({c:e}){let t=q(e=>e.loading),n=e.id===`ollama`?`https://ollama.com`:`https://lmstudio.ai`;return(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-3 px-3 py-3`,"data-connection":e.id,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[e.label,` `,(0,V.jsx)(rn,{c:e})]}),(0,V.jsxs)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:[e.detail,` `,e.status!==`ready`&&(0,V.jsxs)(`a`,{className:`inline-flex items-center gap-0.5 text-human-fg hover:underline`,href:n,target:`_blank`,rel:`noreferrer`,children:[`Get it `,(0,V.jsx)(Oe,{className:`size-3`})]})]})]}),e.status===`ready`?(0,V.jsx)(z,{checked:!e.disabled,onCheckedChange:t=>void X.setOff(e.id,!t),"aria-label":`Use ${e.label}`}):(0,V.jsx)(R,{size:`sm`,variant:`ghost`,onClick:()=>void X.load(!0),disabled:t,icon:t?(0,V.jsx)(w,{}):(0,V.jsx)(we,{}),children:`Check again`})]})}function hn({c:e}){let t=q(t=>!!t.busy[e.id]),n=q(t=>t.results[e.id]),[i,a]=(0,B.useState)(``);return(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-connection":e.id,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[e.label,` `,(0,V.jsx)(rn,{c:e})]}),(0,V.jsxs)(`div`,{className:`mt-0.5 truncate text-[12px] text-fg-3`,children:[e.baseUrl,e.detail?` · ${e.detail}`:``]})]}),(0,V.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1`,children:[(0,V.jsx)(R,{size:`sm`,onClick:()=>void X.test(e.id),disabled:t||e.status!==`ready`,children:t?(0,V.jsx)(w,{}):`Test`}),(0,V.jsx)(R,{size:`sm`,variant:`ghost`,"aria-label":`Remove ${e.label}`,onClick:async()=>await E({title:`Remove ${e.label}?`,body:`Its key is deleted from this computer.`,action:`Remove`,danger:!0})&&void X.remove(e.id),children:(0,V.jsx)(k,{})})]})]}),(0,V.jsxs)(`form`,{className:`mt-2 flex gap-2`,onSubmit:t=>{t.preventDefault(),i.trim()&&X.addModel(e.id,i.trim()).then(()=>a(``))},children:[(0,V.jsx)(`input`,{"data-hand":!0,value:i,onChange:e=>a(e.target.value),placeholder:`Add a model by its id (e.g. anthropic/claude-sonnet-5-5)`,className:r(Q,`flex-1 font-mono`),"aria-label":`Model for ${e.label}`}),(0,V.jsx)(R,{type:`submit`,size:`md`,disabled:!i.trim(),children:`Add model`})]}),n&&(0,V.jsx)(`p`,{className:r(`mt-1.5 text-[12px]`,n.ok?`text-ok`:`text-bad`),children:n.message})]})}function gn(){let[e,t]=(0,B.useState)(`openrouter`),[n,i]=(0,B.useState)(``),[a,o]=(0,B.useState)(``),[s,c]=(0,B.useState)(``),[l,u]=(0,B.useState)(!1),d=q(e=>e.error),f=se.find(t=>t.id===e),p=se.filter(e=>e.id!==`ollama`&&e.id!==`lmstudio`).map(e=>({value:e.id,label:e.label}));return(0,V.jsxs)(`form`,{className:`space-y-2 px-3 py-3`,"data-add-provider":!0,onSubmit:async t=>{t.preventDefault(),u(!0);let r=await X.add({preset:e,baseUrl:e===`custom`?n:void 0,key:a||void 0,models:s?[s]:void 0});u(!1),r&&(o(``),c(``),i(``))},children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[(0,V.jsx)(S,{className:`size-[14px] text-fg-3`}),` Add a provider`]}),(0,V.jsx)(`p`,{className:`text-[12px] leading-relaxed text-fg-3`,children:f.note??`Any provider with an OpenAI-compatible API.`}),(0,V.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,V.jsx)(Zt,{value:e,onChange:t,options:p,className:`w-[190px]`}),e===`custom`&&(0,V.jsx)(`input`,{"data-hand":!0,value:n,onChange:e=>i(e.target.value),placeholder:`https://api.example.com/v1`,className:r(`h-8 min-w-0 rounded-[8px] bg-sunken px-2.5 text-[12.5px] text-fg ring-1 ring-inset ring-line-strong outline-none placeholder:text-fg-3 focus:ring-human-line`,`min-w-[220px] flex-1 font-mono`),"aria-label":`Provider address`})]}),(0,V.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,V.jsx)(`input`,{"data-hand":!0,type:`password`,value:a,onChange:e=>o(e.target.value),placeholder:f.keyUrl?`API key`:`API key (if it needs one)`,autoComplete:`off`,className:r(Q,`min-w-[200px] flex-1 font-mono`),"aria-label":`Provider key`}),(0,V.jsx)(`input`,{"data-hand":!0,value:s,onChange:e=>c(e.target.value),placeholder:`Model id (optional)`,className:r(Q,`w-[200px] font-mono`),"aria-label":`Provider model`}),(0,V.jsx)(R,{type:`submit`,size:`md`,variant:`primary`,disabled:l||f.keyUrl!==null&&!a.trim()||e===`custom`&&!n.trim(),children:l?(0,V.jsx)(w,{}):`Add`})]}),f.keyUrl&&(0,V.jsxs)(`a`,{className:`inline-flex items-center gap-0.5 text-[12px] text-human-fg hover:underline`,href:f.keyUrl,target:`_blank`,rel:`noreferrer`,children:[`Get `,/^[aeiou]/i.test(f.label)||/^x[A-Z]/.test(f.label)?`an`:`a`,` `,f.label,` key `,(0,V.jsx)(Oe,{className:`size-3`})]}),d&&(0,V.jsx)(`p`,{className:`text-[12px] text-bad`,children:d})]})}function _n(){let e=nn();if(!e)return(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[12.5px] text-fg-3`,children:[(0,V.jsx)(w,{}),` Looking for AI on this computer…`]});let t=(t,n)=>e.connections.filter(e=>e.auth===t&&(!n||n.includes(e.id))),n=e.connections.length&&e.ready&&!e.routes.code;return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(tn,{sub:(0,V.jsx)(Ne,{}),children:`AI`}),n?(0,V.jsx)(`p`,{className:`mb-3 text-[12px] text-fg-3`,children:`The automated tests’ stand-in answers requests in this studio.`}):null,!e.ready&&(0,V.jsx)(vn,{state:e}),(0,V.jsx)(Z,{id:`ai-plans`,title:`Your plans`,sub:`No API key needed: Saywright runs the official app on this computer, signed in with your own account. Requests count toward your plan’s limits, not a bill.`,children:t(`subscription`).map(e=>(0,V.jsx)(fn,{c:e},e.id))}),(0,V.jsx)(Z,{id:`ai-keys`,title:`API keys`,sub:`Pay per use, straight to the provider. Prompt caching keeps repeated context cheap.`,children:t(`key`,[`anthropic`,`openai`,`gemini`]).map(t=>(0,V.jsx)(pn,{c:t,file:e.keysFile},t.id))}),(0,V.jsx)(Z,{id:`ai-local`,title:`On this computer`,sub:`Free and private. Changes need a model that can call tools (most recent ones can).`,children:t(`local`,[`ollama`,`lmstudio`]).map(e=>(0,V.jsx)(mn,{c:e},e.id))}),(0,V.jsxs)(Z,{title:`Other providers`,sub:`OpenRouter, Groq, DeepSeek, Mistral, xAI, or any OpenAI-compatible address.`,children:[e.connections.filter(e=>e.kind===`compatible`&&e.id!==`ollama`&&e.id!==`lmstudio`).map(e=>(0,V.jsx)(hn,{c:e},e.id)),(0,V.jsx)(gn,{})]}),e.ready&&(0,V.jsxs)(`div`,{className:`mt-8`,"data-ai-advanced":!0,children:[(0,V.jsx)(`h3`,{className:`text-[14px] font-semibold text-fg`,children:`Advanced`}),(0,V.jsx)(`p`,{className:`mt-1 max-w-[500px] text-[12.5px] leading-relaxed text-fg-3`,children:`Which model does each kind of work, and how hard it thinks. Automatic is a good start.`}),(0,V.jsx)(sn,{state:e})]})]})}function vn({state:e}){let t=t=>e.connections.filter(e=>e.auth===t),n=t(`subscription`),r=n.filter(e=>e.status===`needs-login`),i=t(`local`).filter(e=>e.id===`ollama`||e.id===`lmstudio`),a=[{id:`ai-plans`,title:`Use a plan you pay for`,body:`Claude, ChatGPT or Gemini, through their app on this computer, signed in as you. No extra bill.`,status:r.length?`${r.map(e=>on[e.id]??e.label).join(`, `)}: sign in needed`:n.every(e=>e.status===`missing`)?`None installed yet`:`Not ready yet`,action:`Set it up`},{id:`ai-keys`,title:`Paste an API key`,body:`Anthropic, OpenAI or Google, billed per use by the provider. You can set a budget.`,status:`No key yet`,action:`Add a key`},{id:`ai-local`,title:`Run a model on this computer`,body:`Free and private, with Ollama or LM Studio. Changes need a model that can use tools.`,status:i.every(e=>e.status===`missing`)?`Not installed yet`:`Not running`,action:`Set it up`}];return(0,V.jsxs)(`section`,{className:`mb-7`,"data-connect-ai":!0,children:[(0,V.jsx)(`h3`,{className:`text-[14px] font-semibold text-fg`,children:`Connect an AI`}),(0,V.jsx)(`p`,{className:`mt-1 max-w-[520px] text-[12.5px] leading-relaxed text-fg-3`,children:`Quick edits work without one. For everything else, pick one of these:`}),(0,V.jsx)(`div`,{className:`mt-3 grid gap-2 sm:grid-cols-3`,children:a.map(e=>(0,V.jsxs)(`div`,{className:`flex flex-col rounded-[12px] p-3 ring-1 ring-inset ring-line`,"data-way":e.id,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:e.title}),(0,V.jsx)(`p`,{className:`mt-1 flex-1 text-[12px] leading-relaxed text-fg-3`,children:e.body}),(0,V.jsxs)(`div`,{className:`mt-2 flex items-center gap-1.5 text-[11.5px] text-fg-3`,children:[(0,V.jsx)(D,{tone:`warn`}),` `,e.status]}),(0,V.jsx)(R,{size:`sm`,variant:`primary`,className:`mt-2.5 self-start`,onClick:()=>document.getElementById(e.id)?.scrollIntoView({behavior:`smooth`,block:`start`}),children:e.action})]},e.id))})]})}var yn=e=>e.input+e.output+e.cacheRead+e.cacheWrite;function bn({label:e,value:t,sub:n}){return(0,V.jsxs)(`div`,{className:`rounded-[10px] px-3 py-2.5 ring-1 ring-inset ring-line`,children:[(0,V.jsx)(`div`,{className:`text-[11.5px] text-fg-3`,children:e}),(0,V.jsx)(`div`,{className:`mt-0.5 text-[17px] font-semibold tabular-nums tracking-[-0.01em] text-fg`,children:t}),n&&(0,V.jsx)(`div`,{className:`mt-0.5 text-[11.5px] tabular-nums text-fg-3`,children:n})]})}function xn({rows:e}){return e.length?(0,V.jsxs)(`table`,{className:`w-full text-[12px]`,children:[(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{className:`text-left text-fg-3`,children:[(0,V.jsx)(`th`,{className:`px-3 py-2 font-medium`,children:` `}),(0,V.jsx)(`th`,{className:`px-2 py-2 text-right font-medium`,children:`Calls`}),(0,V.jsx)(`th`,{className:`px-2 py-2 text-right font-medium`,children:`Tokens`}),(0,V.jsx)(`th`,{className:`px-3 py-2 text-right font-medium`,children:`Cost`})]})}),(0,V.jsx)(`tbody`,{className:`tabular-nums`,children:e.slice(0,8).map(e=>(0,V.jsxs)(`tr`,{className:`border-t border-line`,children:[(0,V.jsx)(`td`,{className:`max-w-[260px] truncate px-3 py-1.5 text-fg`,children:e.label}),(0,V.jsx)(`td`,{className:`px-2 py-1.5 text-right text-fg-2`,children:e.calls}),(0,V.jsx)(`td`,{className:`px-2 py-1.5 text-right text-fg-2`,children:Se(yn(e))}),(0,V.jsx)(`td`,{className:`px-3 py-1.5 text-right text-fg-2`,children:e.usd>=.005?I(e.usd):e.planUsd>=.005?`plan (${I(e.planUsd)})`:e.unpriced===e.calls?`—`:`$0`})]},e.key))})]}):(0,V.jsx)(`div`,{className:`px-3 py-4 text-[12px] text-fg-3`,children:`No AI calls this month yet.`})}function Sn({label:e,hint:t,value:n,onSave:i,unit:a}){let[o,s]=(0,B.useState)(n==null?``:String(n));(0,B.useEffect)(()=>s(n==null?``:String(n)),[n]);let c=()=>{let e=o.trim(),t=e===``?null:Number(e.replace(/[$,\s]/g,``));t===null||Number.isFinite(t)&&t>=0?i(t):s(n==null?``:String(n))};return(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-4 px-3 py-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:e}),(0,V.jsx)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:t})]}),(0,V.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1.5`,children:[a===`$`&&(0,V.jsx)(`span`,{className:`text-[12.5px] text-fg-3`,children:`$`}),(0,V.jsx)(`input`,{"data-hand":!0,inputMode:`decimal`,value:o,onChange:e=>s(e.target.value),onBlur:c,onKeyDown:e=>e.key===`Enter`&&c(),placeholder:`No limit`,"aria-label":e,className:r(Q,`w-[110px] text-right tabular-nums`)}),a===`tokens`&&(0,V.jsx)(`span`,{className:`text-[12.5px] text-fg-3`,children:`tokens`})]})]})}function Cn(){let e=nn(),[t,n]=(0,B.useState)(`feature`),i=e?.usage,a=(0,B.useMemo)(()=>Math.max(1e-4,...(i?.days??[]).map(e=>e.usd>0?e.usd:0)),[i]),o=(0,B.useMemo)(()=>Math.max(1,...(i?.days??[]).map(e=>e.tokens)),[i]);if(!i)return(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[12.5px] text-fg-3`,children:[(0,V.jsx)(w,{}),` Loading usage…`]});let s=i.days.some(e=>e.usd>0);return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(tn,{sub:`Every AI call the studio makes is counted here: tokens, cost at list price, and what prompt caching saved. Plans and local models are counted too; they bill no dollars.`,children:`Usage and budget`}),i.status.message&&(0,V.jsxs)(`div`,{className:r(`mb-3 rounded-[10px] px-3 py-2 text-[12.5px] ring-1 ring-inset`,i.status.level===`over`?`text-bad ring-bad/40`:`text-warn ring-warn/40`),"data-budget-status":i.status.level,children:[i.status.message,` `,i.status.level===`over`&&i.budget.mode===`stop`?`AI requests are paused until you raise the limit or reset the count.`:``]}),(0,V.jsxs)(`div`,{className:`grid grid-cols-2 gap-2 sm:grid-cols-4`,"data-usage":!0,children:[(0,V.jsx)(bn,{label:`Today`,value:I(i.today.usd),sub:`${Se(yn(i.today))} tokens · ${i.today.calls} calls`}),(0,V.jsx)(bn,{label:`This month`,value:I(i.month.usd),sub:`${Se(yn(i.month))} tokens · ${i.month.calls} calls`}),(0,V.jsx)(bn,{label:`Plan use this month`,value:I(i.month.planUsd),sub:`what it would cost through the API`}),(0,V.jsx)(bn,{label:`Saved by caching`,value:I(i.savedUsd),sub:`this month`})]}),(0,V.jsxs)(`div`,{className:`mt-3 rounded-[10px] px-3 pb-2 pt-3 ring-1 ring-inset ring-line`,children:[(0,V.jsx)(`div`,{className:`flex h-16 items-end gap-[3px]`,"aria-label":`Last 30 days`,children:i.days.map(e=>{let t=s?e.usd/a:e.tokens/o;return(0,V.jsx)(`div`,{title:`${e.date}: ${I(e.usd)}, ${Se(e.tokens)} tokens`,className:r(`min-h-[2px] flex-1 rounded-t-[2px]`,e.tokens?`bg-ai/70`:`bg-line`),style:{height:`${Math.max(3,t*100)}%`}},e.date)})}),(0,V.jsxs)(`div`,{className:`mt-1.5 flex justify-between text-[11px] text-fg-3`,children:[(0,V.jsx)(`span`,{children:`30 days ago`}),(0,V.jsx)(`span`,{children:s?`Cost per day`:`Tokens per day`}),(0,V.jsx)(`span`,{children:`Today`})]})]}),(0,V.jsxs)(`div`,{className:`mt-3 rounded-[10px] ring-1 ring-inset ring-line`,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between px-3 pt-2.5`,children:[(0,V.jsx)(`span`,{className:`text-[12px] font-semibold text-fg-2`,children:`This month by`}),(0,V.jsx)(Re,{value:t,onChange:n,options:[{value:`feature`,label:`Feature`},{value:`model`,label:`Model`},{value:`app`,label:`App`}]})]}),(0,V.jsx)(xn,{rows:t===`feature`?i.byFeature:t===`model`?i.byModel:i.byApp})]}),(0,V.jsxs)(Z,{title:`Budget`,sub:`Limits on what API keys may spend. A daily token limit also covers plans and local models.`,children:[(0,V.jsx)(Sn,{label:`Daily limit`,hint:`Dollars per day, across all API keys.`,value:i.budget.dailyUsd,unit:`$`,onSave:e=>void X.setBudget({dailyUsd:e})}),(0,V.jsx)(Sn,{label:`Monthly limit`,hint:`Dollars per calendar month.`,value:i.budget.monthlyUsd,unit:`$`,onSave:e=>void X.setBudget({monthlyUsd:e})}),(0,V.jsx)(Sn,{label:`Daily tokens`,hint:`All tokens per day, plans and local models included.`,value:i.budget.dailyTokens,unit:`tokens`,onSave:e=>void X.setBudget({dailyTokens:e})}),(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-4 px-3 py-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:`At a limit`}),(0,V.jsxs)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:[`Warn from `,Math.round(i.budget.warnAt*100),`% and carry on, or stop AI requests until you raise the limit or reset.`]})]}),(0,V.jsx)(Re,{value:i.budget.mode,onChange:e=>void X.setBudget({mode:e}),options:[{value:`warn`,label:`Warn`},{value:`stop`,label:`Stop`}]})]})]}),(0,V.jsx)(Z,{title:`Reset`,children:(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 px-3 py-3`,children:[(0,V.jsx)(R,{size:`sm`,onClick:()=>void X.reset(`today`),children:`Reset today’s count`}),(0,V.jsx)(R,{size:`sm`,onClick:()=>void X.reset(`month`),children:`Reset this month`}),(0,V.jsx)(R,{size:`sm`,variant:`ghost`,onClick:async()=>await E({title:`Forget every AI call the studio recorded?`,body:`The counts and history start again from zero.`,action:`Forget them`,danger:!0})&&void X.reset(`all`),children:`Clear history`}),(i.resetAt.today||i.resetAt.month)&&(0,V.jsxs)(`span`,{className:`text-[11.5px] text-fg-3`,children:[`Counting since `,new Date(Math.max(i.resetAt.today??0,i.resetAt.month??0)).toLocaleString()]})]})})]})}function wn(){let e=nn(),[t,n]=(0,B.useState)(!1),r=e?.mcp;if(!r)return(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[12.5px] text-fg-3`,children:[(0,V.jsx)(w,{}),` Loading…`]});let i=`Bearer ${r.token}`,a=[{app:`Claude Code`,where:`Run in a terminal`,text:`claude mcp add --transport http saywright ${r.url} --header "Authorization: ${i}"`},{app:`Claude Desktop`,where:`Settings → Developer → Edit config (claude_desktop_config.json)`,text:JSON.stringify({mcpServers:{saywright:{command:r.stdio.command,args:r.stdio.args}}},null,2)},{app:`Cursor`,where:`~/.cursor/mcp.json`,text:JSON.stringify({mcpServers:{saywright:{url:r.url,headers:{Authorization:i}}}},null,2)},{app:`VS Code`,where:`.vscode/mcp.json in your project`,text:JSON.stringify({servers:{saywright:{type:`http`,url:r.url,headers:{Authorization:i}}}},null,2)},{app:`Codex`,where:`~/.codex/config.toml`,text:`[mcp_servers.saywright]\nurl = "${r.url}"\nhttp_headers = { Authorization = "${i}" }`}];return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(tn,{sub:`Claude Desktop, Claude Code, Cursor, VS Code and Codex can see what you point at here and propose changes you keep or undo in the studio. They connect to Saywright over MCP, on this computer only.`,children:`Use Saywright from other AI apps`}),(0,V.jsx)(Z,{title:`Connection`,children:(0,V.jsxs)(`div`,{className:`space-y-2 px-3 py-3`,children:[(0,V.jsx)(`div`,{className:`text-[12px] text-fg-3`,children:`Address`}),(0,V.jsx)(dn,{text:r.url,label:`Copy the address`}),(0,V.jsxs)(`div`,{className:`flex items-center justify-between pt-1 text-[12px] text-fg-3`,children:[(0,V.jsx)(`span`,{children:`Token (keep it private: it lets apps on this computer use Saywright)`}),(0,V.jsxs)(`button`,{className:`inline-flex items-center gap-1 text-human-fg hover:underline [&_svg]:size-3`,onClick:()=>n(!t),children:[t?(0,V.jsx)(Ce,{}):(0,V.jsx)(Ie,{}),` `,t?`Hide`:`Show`]})]}),(0,V.jsx)(dn,{text:r.token,shown:t?r.token:`•`.repeat(24),label:`Copy the token`})]})}),(0,V.jsx)(Z,{title:`Set up an app`,sub:`Copy the settings for the app you use. They read what you selected or pinned (get_context), the code (read_file, search_code), your test sessions’ reports, and propose changes (propose_change).`,children:a.map(e=>(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-mcp-app":e.app,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:e.app}),(0,V.jsxs)(`div`,{className:`flex items-center gap-1 text-[11.5px] text-fg-3`,children:[e.where,(0,V.jsx)(un,{text:e.text,label:`Copy the ${e.app} settings`})]})]}),(0,V.jsx)(`pre`,{tabIndex:0,role:`region`,"aria-label":`${e.app} settings`,className:`mt-1.5 max-h-[140px] overflow-auto whitespace-pre-wrap break-all rounded-[8px] bg-sunken p-2.5 font-mono text-[11.5px] leading-relaxed text-fg-2`,children:t?e.text:e.text.replaceAll(r.token,`•`.repeat(12))})]},e.app))})]})}var Tn={key:`https://console.cloud.google.com/apis/credentials`,crux:`https://console.cloud.google.com/apis/library/chromeuxreport.googleapis.com`,serviceAccounts:`https://console.cloud.google.com/iam-admin/serviceaccounts`,searchApi:`https://console.cloud.google.com/apis/library/searchconsole.googleapis.com`,analyticsApi:`https://console.cloud.google.com/apis/library/analyticsdata.googleapis.com`};function En({href:e,children:t}){return(0,V.jsxs)(`a`,{className:`inline-flex items-center gap-0.5 text-human-fg hover:underline`,href:e,target:`_blank`,rel:`noreferrer`,children:[t,` `,(0,V.jsx)(Oe,{className:`size-3`})]})}function Dn({r:e}){return e?(0,V.jsx)(`p`,{className:r(`mt-1.5 text-[12px] leading-relaxed`,e.ok?`text-ok`:`text-bad`),children:e.message}):null}function On(){let[e,t]=(0,B.useState)(null),[n,r]=(0,B.useState)(null),i=he(e=>e.apps.find(t=>t.id===e.active)?.name??null);(0,B.useEffect)(()=>{N.get(`/connectors/google`).then(t,e=>r(e.message))},[]);let a=async e=>{try{return t(await N.put(`/connectors/google`,e)),{ok:!0,message:`Saved.`}}catch(e){return{ok:!1,message:e.message}}};return e?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(tn,{sub:`Real-user data next to the expert reviews: how fast your pages are for real visitors, what people search to find them, and how they use them. Read-only, from your own Google accounts, for your production address.`,children:`Google data`}),(0,V.jsx)(kn,{state:e,save:a}),(0,V.jsx)(An,{state:e,save:a}),(0,V.jsx)(jn,{state:e,save:a,appName:i},i??``)]}):(0,V.jsx)(`div`,{className:`flex items-center gap-2 text-[12.5px] text-fg-3`,children:n??(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(w,{}),` Loading…`]})})}function kn({state:e,save:t}){let[n,i]=(0,B.useState)(``),[a,o]=(0,B.useState)(!1),[s,c]=(0,B.useState)(!1),[l,u]=(0,B.useState)(null);return(0,V.jsx)(Z,{title:`Speed for real users`,sub:`Chrome UX Report: Core Web Vitals of real Chrome users on phones over the last 28 days. Free; needs a Google Cloud API key with the Chrome UX Report API turned on.`,children:(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-service":`crux`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[`Google API key`,` `,e.apiKey?(0,V.jsxs)(y,{tone:`ok`,children:[(0,V.jsx)(D,{tone:`ok`,className:`mr-0.5`}),` `,e.apiKey]}):(0,V.jsx)(y,{children:`No key`})]}),(0,V.jsxs)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:[(0,V.jsx)(En,{href:Tn.key,children:`Create a key`}),` · `,(0,V.jsx)(En,{href:Tn.crux,children:`Turn on the Chrome UX Report API`})]}),(0,V.jsxs)(`form`,{className:`mt-2 flex gap-2`,onSubmit:async e=>{if(e.preventDefault(),!n.trim())return;c(!0);let r=await t({apiKey:n.trim()});c(!1),u(r),r?.ok&&i(``)},children:[(0,V.jsxs)(`div`,{className:`relative min-w-0 flex-1`,children:[(0,V.jsx)(`input`,{"data-hand":!0,type:a?`text`:`password`,value:n,onChange:e=>i(e.target.value),placeholder:e.apiKey?`Replace the key`:`Paste a Google API key`,autoComplete:`off`,spellCheck:!1,"aria-label":`Google API key`,className:r(Q,`w-full pr-8 font-mono`)}),(0,V.jsx)(`button`,{type:`button`,className:`absolute right-1.5 top-1.5 text-fg-3 hover:text-fg [&_svg]:size-[14px]`,onClick:()=>o(!a),"aria-label":a?`Hide key`:`Show key`,children:a?(0,V.jsx)(Ce,{}):(0,V.jsx)(Ie,{})})]}),(0,V.jsx)(R,{type:`submit`,size:`md`,variant:`primary`,disabled:!n.trim()||s,children:s?(0,V.jsx)(w,{}):`Save`}),e.apiKey&&(0,V.jsx)(R,{type:`button`,size:`md`,variant:`ghost`,"aria-label":`Remove the Google API key`,onClick:async()=>await E({title:`Remove the Google API key?`,body:`It is deleted from this computer. Real-user speed data (Chrome UX Report) stops until you add a key again.`,action:`Remove`,danger:!0})&&u(await t({apiKey:null})),children:(0,V.jsx)(k,{})})]}),(0,V.jsx)(Dn,{r:l}),(0,V.jsx)(`p`,{className:`mt-1.5 text-[11.5px] text-fg-3`,children:`Saved in .env.local in the Saywright folder, readable only by you. Restrict it to the Chrome UX Report API in Google Cloud.`})]})})}function An({state:e,save:t}){let[n,i]=(0,B.useState)(``),[a,o]=(0,B.useState)(!1),[s,c]=(0,B.useState)(null),l=(0,B.useRef)(null),u=async e=>{o(!0);let n=await t({account:e});o(!1),c(n),n?.ok&&i(``)};return(0,V.jsx)(Z,{title:`Search Console and Analytics`,sub:`A Google Cloud service account that you add, read-only, to your Search Console property and your Google Analytics 4 property. Saywright signs in as it; your own Google password is never asked for.`,children:(0,V.jsxs)(`div`,{className:`px-3 py-3`,"data-service":`account`,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] font-medium text-fg`,children:[`Service account`,` `,e.account?(0,V.jsxs)(y,{tone:`ok`,children:[(0,V.jsx)(D,{tone:`ok`,className:`mr-0.5`}),` Added`]}):(0,V.jsx)(y,{children:`Not added`})]}),e.account&&(0,V.jsx)(`div`,{className:`mt-0.5 truncate font-mono text-[11.5px] text-fg-2`,children:e.account.email})]}),e.account&&(0,V.jsx)(R,{size:`sm`,variant:`ghost`,icon:(0,V.jsx)(k,{}),onClick:async()=>await E({title:`Remove the service account key?`,body:`It is deleted from this computer. Search Console and Analytics data stop until you add it again.`,action:`Remove`,danger:!0})&&c(await t({account:null})),children:`Remove`})]}),!e.account&&(0,V.jsxs)(`ol`,{className:`mt-2 list-decimal space-y-1 pl-4 text-[12px] leading-relaxed text-fg-3`,children:[(0,V.jsxs)(`li`,{children:[(0,V.jsx)(En,{href:Tn.serviceAccounts,children:`Create a service account`}),` and add a JSON key to it.`]}),(0,V.jsxs)(`li`,{children:[`Turn on the `,(0,V.jsx)(En,{href:Tn.searchApi,children:`Search Console API`}),` and the `,(0,V.jsx)(En,{href:Tn.analyticsApi,children:`Google Analytics Data API`}),`.`]}),(0,V.jsx)(`li`,{children:`Add its email address as a user: in Search Console (Settings → Users, Restricted) and in Analytics (Admin → Property access, Viewer).`}),(0,V.jsx)(`li`,{children:`Choose the key file, or paste what it says, below.`})]}),(0,V.jsxs)(`div`,{className:`mt-2 space-y-2`,children:[(0,V.jsx)(`textarea`,{"data-hand":!0,value:n,onChange:e=>i(e.target.value),placeholder:e.account?`Paste another key to replace it`:`{ "type": "service_account", "client_email": "…", "private_key": "…" }`,spellCheck:!1,autoComplete:`off`,rows:3,"aria-label":`Service account key (JSON)`,className:r(Q,`block h-auto w-full resize-none py-2 font-mono text-[11.5px]`)}),(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(R,{size:`md`,variant:`primary`,disabled:!n.trim()||a,onClick:()=>void u(n),children:a?(0,V.jsx)(w,{}):`Save`}),(0,V.jsx)(R,{size:`md`,icon:(0,V.jsx)(Wt,{}),onClick:()=>l.current?.click(),disabled:a,children:`Choose the key file`}),(0,V.jsx)(`input`,{ref:l,type:`file`,accept:`application/json,.json`,className:`hidden`,onChange:async e=>{let t=e.target.files?.[0];if(e.target.value=``,t){if(t.size>2e4)return c({ok:!1,message:`That file is too big to be a service account key.`});await u(await t.text())}}})]})]}),(0,V.jsx)(Dn,{r:s}),(0,V.jsx)(`p`,{className:`mt-1.5 text-[11.5px] text-fg-3`,children:`Kept in Saywright’s data folder, readable only by you. Only its email and private key are kept; it is sent nowhere but Google.`})]})})}function jn({state:e,save:t,appName:n}){let[i,a]=(0,B.useState)(e.settings.searchConsoleSite??``),[o,s]=(0,B.useState)(e.settings.ga4Property??``),[c,l]=(0,B.useState)(null),[u,d]=(0,B.useState)(null),f=i.trim()!==(e.settings.searchConsoleSite??``)||o.trim()!==(e.settings.ga4Property??``),p=o.trim()!==``&&!/^\d{4,15}$/.test(o.trim()),m=!e.apiKey&&!e.account;return n?(0,V.jsx)(Z,{title:`For ${n}`,sub:`Each linked app has its own properties. Data is looked up for the same page on the app’s production address.`,children:(0,V.jsxs)(`div`,{className:`space-y-3 px-3 py-3`,"data-service":`app`,children:[(0,V.jsxs)(`div`,{className:`text-[12px] leading-relaxed`,children:[(0,V.jsx)(`span`,{className:`text-fg-3`,children:`Production address: `}),e.publicUrl?(0,V.jsx)(`span`,{className:`font-mono text-[11.5px] text-fg-2`,children:e.publicUrl}):(0,V.jsxs)(`span`,{className:`text-warn`,children:[`none yet.`,` `,(0,V.jsx)(`button`,{className:`text-human-fg hover:underline`,onClick:()=>{P({overlay:null}),oe.show()},children:`Add one to the app`}),` `,`(Google only has data for public pages).`]})]}),(0,V.jsxs)(`label`,{className:`block space-y-1`,children:[(0,V.jsx)(`span`,{className:`text-[12px] font-medium text-fg`,children:`Search Console property`}),(0,V.jsx)(`input`,{"data-hand":!0,value:i,onChange:e=>a(e.target.value),placeholder:`sc-domain:example.com or https://www.example.com/`,spellCheck:!1,className:r(Q,`w-full font-mono`)})]}),(0,V.jsxs)(`label`,{className:`block space-y-1`,children:[(0,V.jsx)(`span`,{className:`text-[12px] font-medium text-fg`,children:`Google Analytics 4 property ID`}),(0,V.jsx)(`input`,{"data-hand":!0,value:o,onChange:e=>s(e.target.value),placeholder:`123456789 (Admin → Property details)`,inputMode:`numeric`,spellCheck:!1,className:r(Q,`w-full font-mono`),"aria-invalid":p}),p&&(0,V.jsx)(`span`,{className:`block text-[11.5px] text-bad`,children:`A property ID is only numbers (not the G-… measurement ID).`})]}),(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,V.jsx)(R,{size:`md`,variant:`primary`,disabled:!f||p||!!c,onClick:async()=>{l(`save`),d(await t({settings:{searchConsoleSite:i.trim(),ga4Property:o.trim()}})),l(null)},children:c===`save`?(0,V.jsx)(w,{}):`Save`}),(0,V.jsx)(R,{size:`md`,disabled:!!c||f||m,title:m?`Add an API key or a service account first`:f?`Save first`:void 0,onClick:async()=>{l(`test`);try{d(await N.post(`/connectors/google/test`))}catch(e){d({ok:!1,message:e.message})}l(null)},"data-test-google":!0,children:c===`test`?(0,V.jsx)(w,{}):`Test`})]}),(0,V.jsx)(Dn,{r:u})]})}):(0,V.jsx)(Z,{title:`This app`,children:(0,V.jsx)(`p`,{className:`px-3 py-3 text-[12px] text-fg-3`,children:`Open an app to choose its Search Console and Analytics properties.`})})}function Mn(){let e=de(e=>e.speech);if((0,B.useEffect)(()=>void me.refreshSpeech(),[]),!e)return(0,V.jsx)(w,{className:`size-3.5 text-fg-3`});if(e.runtime===`missing`)return(0,V.jsx)(`p`,{className:`text-[12px] text-warn`,children:`The speech engine isn’t installed for this platform. Run npm install again; voice still works through the browser.`});let t=e.models.filter(e=>e.wordErrors.ar!=null).sort((e,t)=>e.wordErrors.ar-t.wordErrors.ar)[0],n=e.models.find(t=>t.id===e.active.ar),r=t&&!t.installed&&n?.wordErrors.ar!=null&&n.id!==t.id?{now:n.wordErrors.ar,best:t}:null;return(0,V.jsxs)(`div`,{className:`space-y-2`,children:[r&&(0,V.jsxs)(`p`,{className:`rounded-[10px] bg-ai-soft px-3 py-2 text-[12px] text-ai-fg ring-1 ring-inset ring-ai-line/30`,"data-arabic-upgrade":!0,children:[`For Arabic, `,r.best.label.split(` (`)[0],` gets `,r.best.wordErrors.ar,`% of words wrong, against `,r.now,`% with the model you have (measured on real speech). It is a`,` `,(r.best.sizeMb/1e3).toFixed(1),` GB download, once.`]}),(0,V.jsxs)(`div`,{className:`divide-y divide-line rounded-[10px] ring-1 ring-inset ring-line`,children:[e.runtime===`failed`&&(0,V.jsxs)(`p`,{className:`px-3 py-2 text-[12px] text-bad`,children:[`The speech engine crashed: `,e.runtimeError]}),e.models.map(t=>{let n=[`ar`,`en`].filter(n=>e.active[n]===t.id),r=[`ar`,`en`].filter(e=>t.wordErrors[e]!=null).map(e=>`${e===`ar`?`Arabic`:`English`} ${t.wordErrors[e]}%`);return(0,V.jsxs)(`div`,{className:`flex items-center gap-3 px-3 py-2.5`,children:[(0,V.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[12.5px] font-medium text-fg`,children:[t.installed&&(0,V.jsx)(D,{tone:`ok`}),t.label]}),(0,V.jsxs)(`div`,{className:`text-[11.5px] text-fg-3`,children:[t.sizeMb>=1e3?`${(t.sizeMb/1e3).toFixed(1)} GB`:`${t.sizeMb} MB`,r.length>0&&(0,V.jsxs)(`span`,{title:`Words it gets wrong per hundred, on real read speech (FLEURS)`,children:[` · word errors: `,r.join(`, `)]}),n.length>0&&` · used for ${n.map(e=>e===`ar`?`Arabic`:`English`).join(` and `)}`,t.error&&(0,V.jsxs)(`span`,{className:`text-bad`,children:[` · `,t.error]})]}),t.installing!=null&&(0,V.jsx)(`div`,{className:`mt-1.5 h-1 overflow-hidden rounded-full bg-active`,children:(0,V.jsx)(`div`,{className:`h-full bg-ai transition-[width] duration-300`,style:{width:`${t.installing}%`}})})]}),t.installed?(0,V.jsx)(pe,{className:`size-4 text-ok`}):t.installing==null?(0,V.jsx)(R,{size:`xs`,icon:(0,V.jsx)(je,{}),onClick:()=>void me.installSpeech(t.id),children:`Install`}):(0,V.jsxs)(`span`,{className:`tabular text-[11.5px] text-fg-3`,children:[t.installing,`%`]})]},t.id)})]})]})}var Nn={ar:[`كبّر هذا`,`الإجمالي غلط، المفروض يكون ثمانين دولار وثمانين سنت`,`زرار الدفع مش بيشتغل لما أضغط عليه`,`غيّر لون الزرار ده للأخضر`,`الصفحة بطيئة جدًا في التحميل`,`تراجع`],en:[`Make this bigger`,`The total is wrong, it should be eighty dollars eighty`,`The pay button does nothing when I click it`,`Change this button to green`,`The page takes too long to load`,`Undo`]};function Pn(e){return`${Math.round(e*100)}%`}function Fn(){let e=L(e=>e.voice.lang),t=/^ar\b/i.test(e)?`ar`:`en`,n=j(e=>e.voice),[i,a]=(0,B.useState)(!1),[o,s]=(0,B.useState)(0),[c,l]=(0,B.useState)([]),u=(0,B.useRef)(0);u.current=o;let d=Nn[t];if((0,B.useEffect)(()=>{if(!i)return;let e=M.dryRun;return M.dryRun=()=>{let e=j.getState().voice.last;if(!e)return;let t=d[u.current];l(n=>[...n,{said:t,browser:e.browser[0]??``,device:e.device}]),s(e=>Math.min(d.length,e+1))},()=>{M.dryRun=e}},[i,d]),!i)return(0,V.jsxs)(R,{size:`sm`,icon:(0,V.jsx)(Be,{}),onClick:()=>(a(!0),s(0),l([])),children:[`Start the check (`,t===`ar`?`Arabic`:`English`,`)`]});let f=n.state===`starting`||n.state===`listening`,p=o>=d.length,m=e=>{let t=c.filter(t=>t[e]);return t.length?1-t.reduce((t,n)=>t+Math.min(1,le(n.said,n[e])),0)/t.length:null},h=m(`browser`),g=m(`device`);return(0,V.jsxs)(`div`,{className:`space-y-3 rounded-[12px] bg-sunken p-3 ring-1 ring-inset ring-line`,"data-accuracy-check":!0,children:[p?(0,V.jsx)(`div`,{className:`text-[13px] font-medium text-fg`,children:`Done. Words heard correctly:`}):(0,V.jsxs)(V.Fragment,{children:[(0,V.jsxs)(`div`,{className:`text-[11.5px] text-fg-3`,children:[`Sentence `,o+1,` of `,d.length,`: hold the button, read it naturally, let go.`]}),(0,V.jsx)(`div`,{dir:`auto`,className:`text-[16px] font-medium leading-relaxed text-fg`,children:d[o]}),(0,V.jsxs)(`button`,{type:`button`,onPointerDown:e=>{e.currentTarget.setPointerCapture?.(e.pointerId),M.pressTalk()},onPointerUp:()=>M.releaseTalk(),onPointerCancel:()=>M.releaseTalk(),className:r(`inline-flex h-8 select-none items-center gap-2 rounded-[9px] px-3 text-[12.5px] font-medium`,f?`bg-human text-[#1b1203]`:`bg-raised text-fg ring-1 ring-inset ring-line hover:bg-hover`),children:[(0,V.jsx)(Be,{className:`size-[14px]`}),n.state===`finishing`?`Checking…`:f?`Listening`:`Hold to read`]})]}),c.length>0&&(0,V.jsxs)(`div`,{className:`grid grid-cols-2 gap-2`,children:[(0,V.jsxs)(`div`,{className:`rounded-[9px] bg-raised p-2.5 ring-1 ring-inset ring-line`,children:[(0,V.jsx)(`div`,{className:`text-[11.5px] text-fg-3`,children:`Browser recogniser`}),(0,V.jsx)(`div`,{className:`tabular text-[18px] font-semibold text-fg`,children:h==null?`—`:Pn(h)})]}),(0,V.jsxs)(`div`,{className:`rounded-[9px] bg-raised p-2.5 ring-1 ring-inset ring-line`,children:[(0,V.jsx)(`div`,{className:`text-[11.5px] text-fg-3`,children:`On this computer`}),(0,V.jsx)(`div`,{className:`tabular text-[18px] font-semibold text-fg`,children:g==null?`—`:Pn(g)})]})]}),c.length>0&&(0,V.jsx)(`div`,{className:`max-h-[160px] space-y-1.5 overflow-y-auto text-[12px]`,children:c.map((e,t)=>(0,V.jsxs)(`div`,{className:`rounded-[8px] bg-raised px-2.5 py-1.5 ring-1 ring-inset ring-line`,children:[(0,V.jsx)(`div`,{dir:`auto`,className:`font-medium text-fg`,children:e.said}),e.browser&&(0,V.jsxs)(`div`,{dir:`auto`,className:`text-fg-3`,children:[`Browser: `,e.browser,` `,(0,V.jsxs)(`span`,{className:`tabular`,children:[`(`,Pn(1-Math.min(1,le(e.said,e.browser))),`)`]})]}),e.device&&(0,V.jsxs)(`div`,{dir:`auto`,className:`text-fg-3`,children:[`Computer: `,e.device,` `,(0,V.jsxs)(`span`,{className:`tabular`,children:[`(`,Pn(1-Math.min(1,le(e.said,e.device))),`)`]})]})]},t))}),(0,V.jsxs)(`div`,{className:`flex gap-2`,children:[(0,V.jsx)(R,{size:`xs`,icon:(0,V.jsx)(ke,{}),onClick:()=>(s(0),l([])),children:`Start over`}),(0,V.jsx)(R,{size:`xs`,variant:`ghost`,onClick:()=>a(!1),children:`Close`})]})]})}var In=[{id:`general`,label:`General`,icon:(0,V.jsx)(Xt,{})},{id:`hand`,label:`Hand`,icon:(0,V.jsx)(De,{})},{id:`voice`,label:`Voice`,icon:(0,V.jsx)(Be,{})},{id:`ai`,label:`AI`,icon:(0,V.jsx)(x,{})},{id:`usage`,label:`Usage and budget`,icon:(0,V.jsx)(Ee,{})},{id:`mcp`,label:`Other AI apps`,icon:(0,V.jsx)(Jt,{})},{id:`services`,label:`Google data`,icon:(0,V.jsx)(Ht,{})},{id:`shortcuts`,label:`Shortcuts`,icon:(0,V.jsx)(Kt,{})},{id:`labs`,label:`Labs`,icon:(0,V.jsx)(te,{})}];function Ln(){let e=j(e=>e.overlay===`settings`),t=j(e=>e.settingsTab),n=_e();return(0,V.jsx)(ne,{open:e,onOpenChange:e=>P({overlay:e?`settings`:null}),title:`Settings`,className:`h-[600px] w-[min(780px,calc(100vw-32px))]`,children:(0,V.jsxs)(`div`,{className:`flex h-full min-h-0`,children:[(0,V.jsxs)(`nav`,{className:`flex w-[188px] shrink-0 flex-col gap-0.5 border-r border-line bg-sunken/50 p-2`,children:[(0,V.jsx)(`div`,{className:`px-2 pb-2 pt-1.5 text-[13px] font-semibold text-fg`,children:`Settings`}),In.filter(e=>e.id!==`hand`||n).map(e=>(0,V.jsxs)(`button`,{"data-hand":!0,onClick:()=>P({settingsTab:e.id}),className:r(`flex h-8 items-center gap-2.5 rounded-[7px] px-2 text-[12.5px] font-medium transition-colors [&_svg]:size-[15px]`,t===e.id?`bg-active text-fg`:`text-fg-2 hover:bg-hover hover:text-fg`),children:[e.icon,e.label]},e.id))]}),(0,V.jsxs)(`div`,{className:`relative min-w-0 flex-1 overflow-y-auto`,children:[(0,V.jsx)(ge,{className:`absolute right-3 top-3`,onClick:()=>P({overlay:null}),"aria-label":`Close`,children:(0,V.jsx)(ve,{})}),(0,V.jsxs)(`div`,{className:`px-6 pb-8 pt-5`,children:[t===`general`&&(0,V.jsx)(zn,{}),t===`hand`&&n&&(0,V.jsx)(Bn,{}),t===`voice`&&(0,V.jsx)(Wn,{}),t===`ai`&&(0,V.jsx)(_n,{}),t===`usage`&&(0,V.jsx)(Cn,{}),t===`mcp`&&(0,V.jsx)(wn,{}),t===`services`&&(0,V.jsx)(On,{}),t===`shortcuts`&&(0,V.jsx)($n,{}),t===`labs`&&(0,V.jsx)(er,{}),t===`hand`&&!n&&(0,V.jsx)(er,{})]})]},t)]})})}function Rn({children:e,sub:t}){return(0,V.jsxs)(`div`,{className:`mb-4`,children:[(0,V.jsx)(`h2`,{className:`text-[15px] font-semibold tracking-[-0.01em] text-fg`,children:e}),t&&(0,V.jsx)(`p`,{className:`mt-1 max-w-[460px] text-[12.5px] leading-relaxed text-fg-3`,children:t})]})}function $({label:e,hint:t,children:n,stack:i}){let a=(0,B.useId)();return(0,V.jsxs)(`div`,{className:r(`border-b border-line py-3.5 last:border-0`,i?`space-y-2.5`:`flex items-center justify-between gap-6`),children:[(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsx)(`div`,{id:a,className:`text-[13px] font-medium text-fg`,children:e}),t&&(0,V.jsx)(`div`,{className:`mt-0.5 text-[12px] leading-relaxed text-fg-3`,children:t})]}),(0,V.jsx)(`div`,{className:r(i?``:`shrink-0`),children:(0,V.jsx)(Me.Provider,{value:a,children:n})})]})}function zn(){let e=_e(),t=L(e=>e.theme),n=L(e=>e.voice.sounds),r=L(e=>e.ui.commitOnKeep),i=L(),a=j(e=>e.status?.target.git);return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Rn,{children:`General`}),(0,V.jsx)($,{label:`Appearance`,children:(0,V.jsx)(Re,{value:t,onChange:e=>i.set({theme:e}),options:[{value:`light`,label:`Light`},{value:`dark`,label:`Dark`},{value:`system`,label:`System`}]})}),(0,V.jsx)($,{label:`Commit when you keep a change`,hint:a?`Kept changes become a git commit that includes what you said.`:`Your app’s folder isn’t a git repository.`,children:(0,V.jsx)(z,{checked:r&&!!a,disabled:!a,onCheckedChange:e=>i.setUi({commitOnKeep:e})})}),(0,V.jsx)($,{label:`Sounds`,hint:`Quiet cues when listening starts, a request is sent, and a change is kept or undone.`,children:(0,V.jsx)(z,{checked:n,onCheckedChange:e=>i.setVoice({sounds:e})})}),(0,V.jsx)($,{label:`Quick-start tour`,hint:`A minute on your own app: point at something, change it, keep or undo it, and where testing and reviews live.`,children:(0,V.jsx)(R,{size:`sm`,onClick:()=>{P({overlay:null}),Le.start()},children:`Take the tour`})}),(0,V.jsx)($,{label:e?`Voice and hand setup`:`Voice check`,hint:e?`The camera, reach and pinch practice for hand control, then talking.`:`Hold Space and talk, to check the studio hears you.`,children:(0,V.jsx)(R,{size:`sm`,onClick:()=>P({overlay:`onboarding`,onboardingStep:e?0:4}),children:e?`Set up`:`Check`})}),(0,V.jsx)($,{label:`Reset all settings`,hint:e?`Theme, layout, voice, hand tuning and calibration, and Labs go back to their defaults.`:`Theme, layout, voice and Labs settings go back to their defaults.`,children:(0,V.jsx)(R,{size:`sm`,variant:`danger`,onClick:()=>i.reset(),children:`Reset`})})]})}function Bn(){let e=j(e=>e.camera),t=L(),[n,r]=(0,B.useState)([]);(0,B.useEffect)(()=>{be().then(e=>r(e.filter(e=>e.deviceId)))},[e.status]);let i=t.engine;return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Rn,{sub:`Point with your index finger. Pinch thumb and index to select or click. Everything runs on this computer; video never leaves it.`,children:`Hand control`}),(0,V.jsx)($,{label:`Hand control`,hint:e.status===`on`?`Tracking at ${e.fps} fps on the ${e.delegate}.`:e.status===`error`?e.error:`Uses your camera to track one hand.`,children:(0,V.jsxs)(`div`,{className:`flex items-center gap-2`,children:[e.status===`starting`&&(0,V.jsx)(w,{className:`text-fg-3`}),(0,V.jsx)(z,{checked:e.status===`on`||e.status===`starting`,onCheckedChange:e=>e?void M.startCamera():M.stopCamera()})]})}),n.length>1&&(0,V.jsx)($,{label:`Camera`,children:(0,V.jsx)(Zt,{value:t.camera.deviceId??n[0]?.deviceId,onChange:n=>{t.setCamera({deviceId:n}),e.status===`on`&&M.startCamera(n)},options:n.map((e,t)=>({value:e.deviceId,label:e.label||`Camera ${t+1}`})),className:`w-[220px]`})}),(0,V.jsx)($,{label:`Reach`,hint:`Map your comfortable pointing area to the screen. Recalibrate if corners are hard to reach.`,children:(0,V.jsx)(R,{size:`sm`,onClick:()=>P({overlay:`calibrate`,calibrateReturn:`settings`}),children:`Calibrate…`})}),(0,V.jsx)($,{label:`Which hand`,hint:`With two hands in view, follow this one.`,children:(0,V.jsx)(Re,{value:i.hand,onChange:e=>t.setEngine({hand:e}),options:[{value:`any`,label:`Either`},{value:`left`,label:`Left`},{value:`right`,label:`Right`}]})}),(0,V.jsx)($,{label:`Steadiness`,hint:`Steadier filters out tremor; responsive follows fast moves with less lag.`,stack:!0,children:(0,V.jsx)(Vn,{left:`Responsive`,right:`Steady`,value:i.steadiness,onChange:e=>t.setEngine({steadiness:e})})}),(0,V.jsx)($,{label:`Pinch sensitivity`,hint:`Lighter means a smaller pinch counts as a click.`,stack:!0,children:(0,V.jsx)(Vn,{left:`Firm`,right:`Light`,value:ye(i.pinchOn),onChange:e=>t.setEngine(fe(e))})}),(0,V.jsx)($,{label:`Aim assist`,hint:`How far the cursor reaches to snap onto small targets.`,stack:!0,children:(0,V.jsx)(Vn,{left:`Off`,right:`Strong`,value:t.aimAssist/48,onChange:e=>t.set({aimAssist:Math.round(e*48)})})}),(0,V.jsx)($,{label:`Select by resting`,hint:`In Edit mode, pointing at something for a second selects it, without a pinch.`,children:(0,V.jsx)(z,{checked:t.dwellSelect,onCheckedChange:e=>t.set({dwellSelect:e})})}),(0,V.jsx)($,{label:`Peace sign starts talking`,hint:`Hold ✌ briefly; pause to send. No keyboard needed.`,children:(0,V.jsx)(z,{checked:i.talkEnabled,onCheckedChange:e=>t.setEngine({talkEnabled:e})})}),(0,V.jsx)($,{label:`Thumbs keep and undo`,hint:`Thumb up keeps the preview, thumb down undoes it.`,children:(0,V.jsx)(z,{checked:i.thumbsEnabled,onCheckedChange:e=>t.setEngine({thumbsEnabled:e})})}),(0,V.jsx)($,{label:`Open palm stops`,hint:`Hold an open hand still to cancel listening or a running request.`,children:(0,V.jsx)(z,{checked:i.palmEnabled,onCheckedChange:e=>t.setEngine({palmEnabled:e})})}),(0,V.jsx)($,{label:`Show hand skeleton`,children:(0,V.jsx)(z,{checked:t.camera.skeleton,onCheckedChange:e=>t.setCamera({skeleton:e})})}),(0,V.jsx)($,{label:`Show gesture legend`,children:(0,V.jsx)(z,{checked:t.camera.legend,onCheckedChange:e=>t.setCamera({legend:e})})})]})}function Vn({left:e,right:t,value:n,onChange:r}){return(0,V.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,V.jsx)(`span`,{className:`w-[72px] text-[11.5px] text-fg-3`,children:e}),(0,V.jsx)(Pe,{value:n,onChange:r}),(0,V.jsx)(`span`,{className:`w-[56px] text-right text-[11.5px] text-fg-3`,children:t})]})}var Hn=[[`en-US`,`English (US)`],[`en-GB`,`English (UK)`],[`en-AU`,`English (Australia)`],[`en-IN`,`English (India)`],[`de-DE`,`Deutsch`],[`fr-FR`,`Français`],[`es-ES`,`Español`],[`it-IT`,`Italiano`],[`pt-BR`,`Português (Brasil)`],[`nl-NL`,`Nederlands`],[`ar-EG`,`العربية (مصر)`],[`ar-SA`,`العربية (السعودية)`],[`ar-AE`,`العربية (الإمارات)`],[`ar-JO`,`العربية (الأردن)`],[`ar-MA`,`العربية (المغرب)`],[`ja-JP`,`日本語`]],Un=[{value:`auto`,label:`Auto`},{value:`browser`,label:`Browser`},{value:`device`,label:`On-device`}];function Wn(){let e=L(),t=j(e=>e.voice.supported),n=j(e=>e.voice.model===`unavailable`),r=/^en\b/i.test(e.voice.lang),i=/^ar\b/i.test(e.voice.lang),a={auto:r?n?`Your browser’s recogniser. Once the on-device model is there, it double-checks what was heard against the recording, keeps your first word and catches misheard short commands.`:`Your browser’s recogniser, double-checked against the recording by a speech model on this computer. It keeps your first word, and catches misheard short commands.`:i?`Your browser’s recogniser and an Arabic speech model on this computer, both hearing you; the studio picks what it understands. Commands work in Egyptian, Gulf, Levantine and standard Arabic.`:`Your browser’s recogniser. (The on-device check understands English and Arabic.)`,browser:`Your browser’s recogniser alone. In Chrome, audio goes to Google’s speech service.`,device:i?`The Arabic speech model on this computer alone: audio never leaves it.`:`A speech model on this computer alone: audio never leaves it. Live words appear a little later.`};return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Rn,{sub:`Quick edits understand English and Arabic phrases; the AI understands any language.`,children:`Voice`}),!t&&(0,V.jsx)(`div`,{className:`mb-3 rounded-[10px] bg-warn-soft p-3 text-[12.5px] text-fg ring-1 ring-inset ring-warn/25`,children:e.voice.engine===`browser`?`This browser has no speech recognition. Choose Auto or On-device, or use Chrome.`:`No microphone is available here, so voice is off. You can still type requests.`}),(0,V.jsxs)($,{label:`Recognition`,hint:a[e.voice.engine],stack:!0,children:[(0,V.jsx)(Re,{value:e.voice.engine,onChange:t=>e.setVoice({engine:t}),options:Un}),e.voice.engine===`device`&&!r&&!i&&(0,V.jsx)(`div`,{className:`text-[12px] text-warn`,children:`On-device recognition understands English and Arabic. Pick one of them, or use Auto.`}),e.voice.engine!==`browser`&&r&&(0,V.jsx)(Gn,{})]}),(0,V.jsx)($,{label:`Language`,children:(0,V.jsx)(Zt,{value:Hn.some(([t])=>t===e.voice.lang)?e.voice.lang:`en-US`,onChange:t=>e.setVoice({lang:t}),options:Hn.map(([e,t])=>({value:e,label:t})),className:`w-[200px]`})}),(0,V.jsx)($,{label:`Speech models on this computer`,hint:`Transcribe test-session narration, and Arabic voice commands. Measured on real recordings of people reading Arabic and English.`,stack:!0,children:(0,V.jsx)(Mn,{})}),(0,V.jsx)($,{label:`Test your microphone`,hint:i?`Hold the button (or Space) and say something like “كبّر هذا”.`:`Hold the button (or Space) and say something like “make this bigger”.`,stack:!0,children:(0,V.jsx)(Jn,{})}),(0,V.jsx)($,{label:`Accuracy on your voice`,hint:`Read a few sentences; see how many words each recogniser gets right for your voice, accent and microphone.`,stack:!0,children:(0,V.jsx)(Fn,{})}),(0,V.jsx)($,{label:`Check before sending`,hint:`What you said appears in the command bar first, with other ways it could have been heard. Press Enter to send it.`,children:(0,V.jsx)(z,{checked:e.voice.review,onCheckedChange:t=>e.setVoice({review:t})})}),(0,V.jsx)($,{label:`Push to talk`,hint:`Hold to talk, release to send.`,children:(0,V.jsx)(ze,{children:`Space`})}),(0,V.jsx)($,{label:`Hands-free`,hint:`Tap Space, click the mic, or hold a peace sign. Sends when you pause.`,children:(0,V.jsx)(`span`,{className:`text-[12px] text-fg-3`,children:`Tap Space · ✌`})}),(0,V.jsx)($,{label:`Pause before sending`,hint:`In hands-free mode, send after ${(e.voice.autoStopMs/1e3).toFixed(1)} s of silence.`,stack:!0,children:(0,V.jsx)(Vn,{left:`0.8 s`,right:`2.5 s`,value:(e.voice.autoStopMs-800)/1700,onChange:t=>e.setVoice({autoStopMs:Math.round(800+t*1700)})})}),(0,V.jsx)($,{label:`Microphone`,hint:`After you talk it stays on for two minutes, so the start of your next sentence isn’t cut off. The audio stays in this tab and is only used when you talk.`,children:(0,V.jsx)(R,{size:`sm`,onClick:()=>M.voice.capture.close(),children:`Turn off now`})})]})}function Gn(){let e=j(e=>e.voice.model),t=j(e=>e.voice.modelError);return e===`ready`?(0,V.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[12px] text-fg-3`,"data-model":`ready`,children:[(0,V.jsx)(D,{tone:`ok`}),` On-device model ready`]}):e===`unavailable`&&t===`The on-device speech model isn’t downloaded.`?(0,V.jsx)(Kn,{}):e===`unavailable`?(0,V.jsxs)(`div`,{className:`text-[12px] text-warn`,"data-model":`unavailable`,children:[`The on-device model isn’t available`,t?`: ${t}`:`.`,` Voice uses the browser’s recogniser meanwhile.`]}):(0,V.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[12px] text-fg-3`,"data-model":`loading`,children:[(0,V.jsx)(w,{className:`size-3`}),` Loading the on-device model…`]})}function Kn(){let[e,t]=(0,B.useState)(null),[n,r]=(0,B.useState)(!1),[i,a]=(0,B.useState)(``);(0,B.useEffect)(()=>{N.get(`/voice-model`).then(t,()=>void 0)},[]);let o=async()=>{r(!0),a(``);try{await N.post(`/voice-model`),M.voice.asr.retry()}catch(e){a(e instanceof Error?e.message:String(e))}finally{r(!1)}};return(0,V.jsxs)(`div`,{className:`space-y-2 text-[12px]`,"data-model":`unavailable`,children:[(0,V.jsx)(`div`,{className:`text-warn`,children:`The on-device model isn’t downloaded yet. Voice uses the browser’s recogniser meanwhile.`}),e&&(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2 text-fg-3`,children:[(0,V.jsx)(R,{size:`sm`,icon:n?(0,V.jsx)(w,{}):(0,V.jsx)(je,{}),disabled:n,onClick:()=>void o(),"data-download-model":!0,children:n?`Downloading…`:`Download the voice model (${e.mb} MB)`}),(0,V.jsxs)(`span`,{children:[`or run `,(0,V.jsx)(`code`,{className:`rounded-[4px] bg-sunken px-1 py-px font-mono text-[11.5px] text-fg-2 ring-1 ring-inset ring-line`,children:e.setup})]})]}),i&&(0,V.jsx)(`div`,{className:`text-bad`,children:i})]})}var qn={browser:`browser`,device:`on-device`,command:`command check`,variant:`sound-alike check`};function Jn(){let e=j(e=>e.voice),[t,n]=(0,B.useState)(null);(0,B.useEffect)(()=>(M.dryRun=()=>n(j.getState().voice.last),()=>{M.dryRun=null}),[]);let i=e.state===`starting`||e.state===`listening`;return(0,V.jsxs)(`div`,{className:`space-y-2.5 rounded-[12px] bg-sunken p-3 ring-1 ring-inset ring-line`,"data-voice-test":!0,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,V.jsxs)(`button`,{type:`button`,onPointerDown:e=>{e.currentTarget.setPointerCapture?.(e.pointerId),M.pressTalk()},onPointerUp:()=>M.releaseTalk(),onPointerCancel:()=>M.releaseTalk(),className:r(`inline-flex h-8 shrink-0 select-none items-center gap-2 rounded-[9px] px-3 text-[12.5px] font-medium transition-colors [&_svg]:size-[14px]`,i?`bg-human text-[#1b1203]`:`bg-raised text-fg ring-1 ring-inset ring-line hover:bg-hover`),children:[(0,V.jsx)(Be,{}),` `,e.state===`starting`?`Starting…`:i?`Listening`:`Hold to talk`]}),(0,V.jsx)(Xn,{active:i})]}),(0,V.jsx)(`div`,{className:`min-h-[40px] text-[13px] leading-relaxed text-fg`,children:i?(0,V.jsx)(`span`,{className:e.words.length?``:`text-fg-3`,children:e.words.join(` `)||`Say something…`}):e.state===`finishing`?(0,V.jsxs)(`span`,{className:`flex items-center gap-2 text-fg-3`,children:[(0,V.jsx)(w,{className:`size-3.5`}),` Working out what you said…`]}):e.error?(0,V.jsx)(`span`,{className:`text-bad`,children:e.error}):t?(0,V.jsx)(Yn,{r:t}):(0,V.jsx)(`span`,{className:`text-fg-3`,children:`Nothing yet.`})})]})}function Yn({r:e}){return(0,V.jsxs)(`div`,{className:`space-y-1`,children:[(0,V.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2`,children:[(0,V.jsx)(`span`,{className:`text-[15px] font-medium text-fg`,children:e.text?`“${e.text}”`:`Didn’t catch anything.`}),e.text&&(0,V.jsxs)(`span`,{className:`text-[11.5px] text-fg-3`,children:[`via `,qn[e.source],` · `,F(e.ms),` after you let go`]})]}),e.browser.length>0&&(0,V.jsxs)(`div`,{className:`text-[12px] text-fg-3`,children:[`Browser heard: `,(0,V.jsx)(`span`,{className:`text-fg-2`,children:e.browser.slice(0,3).map(e=>`“${e}”`).join(` or `)})]}),e.device&&(0,V.jsxs)(`div`,{className:`text-[12px] text-fg-3`,children:[`On-device heard: `,(0,V.jsxs)(`span`,{className:`text-fg-2`,children:[`“`,e.device,`”`]})]}),e.browserError&&(0,V.jsxs)(`div`,{className:`text-[12px] text-fg-3`,children:[`The browser’s recogniser couldn’t listen: `,e.browserError]}),e.loudness>0&&e.loudness<.03&&(0,V.jsx)(`div`,{className:`text-[12px] text-warn`,children:`Your microphone sounds quiet. Move closer, or raise the input volume (on a Mac: System Settings → Sound → Input).`})]})}function Xn({active:e}){let t=(0,B.useRef)(null);return(0,B.useEffect)(()=>{let e=0,n=()=>{let r=M.voice.level();t.current&&(t.current.style.transform=`scaleX(${Math.min(1,r*1.4)})`),e=requestAnimationFrame(n)};return e=requestAnimationFrame(n),()=>cancelAnimationFrame(e)},[]),(0,V.jsx)(`span`,{className:r(`relative h-1.5 flex-1 overflow-hidden rounded-full bg-line transition-opacity`,e?`opacity-100`:`opacity-40`),"aria-hidden":!0,children:(0,V.jsx)(`span`,{ref:t,className:`absolute inset-0 origin-left rounded-full bg-human transition-transform duration-75`,style:{transform:`scaleX(0)`}})})}var Zn=[[`Talk (hold) / hands-free (tap)`,[`Space`]],[`Keep the preview`,[`↵`]],[`Undo the preview`,xe(`mod+z`)],[`Close what is on top, stop, or clear the selection`,[`Esc`]],[`Type a request`,[`/`]],[`Run a suggestion`,[`1`,`–`,`4`]],[`Select what contains it · inside it`,[`↑`,`↓`]],[`Select the previous · next one`,[`←`,`→`]],[`Open in editor`,[`O`]],[`Add to the selection, or take out`,xe(`shift+Click`)],[`Select inner element`,xe(`alt+Click`)],[`Edit · Use · Write test`,[`E`,`U`,`R`]],[`Hand control on/off (Labs)`,[`C`]],[`Toggle panel`,[`\\`]],[`Command palette`,xe(`mod+k`)],[`Help`,[`?`]]],Qn=e=>Zn.filter(([,t])=>e||t[0]!==`C`);function $n(){let e=_e();return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Rn,{children:`Keyboard shortcuts`}),(0,V.jsx)(`div`,{className:`divide-y divide-line`,children:Qn(e).map(([e,t])=>(0,V.jsxs)(`div`,{className:`flex items-center justify-between py-2.5`,children:[(0,V.jsx)(`span`,{className:`text-[12.5px] text-fg-2`,children:e}),(0,V.jsx)(`span`,{className:`flex gap-1`,children:t.map((e,t)=>e===`–`?(0,V.jsx)(`span`,{className:`text-fg-3`,children:`–`},t):(0,V.jsx)(ze,{children:e},t))})]},e))})]})}function er(){let e=_e(),t=L(e=>e.setLabs);return(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(Rn,{sub:`Features still in development. They work, but may change or go away in a later release.`,children:`Labs`}),(0,V.jsx)($,{label:`Hand control`,hint:`Point and pinch with your hand instead of the mouse, and use gestures to keep, undo and talk. Uses your webcam; video never leaves this computer.`,children:(0,V.jsx)(z,{checked:e,onCheckedChange:e=>{t({hand:e}),e&&P({overlay:`onboarding`,onboardingStep:1})},"aria-label":`Hand control`})})]})}export{Ln as SettingsDialog,Qn as shortcutsFor};