@xopcai/xopc 0.0.40 → 0.0.41

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 (34) hide show
  1. package/dist/extensions/telegram/xopc.extension.json +1 -1
  2. package/dist/gateway/static/root/assets/{agents-DcHp6W8S.js → agents-Cg_LGzbv.js} +2 -2
  3. package/dist/gateway/static/root/assets/{agents-DcHp6W8S.js.map → agents-Cg_LGzbv.js.map} +1 -1
  4. package/dist/gateway/static/root/assets/{apps-page-W9XwqSi7.js → apps-page-CW1VZ5L2.js} +2 -2
  5. package/dist/gateway/static/root/assets/{apps-page-W9XwqSi7.js.map → apps-page-CW1VZ5L2.js.map} +1 -1
  6. package/dist/gateway/static/root/assets/{channels-settings-m10wg_Lg.js → channels-settings-BDkP3YdO.js} +2 -2
  7. package/dist/gateway/static/root/assets/{channels-settings-m10wg_Lg.js.map → channels-settings-BDkP3YdO.js.map} +1 -1
  8. package/dist/gateway/static/root/assets/{cron-api-DIzlYLdG.js → cron-api-BF3i6fQ6.js} +2 -2
  9. package/dist/gateway/static/root/assets/{cron-api-DIzlYLdG.js.map → cron-api-BF3i6fQ6.js.map} +1 -1
  10. package/dist/gateway/static/root/assets/{cron-page-B5nTa2u4.js → cron-page-C82UvjSi.js} +2 -2
  11. package/dist/gateway/static/root/assets/{cron-page-B5nTa2u4.js.map → cron-page-C82UvjSi.js.map} +1 -1
  12. package/dist/gateway/static/root/assets/{dist-DL8vJx7B.js → dist-KXNTFU5L.js} +2 -2
  13. package/dist/gateway/static/root/assets/{dist-DL8vJx7B.js.map → dist-KXNTFU5L.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/{extension-debug-page-DMkgbZXH.js → extension-debug-page-Cb1TVFq8.js} +2 -2
  15. package/dist/gateway/static/root/assets/{extension-debug-page-DMkgbZXH.js.map → extension-debug-page-Cb1TVFq8.js.map} +1 -1
  16. package/dist/gateway/static/root/assets/{extension-page-D5iyUHNi.js → extension-page-ClpFl3ym.js} +2 -2
  17. package/dist/gateway/static/root/assets/{extension-page-D5iyUHNi.js.map → extension-page-ClpFl3ym.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-settings-page-DXYuT-Dq.js → extension-settings-page-AawKA54u.js} +2 -2
  19. package/dist/gateway/static/root/assets/{extension-settings-page-DXYuT-Dq.js.map → extension-settings-page-AawKA54u.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/{index-Cir8fqd7.js → index-DFgsyQna.js} +5 -5
  21. package/dist/gateway/static/root/assets/{index-Cir8fqd7.js.map → index-DFgsyQna.js.map} +1 -1
  22. package/dist/gateway/static/root/assets/{logs-page-BuugMrI_.js → logs-page-DCH6aatp.js} +2 -2
  23. package/dist/gateway/static/root/assets/{logs-page-BuugMrI_.js.map → logs-page-DCH6aatp.js.map} +1 -1
  24. package/dist/gateway/static/root/assets/{sessions-page-CaRD3IvA.js → sessions-page-DgAIvstc.js} +2 -2
  25. package/dist/gateway/static/root/assets/{sessions-page-CaRD3IvA.js.map → sessions-page-DgAIvstc.js.map} +1 -1
  26. package/dist/gateway/static/root/assets/{settings-page-DYOSuaHt.js → settings-page-CyQrYfl-.js} +2 -2
  27. package/dist/gateway/static/root/assets/{settings-page-DYOSuaHt.js.map → settings-page-CyQrYfl-.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/{skills-page-CN7HsYLQ.js → skills-page-BR5vm_QN.js} +2 -2
  29. package/dist/gateway/static/root/assets/{skills-page-CN7HsYLQ.js.map → skills-page-BR5vm_QN.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/{use-image-provider-credentials-DPIDwada.js → use-image-provider-credentials-DGrrG5oe.js} +2 -2
  31. package/dist/gateway/static/root/assets/{use-image-provider-credentials-DPIDwada.js.map → use-image-provider-credentials-DGrrG5oe.js.map} +1 -1
  32. package/dist/gateway/static/root/index.html +1 -1
  33. package/dist/package.js +1 -1
  34. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{i as r}from"./vendor-swr-DKvYJ-LI.js";import{At as i,Ci as a,Cn as o,Fn as s,Ln as c,Mt as l,Nt as u,Oi as d,Ot as f,Yr as p,_n as m,ar as h,ci as g,cn as _,dn as v,fr as y,gn as b,jn as x,jt as S,kt as C,ln as w,mi as T,nr as E,on as D,sn as O,vi as k,vn as A,vr as j}from"./index-Cir8fqd7.js";var M=e(t(),1);function N(e){return e===`builtin`||e===`user`?e:`marketplace`}var P=n();function F({className:e}){let t=A(e=>!!e.token),[n,i]=(0,M.useState)(``),[a,o]=(0,M.useState)(``),c=t?`marketplace-${a}`:null;(0,M.useEffect)(()=>{let e=window.setTimeout(()=>o(n.trim()),300);return()=>window.clearTimeout(e)},[n]);let{data:l,isLoading:u,error:d}=r(c,async()=>b(a.length>0?v(`/api/marketplace?q=${encodeURIComponent(a)}`):v(`/api/marketplace`)),{revalidateOnFocus:!1}),f=l?.extensions??[];return(0,P.jsxs)(`div`,{className:s(`flex flex-col gap-4`,e),children:[(0,P.jsxs)(`div`,{className:`relative`,children:[(0,P.jsx)(h,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,strokeWidth:1.75,"aria-hidden":!0}),(0,P.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`Search extensions…`,className:`ui-input h-10 w-full rounded-lg border border-edge bg-surface-base pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted`})]}),d?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:d instanceof Error?d.message:`Failed to load marketplace`}):null,u&&!l?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:`Loading…`}):(0,P.jsx)(`ul`,{className:`flex flex-col gap-3`,children:f.length===0?(0,P.jsx)(`li`,{className:`text-sm text-fg-muted`,children:`No extensions from xopc-store.`}):f.map(e=>(0,P.jsxs)(`li`,{className:`rounded-xl border border-edge bg-surface-base p-4 shadow-surface`,children:[(0,P.jsx)(`div`,{className:`flex flex-wrap items-start justify-between gap-2`,children:(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,P.jsx)(`h3`,{className:`font-semibold text-fg`,children:e.name}),e.verified?(0,P.jsx)(g,{className:`size-4 shrink-0 text-emerald-600 dark:text-emerald-400`,strokeWidth:1.75,"aria-label":`Verified`}):null,e.version?(0,P.jsx)(`span`,{className:`text-xs text-fg-muted`,children:e.version}):null]}),e.description?(0,P.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:e.description}):null,(0,P.jsx)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:(e.categories??[]).map(e=>(0,P.jsx)(`span`,{className:`rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-[11px] text-fg-muted`,children:e},e))}),(0,P.jsxs)(`p`,{className:`mt-2 flex items-center gap-1.5 text-xs text-fg-muted`,children:[(0,P.jsx)(j,{className:`size-3.5 shrink-0`,strokeWidth:1.75,"aria-hidden":!0}),(0,P.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:e.npmPackage})]}),e.homepage?(0,P.jsxs)(`a`,{href:e.homepage,target:`_blank`,rel:`noreferrer`,className:`mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline`,children:[(0,P.jsx)(p,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),`Homepage`]}):null]})}),(0,P.jsxs)(`p`,{className:`mt-3 text-[11px] text-fg-muted`,children:[`npm package:`,` `,(0,P.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:e.npmPackage})]})]},e.id))})]})}function I(){let e=o(e=>e.language),t=x(e),n=m(e=>e.setPageHeader),r=m(e=>e.clearPageHeader),i=_(),a=w(),[c,l]=d(),u=N(c.get(`tab`)),f=c.get(`q`)??``,[p,g]=(0,M.useState)(u),[v,y]=(0,M.useState)(f),[b,S]=(0,M.useState)(null);(0,M.useEffect)(()=>{let e=N(c.get(`tab`)),t=c.get(`q`)??``;g(t=>t===e?t:e),y(e=>e===t?e:t)},[c]),(0,M.useEffect)(()=>{l(e=>{let t=new URLSearchParams(e),n=v.trim();return n?t.set(`q`,n):t.delete(`q`),p===`marketplace`?t.delete(`tab`):t.set(`tab`,p),t.toString()===e.toString()?e:t},{replace:!0})},[p,v,l]);let C=(0,M.useMemo)(()=>i.filter(e=>e.source===`bundled`),[i]),T=(0,M.useMemo)(()=>i.filter(e=>e.source!==`bundled`),[i]),E=p===`builtin`?C:T,D=(0,M.useMemo)(()=>{let t=v.trim().toLowerCase(),n=E;return t&&(n=n.filter(e=>(e.name??``).toLowerCase().includes(t)||e.id.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t))),[...n].sort((t,n)=>t.hasUi===n.hasUi?(t.name||t.id).localeCompare(n.name||n.id,e):t.hasUi?-1:1)},[E,v,e]);if((0,M.useEffect)(()=>{S(e=>{if(!e)return e;let t=i.find(t=>t.id===e.id);return t?L(e)===L(t)&&e.active===t.active?e:t:null})},[i]),(0,M.useLayoutEffect)(()=>(n({startExtra:null,main:(0,P.jsx)(`div`,{className:`w-full min-w-0 px-3 sm:px-5 xl:px-6`,children:(0,P.jsx)(`h1`,{className:`min-w-0 truncate text-base font-semibold tracking-tight text-fg`,children:t.appsPage.title})}),end:null}),()=>r()),[r,t.appsPage.title,n]),a&&p!==`marketplace`)return(0,P.jsx)(W,{});let O=p!==`marketplace`&&E.length>0;return(0,P.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel`,children:[(0,P.jsxs)(`div`,{className:`mx-auto w-full max-w-app-main px-4 py-8`,children:[(0,P.jsxs)(`header`,{className:`mb-6`,children:[(0,P.jsx)(`h1`,{className:`text-xl font-semibold text-fg`,children:t.appsPage.title}),(0,P.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:t.appsPage.subtitle})]}),(0,P.jsxs)(`div`,{className:`mb-5 flex flex-col gap-3 border-b border-edge-subtle pb-3 sm:flex-row sm:items-center sm:justify-between dark:border-edge-subtle`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-x-1 gap-y-1`,role:`tablist`,"aria-label":t.appsPage.appsNavAria,children:[(0,P.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`marketplace`,className:s(`relative max-w-full rounded-md px-3 py-2 text-left text-sm font-medium transition-colors sm:text-center`,p===`marketplace`?`text-fg`:`text-fg-muted hover:text-fg`,p===`marketplace`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`marketplace`),children:t.appsPage.tabMarketplace}),(0,P.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`builtin`,className:s(`relative rounded-md px-3 py-2 text-sm font-medium transition-colors`,p===`builtin`?`text-fg`:`text-fg-muted hover:text-fg`,p===`builtin`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`builtin`),children:[t.appsPage.tabBuiltin,(0,P.jsxs)(`span`,{className:`ml-1 tabular-nums text-fg-muted`,children:[`(`,C.length,`)`]})]}),(0,P.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`user`,className:s(`relative rounded-md px-3 py-2 text-sm font-medium transition-colors`,p===`user`?`text-fg`:`text-fg-muted hover:text-fg`,p===`user`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`user`),children:[t.appsPage.tabUser,(0,P.jsxs)(`span`,{className:`ml-1 tabular-nums text-fg-muted`,children:[`(`,T.length,`)`]})]})]}),O?(0,P.jsxs)(`div`,{className:`relative w-full min-w-0 sm:max-w-xs`,children:[(0,P.jsx)(h,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,"aria-hidden":!0}),(0,P.jsx)(`input`,{type:`search`,value:v,onChange:e=>y(e.target.value),placeholder:t.appsPage.searchPlaceholder,className:`w-full rounded-lg border border-edge bg-surface-base py-2 pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,autoComplete:`off`})]}):null]}),p===`marketplace`?(0,P.jsx)(F,{}):p===`builtin`&&C.length===0?(0,P.jsx)(G,{message:t.appsPage.emptyBuiltin}):p===`user`&&T.length===0?(0,P.jsx)(G,{message:t.appsPage.emptyUser}):D.length===0?(0,P.jsx)(`p`,{className:`rounded-xl border border-dashed border-edge-subtle bg-surface-hover/30 px-4 py-8 text-center text-sm text-fg-muted dark:bg-surface-hover/15`,children:t.appsPage.noSearchResults}):(0,P.jsx)(`div`,{className:`grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:D.map(e=>(0,P.jsx)(V,{extension:e,copy:t.appsPage,showSourceBadge:p===`user`,onOpen:()=>S(e)},e.id))})]}),b?(0,P.jsx)(H,{extension:b,copy:t.appsPage,onClose:()=>S(null)},b.id):null]})}function L(e){return e.activationEligible??e.active}function R(e,t){return e.source===`bundled`?t.providerBundled:e.source===`global`?t.providerGlobal:e.source===`workspace`?t.providerWorkspace:t.providerOther}function z(e,t){return e.source===`global`?t.badgeSourceGlobal:e.source===`workspace`?t.badgeSourceWorkspace:t.badgeSourceOther}function B(e,t){let n=L(e);return n&&e.active?t.runStateLive:n&&!e.active?t.runStatePendingOn:!n&&e.active?t.runStatePendingOff:t.runStateOff}function V({extension:e,copy:t,showSourceBadge:n,onOpen:r}){let i=L(e),a=e.hasUi?t.cardTooltipHasUi:t.cardTooltipNoUi;return(0,P.jsx)(`button`,{type:`button`,onClick:r,className:s(`group flex w-full flex-col rounded-xl border border-edge bg-surface-base p-4 text-left shadow-sm transition-colors`,`hover:border-edge-subtle hover:bg-surface-hover/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,`dark:hover:bg-surface-hover/25`),children:(0,P.jsxs)(`div`,{className:`flex gap-3`,children:[(0,P.jsx)(`div`,{className:`flex size-12 shrink-0 items-center justify-center rounded-xl bg-accent-soft text-base font-semibold text-accent-fg`,"aria-hidden":!0,children:(e.name||e.id).charAt(0).toUpperCase()}),(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,P.jsxs)(`div`,{className:`min-w-0`,children:[(0,P.jsx)(`h2`,{className:`truncate text-sm font-semibold text-fg`,children:e.name}),e.version?(0,P.jsxs)(`span`,{className:`text-[11px] text-fg-muted`,children:[`v`,e.version]}):null]}),i?(0,P.jsxs)(`span`,{className:`inline-flex shrink-0 items-center gap-1 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:[(0,P.jsx)(T,{className:`size-3`,strokeWidth:2.5,"aria-hidden":!0}),t.statusEnabled]}):(0,P.jsx)(`span`,{className:`flex size-8 shrink-0 items-center justify-center rounded-full border-2 border-accent text-accent`,"aria-hidden":!0,children:(0,P.jsx)(y,{className:`size-4`,strokeWidth:2.5})})]}),(0,P.jsx)(`p`,{className:`mt-2 line-clamp-2 text-xs leading-relaxed text-fg-muted`,children:e.description?.trim()||t.cardNoDescription}),(0,P.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[(0,P.jsx)(`span`,{title:a,className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:e.hasUi?t.badgeKindUi:t.badgeKindBackend}),e.source===`bundled`?(0,P.jsx)(`span`,{className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:t.badgeBundled}):n?(0,P.jsx)(`span`,{title:R(e,t),className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:z(e,t)}):null]})]})]})})}function H({extension:e,copy:t,onClose:n}){let r=e.ui?.contributions?.pages??[],o=e.ui?.contributions?.settingsPanels??[],d=e.ui?.contributions?.chatWidgets??[],m=e.ui?.contributions?.sidebarPanels??[],h=r.find(e=>e.showInNav)??r[0],g=o[0],_=h?D(e.id,h):null,v=g?`/settings/ext/${e.id}/${g.id}`:e.hasConfigSchema?`/settings/ext/${e.id}`:null;return(0,P.jsx)(l,{defaultOpen:!0,onOpenChange:e=>!e&&n(),children:(0,P.jsxs)(S,{children:[(0,P.jsx)(i,{className:`xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim`}),(0,P.jsxs)(f,{className:`fixed left-1/2 top-1/2 z-[131] flex max-h-[min(90vh,44rem)] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated`,onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3`,children:[(0,P.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailBack,children:(0,P.jsx)(k,{className:`size-5`})}),(0,P.jsx)(u,{className:`min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg`,children:t.detailTitle}),(0,P.jsxs)(C,{className:`sr-only`,children:[e.name,` (`,e.id,`)`]}),(0,P.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailClose,children:(0,P.jsx)(c,{className:`size-5`})})]}),(0,P.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-5 py-5`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap items-start gap-4`,children:[(0,P.jsx)(`div`,{className:`flex size-16 shrink-0 items-center justify-center rounded-2xl bg-accent-soft text-xl font-semibold text-accent-fg`,"aria-hidden":!0,children:(e.name||e.id).charAt(0).toUpperCase()}),(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsx)(`h3`,{className:`text-lg font-semibold text-fg`,children:e.name}),(0,P.jsxs)(`p`,{className:`mt-0.5 text-sm text-fg-muted`,children:[t.detailProviderPrefix,` `,R(e,t)]}),e.version?(0,P.jsxs)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:[`v`,e.version]}):null]})]}),(0,P.jsx)(`p`,{className:`mt-5 text-sm leading-relaxed text-fg`,children:e.description?.trim()||t.detailNoDescription}),e.hasUi?null:(0,P.jsx)(`p`,{className:`mt-3 text-xs text-fg-muted`,children:t.backendOnlyHint}),(0,P.jsx)(`p`,{className:`mt-2 text-xs text-fg-muted`,children:B(e,t)}),e.source===`bundled`?(0,P.jsx)(`p`,{className:`mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20`,children:t.builtinConfigHint}):(0,P.jsx)(`p`,{className:`mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20`,children:t.cliManageHint}),e.hasUi&&(r.length>0||o.length>0||d.length>0)?(0,P.jsxs)(`section`,{className:`mt-8`,children:[(0,P.jsx)(`h4`,{className:`mb-3 text-sm font-semibold text-fg`,children:t.detailSectionFeatures}),(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[(0,P.jsx)(U,{template:t.badgePages,count:r.length,hidden:r.length===0}),(0,P.jsx)(U,{template:t.badgeSettings,count:o.length,hidden:o.length===0}),(0,P.jsx)(U,{template:t.badgeWidgets,count:d.length,hidden:d.length===0}),(0,P.jsx)(U,{template:t.badgeSidebar,count:m.length,hidden:m.length===0})]})]}):null,O(e)&&(_||v)?(0,P.jsxs)(`div`,{className:`mt-6 flex flex-wrap gap-2 border-t border-edge-subtle pt-4`,children:[_?(0,P.jsxs)(a,{to:_,onClick:n,className:s(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,P.jsx)(p,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.open]}):null,v?(0,P.jsxs)(a,{to:v,onClick:n,className:s(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,P.jsx)(E,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.openSettings]}):null]}):null,(0,P.jsx)(`p`,{className:`mt-6 text-[11px] leading-relaxed text-fg-muted`,children:t.restartNote})]})]})]})})}function U({template:e,count:t,hidden:n}){return n||t===0?null:(0,P.jsx)(`span`,{className:`inline-flex items-center rounded-md bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:e.replace(/\{\{count\}\}/g,String(t))})}function W(){return(0,P.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel`,children:(0,P.jsxs)(`div`,{className:`mx-auto w-full max-w-app-main px-4 py-8`,children:[(0,P.jsx)(`div`,{className:`mb-6 h-8 w-40 max-w-full animate-pulse rounded-md bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mb-2 h-4 w-full max-w-md animate-pulse rounded bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mb-5 h-9 w-full max-w-lg animate-pulse rounded-full bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:[0,1,2,3,4,5].map(e=>(0,P.jsx)(`div`,{className:`h-36 animate-pulse rounded-xl border border-edge bg-surface-base`},e))})]})})}function G({message:e}){return(0,P.jsx)(`div`,{className:`flex min-h-[min(40vh,16rem)] flex-col items-center justify-center rounded-xl border border-dashed border-edge-subtle bg-surface-hover/40 px-4 py-12 text-center dark:bg-surface-hover/20`,children:(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e})})}export{I as AppsPage};
2
- //# sourceMappingURL=apps-page-W9XwqSi7.js.map
1
+ import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{i as t,t as n}from"./vendor-react-DbimaAId.js";import{i as r}from"./vendor-swr-DKvYJ-LI.js";import{At as i,Ci as a,Cn as o,Fn as s,Ln as c,Mt as l,Nt as u,Oi as d,Ot as f,Yr as p,_n as m,ar as h,ci as g,cn as _,dn as v,fr as y,gn as b,jn as x,jt as S,kt as C,ln as w,mi as T,nr as E,on as D,sn as O,vi as k,vn as A,vr as j}from"./index-DFgsyQna.js";var M=e(t(),1);function N(e){return e===`builtin`||e===`user`?e:`marketplace`}var P=n();function F({className:e}){let t=A(e=>!!e.token),[n,i]=(0,M.useState)(``),[a,o]=(0,M.useState)(``),c=t?`marketplace-${a}`:null;(0,M.useEffect)(()=>{let e=window.setTimeout(()=>o(n.trim()),300);return()=>window.clearTimeout(e)},[n]);let{data:l,isLoading:u,error:d}=r(c,async()=>b(a.length>0?v(`/api/marketplace?q=${encodeURIComponent(a)}`):v(`/api/marketplace`)),{revalidateOnFocus:!1}),f=l?.extensions??[];return(0,P.jsxs)(`div`,{className:s(`flex flex-col gap-4`,e),children:[(0,P.jsxs)(`div`,{className:`relative`,children:[(0,P.jsx)(h,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,strokeWidth:1.75,"aria-hidden":!0}),(0,P.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`Search extensions…`,className:`ui-input h-10 w-full rounded-lg border border-edge bg-surface-base pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted`})]}),d?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:d instanceof Error?d.message:`Failed to load marketplace`}):null,u&&!l?(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:`Loading…`}):(0,P.jsx)(`ul`,{className:`flex flex-col gap-3`,children:f.length===0?(0,P.jsx)(`li`,{className:`text-sm text-fg-muted`,children:`No extensions from xopc-store.`}):f.map(e=>(0,P.jsxs)(`li`,{className:`rounded-xl border border-edge bg-surface-base p-4 shadow-surface`,children:[(0,P.jsx)(`div`,{className:`flex flex-wrap items-start justify-between gap-2`,children:(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,P.jsx)(`h3`,{className:`font-semibold text-fg`,children:e.name}),e.verified?(0,P.jsx)(g,{className:`size-4 shrink-0 text-emerald-600 dark:text-emerald-400`,strokeWidth:1.75,"aria-label":`Verified`}):null,e.version?(0,P.jsx)(`span`,{className:`text-xs text-fg-muted`,children:e.version}):null]}),e.description?(0,P.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:e.description}):null,(0,P.jsx)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:(e.categories??[]).map(e=>(0,P.jsx)(`span`,{className:`rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-[11px] text-fg-muted`,children:e},e))}),(0,P.jsxs)(`p`,{className:`mt-2 flex items-center gap-1.5 text-xs text-fg-muted`,children:[(0,P.jsx)(j,{className:`size-3.5 shrink-0`,strokeWidth:1.75,"aria-hidden":!0}),(0,P.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:e.npmPackage})]}),e.homepage?(0,P.jsxs)(`a`,{href:e.homepage,target:`_blank`,rel:`noreferrer`,className:`mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline`,children:[(0,P.jsx)(p,{className:`size-3.5`,strokeWidth:1.75,"aria-hidden":!0}),`Homepage`]}):null]})}),(0,P.jsxs)(`p`,{className:`mt-3 text-[11px] text-fg-muted`,children:[`npm package:`,` `,(0,P.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:e.npmPackage})]})]},e.id))})]})}function I(){let e=o(e=>e.language),t=x(e),n=m(e=>e.setPageHeader),r=m(e=>e.clearPageHeader),i=_(),a=w(),[c,l]=d(),u=N(c.get(`tab`)),f=c.get(`q`)??``,[p,g]=(0,M.useState)(u),[v,y]=(0,M.useState)(f),[b,S]=(0,M.useState)(null);(0,M.useEffect)(()=>{let e=N(c.get(`tab`)),t=c.get(`q`)??``;g(t=>t===e?t:e),y(e=>e===t?e:t)},[c]),(0,M.useEffect)(()=>{l(e=>{let t=new URLSearchParams(e),n=v.trim();return n?t.set(`q`,n):t.delete(`q`),p===`marketplace`?t.delete(`tab`):t.set(`tab`,p),t.toString()===e.toString()?e:t},{replace:!0})},[p,v,l]);let C=(0,M.useMemo)(()=>i.filter(e=>e.source===`bundled`),[i]),T=(0,M.useMemo)(()=>i.filter(e=>e.source!==`bundled`),[i]),E=p===`builtin`?C:T,D=(0,M.useMemo)(()=>{let t=v.trim().toLowerCase(),n=E;return t&&(n=n.filter(e=>(e.name??``).toLowerCase().includes(t)||e.id.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t))),[...n].sort((t,n)=>t.hasUi===n.hasUi?(t.name||t.id).localeCompare(n.name||n.id,e):t.hasUi?-1:1)},[E,v,e]);if((0,M.useEffect)(()=>{S(e=>{if(!e)return e;let t=i.find(t=>t.id===e.id);return t?L(e)===L(t)&&e.active===t.active?e:t:null})},[i]),(0,M.useLayoutEffect)(()=>(n({startExtra:null,main:(0,P.jsx)(`div`,{className:`w-full min-w-0 px-3 sm:px-5 xl:px-6`,children:(0,P.jsx)(`h1`,{className:`min-w-0 truncate text-base font-semibold tracking-tight text-fg`,children:t.appsPage.title})}),end:null}),()=>r()),[r,t.appsPage.title,n]),a&&p!==`marketplace`)return(0,P.jsx)(W,{});let O=p!==`marketplace`&&E.length>0;return(0,P.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel`,children:[(0,P.jsxs)(`div`,{className:`mx-auto w-full max-w-app-main px-4 py-8`,children:[(0,P.jsxs)(`header`,{className:`mb-6`,children:[(0,P.jsx)(`h1`,{className:`text-xl font-semibold text-fg`,children:t.appsPage.title}),(0,P.jsx)(`p`,{className:`mt-1 text-sm text-fg-muted`,children:t.appsPage.subtitle})]}),(0,P.jsxs)(`div`,{className:`mb-5 flex flex-col gap-3 border-b border-edge-subtle pb-3 sm:flex-row sm:items-center sm:justify-between dark:border-edge-subtle`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-x-1 gap-y-1`,role:`tablist`,"aria-label":t.appsPage.appsNavAria,children:[(0,P.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`marketplace`,className:s(`relative max-w-full rounded-md px-3 py-2 text-left text-sm font-medium transition-colors sm:text-center`,p===`marketplace`?`text-fg`:`text-fg-muted hover:text-fg`,p===`marketplace`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`marketplace`),children:t.appsPage.tabMarketplace}),(0,P.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`builtin`,className:s(`relative rounded-md px-3 py-2 text-sm font-medium transition-colors`,p===`builtin`?`text-fg`:`text-fg-muted hover:text-fg`,p===`builtin`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`builtin`),children:[t.appsPage.tabBuiltin,(0,P.jsxs)(`span`,{className:`ml-1 tabular-nums text-fg-muted`,children:[`(`,C.length,`)`]})]}),(0,P.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":p===`user`,className:s(`relative rounded-md px-3 py-2 text-sm font-medium transition-colors`,p===`user`?`text-fg`:`text-fg-muted hover:text-fg`,p===`user`&&`after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent`),onClick:()=>g(`user`),children:[t.appsPage.tabUser,(0,P.jsxs)(`span`,{className:`ml-1 tabular-nums text-fg-muted`,children:[`(`,T.length,`)`]})]})]}),O?(0,P.jsxs)(`div`,{className:`relative w-full min-w-0 sm:max-w-xs`,children:[(0,P.jsx)(h,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,"aria-hidden":!0}),(0,P.jsx)(`input`,{type:`search`,value:v,onChange:e=>y(e.target.value),placeholder:t.appsPage.searchPlaceholder,className:`w-full rounded-lg border border-edge bg-surface-base py-2 pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,autoComplete:`off`})]}):null]}),p===`marketplace`?(0,P.jsx)(F,{}):p===`builtin`&&C.length===0?(0,P.jsx)(G,{message:t.appsPage.emptyBuiltin}):p===`user`&&T.length===0?(0,P.jsx)(G,{message:t.appsPage.emptyUser}):D.length===0?(0,P.jsx)(`p`,{className:`rounded-xl border border-dashed border-edge-subtle bg-surface-hover/30 px-4 py-8 text-center text-sm text-fg-muted dark:bg-surface-hover/15`,children:t.appsPage.noSearchResults}):(0,P.jsx)(`div`,{className:`grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:D.map(e=>(0,P.jsx)(V,{extension:e,copy:t.appsPage,showSourceBadge:p===`user`,onOpen:()=>S(e)},e.id))})]}),b?(0,P.jsx)(H,{extension:b,copy:t.appsPage,onClose:()=>S(null)},b.id):null]})}function L(e){return e.activationEligible??e.active}function R(e,t){return e.source===`bundled`?t.providerBundled:e.source===`global`?t.providerGlobal:e.source===`workspace`?t.providerWorkspace:t.providerOther}function z(e,t){return e.source===`global`?t.badgeSourceGlobal:e.source===`workspace`?t.badgeSourceWorkspace:t.badgeSourceOther}function B(e,t){let n=L(e);return n&&e.active?t.runStateLive:n&&!e.active?t.runStatePendingOn:!n&&e.active?t.runStatePendingOff:t.runStateOff}function V({extension:e,copy:t,showSourceBadge:n,onOpen:r}){let i=L(e),a=e.hasUi?t.cardTooltipHasUi:t.cardTooltipNoUi;return(0,P.jsx)(`button`,{type:`button`,onClick:r,className:s(`group flex w-full flex-col rounded-xl border border-edge bg-surface-base p-4 text-left shadow-sm transition-colors`,`hover:border-edge-subtle hover:bg-surface-hover/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,`dark:hover:bg-surface-hover/25`),children:(0,P.jsxs)(`div`,{className:`flex gap-3`,children:[(0,P.jsx)(`div`,{className:`flex size-12 shrink-0 items-center justify-center rounded-xl bg-accent-soft text-base font-semibold text-accent-fg`,"aria-hidden":!0,children:(e.name||e.id).charAt(0).toUpperCase()}),(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[(0,P.jsxs)(`div`,{className:`min-w-0`,children:[(0,P.jsx)(`h2`,{className:`truncate text-sm font-semibold text-fg`,children:e.name}),e.version?(0,P.jsxs)(`span`,{className:`text-[11px] text-fg-muted`,children:[`v`,e.version]}):null]}),i?(0,P.jsxs)(`span`,{className:`inline-flex shrink-0 items-center gap-1 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:[(0,P.jsx)(T,{className:`size-3`,strokeWidth:2.5,"aria-hidden":!0}),t.statusEnabled]}):(0,P.jsx)(`span`,{className:`flex size-8 shrink-0 items-center justify-center rounded-full border-2 border-accent text-accent`,"aria-hidden":!0,children:(0,P.jsx)(y,{className:`size-4`,strokeWidth:2.5})})]}),(0,P.jsx)(`p`,{className:`mt-2 line-clamp-2 text-xs leading-relaxed text-fg-muted`,children:e.description?.trim()||t.cardNoDescription}),(0,P.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[(0,P.jsx)(`span`,{title:a,className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:e.hasUi?t.badgeKindUi:t.badgeKindBackend}),e.source===`bundled`?(0,P.jsx)(`span`,{className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:t.badgeBundled}):n?(0,P.jsx)(`span`,{title:R(e,t),className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:z(e,t)}):null]})]})]})})}function H({extension:e,copy:t,onClose:n}){let r=e.ui?.contributions?.pages??[],o=e.ui?.contributions?.settingsPanels??[],d=e.ui?.contributions?.chatWidgets??[],m=e.ui?.contributions?.sidebarPanels??[],h=r.find(e=>e.showInNav)??r[0],g=o[0],_=h?D(e.id,h):null,v=g?`/settings/ext/${e.id}/${g.id}`:e.hasConfigSchema?`/settings/ext/${e.id}`:null;return(0,P.jsx)(l,{defaultOpen:!0,onOpenChange:e=>!e&&n(),children:(0,P.jsxs)(S,{children:[(0,P.jsx)(i,{className:`xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim`}),(0,P.jsxs)(f,{className:`fixed left-1/2 top-1/2 z-[131] flex max-h-[min(90vh,44rem)] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated`,onOpenAutoFocus:e=>e.preventDefault(),children:[(0,P.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3`,children:[(0,P.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailBack,children:(0,P.jsx)(k,{className:`size-5`})}),(0,P.jsx)(u,{className:`min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg`,children:t.detailTitle}),(0,P.jsxs)(C,{className:`sr-only`,children:[e.name,` (`,e.id,`)`]}),(0,P.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailClose,children:(0,P.jsx)(c,{className:`size-5`})})]}),(0,P.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-5 py-5`,children:[(0,P.jsxs)(`div`,{className:`flex flex-wrap items-start gap-4`,children:[(0,P.jsx)(`div`,{className:`flex size-16 shrink-0 items-center justify-center rounded-2xl bg-accent-soft text-xl font-semibold text-accent-fg`,"aria-hidden":!0,children:(e.name||e.id).charAt(0).toUpperCase()}),(0,P.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,P.jsx)(`h3`,{className:`text-lg font-semibold text-fg`,children:e.name}),(0,P.jsxs)(`p`,{className:`mt-0.5 text-sm text-fg-muted`,children:[t.detailProviderPrefix,` `,R(e,t)]}),e.version?(0,P.jsxs)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:[`v`,e.version]}):null]})]}),(0,P.jsx)(`p`,{className:`mt-5 text-sm leading-relaxed text-fg`,children:e.description?.trim()||t.detailNoDescription}),e.hasUi?null:(0,P.jsx)(`p`,{className:`mt-3 text-xs text-fg-muted`,children:t.backendOnlyHint}),(0,P.jsx)(`p`,{className:`mt-2 text-xs text-fg-muted`,children:B(e,t)}),e.source===`bundled`?(0,P.jsx)(`p`,{className:`mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20`,children:t.builtinConfigHint}):(0,P.jsx)(`p`,{className:`mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20`,children:t.cliManageHint}),e.hasUi&&(r.length>0||o.length>0||d.length>0)?(0,P.jsxs)(`section`,{className:`mt-8`,children:[(0,P.jsx)(`h4`,{className:`mb-3 text-sm font-semibold text-fg`,children:t.detailSectionFeatures}),(0,P.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[(0,P.jsx)(U,{template:t.badgePages,count:r.length,hidden:r.length===0}),(0,P.jsx)(U,{template:t.badgeSettings,count:o.length,hidden:o.length===0}),(0,P.jsx)(U,{template:t.badgeWidgets,count:d.length,hidden:d.length===0}),(0,P.jsx)(U,{template:t.badgeSidebar,count:m.length,hidden:m.length===0})]})]}):null,O(e)&&(_||v)?(0,P.jsxs)(`div`,{className:`mt-6 flex flex-wrap gap-2 border-t border-edge-subtle pt-4`,children:[_?(0,P.jsxs)(a,{to:_,onClick:n,className:s(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,P.jsx)(p,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.open]}):null,v?(0,P.jsxs)(a,{to:v,onClick:n,className:s(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,P.jsx)(E,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.openSettings]}):null]}):null,(0,P.jsx)(`p`,{className:`mt-6 text-[11px] leading-relaxed text-fg-muted`,children:t.restartNote})]})]})]})})}function U({template:e,count:t,hidden:n}){return n||t===0?null:(0,P.jsx)(`span`,{className:`inline-flex items-center rounded-md bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:e.replace(/\{\{count\}\}/g,String(t))})}function W(){return(0,P.jsx)(`div`,{className:`flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel`,children:(0,P.jsxs)(`div`,{className:`mx-auto w-full max-w-app-main px-4 py-8`,children:[(0,P.jsx)(`div`,{className:`mb-6 h-8 w-40 max-w-full animate-pulse rounded-md bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mb-2 h-4 w-full max-w-md animate-pulse rounded bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mb-5 h-9 w-full max-w-lg animate-pulse rounded-full bg-surface-hover`}),(0,P.jsx)(`div`,{className:`mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:[0,1,2,3,4,5].map(e=>(0,P.jsx)(`div`,{className:`h-36 animate-pulse rounded-xl border border-edge bg-surface-base`},e))})]})})}function G({message:e}){return(0,P.jsx)(`div`,{className:`flex min-h-[min(40vh,16rem)] flex-col items-center justify-center rounded-xl border border-dashed border-edge-subtle bg-surface-hover/40 px-4 py-12 text-center dark:bg-surface-hover/20`,children:(0,P.jsx)(`p`,{className:`text-sm text-fg-muted`,children:e})})}export{I as AppsPage};
2
+ //# sourceMappingURL=apps-page-CW1VZ5L2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apps-page-W9XwqSi7.js","names":[],"sources":["../../../../../web/src/features/apps/apps-page.constants.ts","../../../../../web/src/features/extensions/extension-marketplace.tsx","../../../../../web/src/pages/apps-page.tsx"],"sourcesContent":["export type AppsMainTab = 'marketplace' | 'builtin' | 'user';\n\nexport function parseAppsMainTab(raw: string | null): AppsMainTab {\n if (raw === 'builtin' || raw === 'user') return raw;\n return 'marketplace';\n}\n","import { CheckCircle, ExternalLink, Package, Search } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport useSWR from 'swr';\n\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\nimport { cn } from '@/lib/cn';\n\ntype RegistryEntry = {\n id: string;\n name: string;\n description?: string;\n npmPackage: string;\n version?: string;\n categories?: string[];\n tags?: string[];\n verified?: boolean;\n homepage?: string;\n author?: string;\n};\n\ntype MarketplaceResponse = { ok: boolean; extensions: RegistryEntry[] };\n\nexport function ExtensionMarketplacePanel({ className }: { className?: string }) {\n const hasToken = useGatewayStore((s) => Boolean(s.token));\n const [q, setQ] = useState('');\n const [debounced, setDebounced] = useState('');\n const key = hasToken ? `marketplace-${debounced}` : null;\n\n useEffect(() => {\n const t = window.setTimeout(() => setDebounced(q.trim()), 300);\n return () => window.clearTimeout(t);\n }, [q]);\n\n const { data, isLoading, error } = useSWR(\n key,\n async () => {\n const url =\n debounced.length > 0\n ? apiUrl(`/api/marketplace?q=${encodeURIComponent(debounced)}`)\n : apiUrl('/api/marketplace');\n return fetchJson<MarketplaceResponse>(url);\n },\n { revalidateOnFocus: false },\n );\n\n const extensions = data?.extensions ?? [];\n\n return (\n <div className={cn('flex flex-col gap-4', className)}>\n <div className=\"relative\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted\"\n strokeWidth={1.75}\n aria-hidden\n />\n <input\n type=\"search\"\n value={q}\n onChange={(e) => setQ(e.target.value)}\n placeholder=\"Search extensions…\"\n className=\"ui-input h-10 w-full rounded-lg border border-edge bg-surface-base pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted\"\n />\n </div>\n\n {error ? (\n <p className=\"text-sm text-fg-muted\">\n {error instanceof Error ? error.message : 'Failed to load marketplace'}\n </p>\n ) : null}\n\n {isLoading && !data ? (\n <p className=\"text-sm text-fg-muted\">Loading…</p>\n ) : (\n <ul className=\"flex flex-col gap-3\">\n {extensions.length === 0 ? (\n <li className=\"text-sm text-fg-muted\">No extensions from xopc-store.</li>\n ) : (\n extensions.map((e) => (\n <li\n key={e.id}\n className=\"rounded-xl border border-edge bg-surface-base p-4 shadow-surface\"\n >\n <div className=\"flex flex-wrap items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"font-semibold text-fg\">{e.name}</h3>\n {e.verified ? (\n <CheckCircle\n className=\"size-4 shrink-0 text-emerald-600 dark:text-emerald-400\"\n strokeWidth={1.75}\n aria-label=\"Verified\"\n />\n ) : null}\n {e.version ? (\n <span className=\"text-xs text-fg-muted\">{e.version}</span>\n ) : null}\n </div>\n {e.description ? (\n <p className=\"mt-1 text-sm text-fg-muted\">{e.description}</p>\n ) : null}\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n {(e.categories ?? []).map((c) => (\n <span\n key={c}\n className=\"rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-[11px] text-fg-muted\"\n >\n {c}\n </span>\n ))}\n </div>\n <p className=\"mt-2 flex items-center gap-1.5 text-xs text-fg-muted\">\n <Package className=\"size-3.5 shrink-0\" strokeWidth={1.75} aria-hidden />\n <code className=\"rounded bg-surface-panel px-1 py-0.5\">{e.npmPackage}</code>\n </p>\n {e.homepage ? (\n <a\n href={e.homepage}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline\"\n >\n <ExternalLink className=\"size-3.5\" strokeWidth={1.75} aria-hidden />\n Homepage\n </a>\n ) : null}\n </div>\n </div>\n <p className=\"mt-3 text-[11px] text-fg-muted\">\n npm package:{' '}\n <code className=\"rounded bg-surface-panel px-1 py-0.5\">{e.npmPackage}</code>\n </p>\n </li>\n ))\n )}\n </ul>\n )}\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ArrowLeft, Check, ExternalLink, Plus, Search, Settings, X } from 'lucide-react';\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { Link, useSearchParams } from 'react-router-dom';\n\nimport { parseAppsMainTab, type AppsMainTab } from '@/features/apps/apps-page.constants';\nimport {\n extensionExposesGatewayShellUi,\n useExtensions,\n useExtensionsLoading,\n} from '@/features/extensions/extension-provider';\nimport { ExtensionMarketplacePanel } from '@/features/extensions/extension-marketplace';\nimport { extensionPagePath } from '@/features/extensions/extension-paths';\nimport type { ExtensionApiRow, PageContribution } from '@/features/extensions/types';\nimport { messages } from '@/i18n/messages';\nimport type { MessageBundle } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { usePageHeaderStore } from '@/stores/page-header-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\ntype AppsPageCopy = MessageBundle['appsPage'];\n\nexport function AppsPage() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const setPageHeader = usePageHeaderStore((s) => s.setPageHeader);\n const clearPageHeader = usePageHeaderStore((s) => s.clearPageHeader);\n const extensions = useExtensions();\n const loading = useExtensionsLoading();\n const [searchParams, setSearchParams] = useSearchParams();\n\n const initialTab = parseAppsMainTab(searchParams.get('tab'));\n const initialQ = searchParams.get('q') ?? '';\n const [mainTab, setMainTab] = useState<AppsMainTab>(initialTab);\n const [search, setSearch] = useState(initialQ);\n const [detail, setDetail] = useState<ExtensionApiRow | null>(null);\n\n useEffect(() => {\n const nextTab = parseAppsMainTab(searchParams.get('tab'));\n const nextQ = searchParams.get('q') ?? '';\n setMainTab((prev) => (prev === nextTab ? prev : nextTab));\n setSearch((prev) => (prev === nextQ ? prev : nextQ));\n }, [searchParams]);\n\n useEffect(() => {\n setSearchParams(\n (prev) => {\n const params = new URLSearchParams(prev);\n const qq = search.trim();\n if (qq) params.set('q', qq);\n else params.delete('q');\n if (mainTab !== 'marketplace') params.set('tab', mainTab);\n else params.delete('tab');\n if (params.toString() === prev.toString()) return prev;\n return params;\n },\n { replace: true },\n );\n }, [mainTab, search, setSearchParams]);\n\n const bundledExtensions = useMemo(\n () => extensions.filter((e) => e.source === 'bundled'),\n [extensions],\n );\n const userExtensions = useMemo(\n () => extensions.filter((e) => e.source !== 'bundled'),\n [extensions],\n );\n\n const listForTab = mainTab === 'builtin' ? bundledExtensions : userExtensions;\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n let list = listForTab;\n if (q) {\n list = list.filter(\n (e) =>\n (e.name ?? '').toLowerCase().includes(q) ||\n e.id.toLowerCase().includes(q) ||\n (e.description ?? '').toLowerCase().includes(q),\n );\n }\n return [...list].sort((a, b) => {\n if (a.hasUi !== b.hasUi) return a.hasUi ? -1 : 1;\n return (a.name || a.id).localeCompare(b.name || b.id, language);\n });\n }, [listForTab, search, language]);\n\n /** Keep dialog + cards in sync after SWR refetch (detail was a stale row reference). */\n useEffect(() => {\n setDetail((prev) => {\n if (!prev) return prev;\n const next = extensions.find((e) => e.id === prev.id);\n if (!next) return null;\n const eligPrev = activationEligibleFor(prev);\n const eligNext = activationEligibleFor(next);\n if (eligPrev === eligNext && prev.active === next.active) return prev;\n return next;\n });\n }, [extensions]);\n\n useLayoutEffect(() => {\n setPageHeader({\n startExtra: null,\n main: (\n <div className=\"w-full min-w-0 px-3 sm:px-5 xl:px-6\">\n <h1 className=\"min-w-0 truncate text-base font-semibold tracking-tight text-fg\">{m.appsPage.title}</h1>\n </div>\n ),\n end: null,\n });\n return () => clearPageHeader();\n }, [clearPageHeader, m.appsPage.title, setPageHeader]);\n\n if (loading && mainTab !== 'marketplace') {\n return <AppsPageSkeleton />;\n }\n\n const showSearch = mainTab !== 'marketplace' && listForTab.length > 0;\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel\">\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <header className=\"mb-6\">\n <h1 className=\"text-xl font-semibold text-fg\">{m.appsPage.title}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{m.appsPage.subtitle}</p>\n </header>\n\n <div className=\"mb-5 flex flex-col gap-3 border-b border-edge-subtle pb-3 sm:flex-row sm:items-center sm:justify-between dark:border-edge-subtle\">\n <div\n className=\"flex flex-wrap gap-x-1 gap-y-1\"\n role=\"tablist\"\n aria-label={m.appsPage.appsNavAria}\n >\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'marketplace'}\n className={cn(\n 'relative max-w-full rounded-md px-3 py-2 text-left text-sm font-medium transition-colors sm:text-center',\n mainTab === 'marketplace' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'marketplace' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('marketplace')}\n >\n {m.appsPage.tabMarketplace}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'builtin'}\n className={cn(\n 'relative rounded-md px-3 py-2 text-sm font-medium transition-colors',\n mainTab === 'builtin' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'builtin' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('builtin')}\n >\n {m.appsPage.tabBuiltin}\n <span className=\"ml-1 tabular-nums text-fg-muted\">({bundledExtensions.length})</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'user'}\n className={cn(\n 'relative rounded-md px-3 py-2 text-sm font-medium transition-colors',\n mainTab === 'user' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'user' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('user')}\n >\n {m.appsPage.tabUser}\n <span className=\"ml-1 tabular-nums text-fg-muted\">({userExtensions.length})</span>\n </button>\n </div>\n {showSearch ? (\n <div className=\"relative w-full min-w-0 sm:max-w-xs\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted\"\n aria-hidden\n />\n <input\n type=\"search\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={m.appsPage.searchPlaceholder}\n className=\"w-full rounded-lg border border-edge bg-surface-base py-2 pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n autoComplete=\"off\"\n />\n </div>\n ) : null}\n </div>\n\n {mainTab === 'marketplace' ? (\n <ExtensionMarketplacePanel />\n ) : mainTab === 'builtin' && bundledExtensions.length === 0 ? (\n <EmptyAppsState message={m.appsPage.emptyBuiltin} />\n ) : mainTab === 'user' && userExtensions.length === 0 ? (\n <EmptyAppsState message={m.appsPage.emptyUser} />\n ) : filtered.length === 0 ? (\n <p className=\"rounded-xl border border-dashed border-edge-subtle bg-surface-hover/30 px-4 py-8 text-center text-sm text-fg-muted dark:bg-surface-hover/15\">\n {m.appsPage.noSearchResults}\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((ext) => (\n <ExtensionAppCard\n key={ext.id}\n extension={ext}\n copy={m.appsPage}\n showSourceBadge={mainTab === 'user'}\n onOpen={() => setDetail(ext)}\n />\n ))}\n </div>\n )}\n </div>\n\n {detail ? (\n <ExtensionDetailDialog key={detail.id} extension={detail} copy={m.appsPage} onClose={() => setDetail(null)} />\n ) : null}\n </div>\n );\n}\n\nfunction activationEligibleFor(ext: ExtensionApiRow): boolean {\n return ext.activationEligible ?? ext.active;\n}\n\nfunction providerLabel(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n if (ext.source === 'bundled') return copy.providerBundled;\n if (ext.source === 'global') return copy.providerGlobal;\n if (ext.source === 'workspace') return copy.providerWorkspace;\n return copy.providerOther;\n}\n\nfunction installSourceBadgeLabel(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n if (ext.source === 'global') return copy.badgeSourceGlobal;\n if (ext.source === 'workspace') return copy.badgeSourceWorkspace;\n return copy.badgeSourceOther;\n}\n\nfunction bundledRunCaption(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n const eligible = activationEligibleFor(ext);\n if (eligible && ext.active) return copy.runStateLive;\n if (eligible && !ext.active) return copy.runStatePendingOn;\n if (!eligible && ext.active) return copy.runStatePendingOff;\n return copy.runStateOff;\n}\n\nfunction ExtensionAppCard({\n extension: ext,\n copy,\n showSourceBadge,\n onOpen,\n}: {\n extension: ExtensionApiRow;\n copy: AppsPageCopy;\n /** When true, show a short global/workspace/other pill (user-installed tab). */\n showSourceBadge: boolean;\n onOpen: () => void;\n}) {\n const eligible = activationEligibleFor(ext);\n const uiTitle = ext.hasUi ? copy.cardTooltipHasUi : copy.cardTooltipNoUi;\n\n return (\n <button\n type=\"button\"\n onClick={onOpen}\n className={cn(\n 'group flex w-full flex-col rounded-xl border border-edge bg-surface-base p-4 text-left shadow-sm transition-colors',\n 'hover:border-edge-subtle hover:bg-surface-hover/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n 'dark:hover:bg-surface-hover/25',\n )}\n >\n <div className=\"flex gap-3\">\n <div\n className=\"flex size-12 shrink-0 items-center justify-center rounded-xl bg-accent-soft text-base font-semibold text-accent-fg\"\n aria-hidden\n >\n {(ext.name || ext.id).charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-fg\">{ext.name}</h2>\n {ext.version ? (\n <span className=\"text-[11px] text-fg-muted\">v{ext.version}</span>\n ) : null}\n </div>\n {eligible ? (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n <Check className=\"size-3\" strokeWidth={2.5} aria-hidden />\n {copy.statusEnabled}\n </span>\n ) : (\n <span\n className=\"flex size-8 shrink-0 items-center justify-center rounded-full border-2 border-accent text-accent\"\n aria-hidden\n >\n <Plus className=\"size-4\" strokeWidth={2.5} />\n </span>\n )}\n </div>\n <p className=\"mt-2 line-clamp-2 text-xs leading-relaxed text-fg-muted\">\n {ext.description?.trim() || copy.cardNoDescription}\n </p>\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n <span\n title={uiTitle}\n className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\"\n >\n {ext.hasUi ? copy.badgeKindUi : copy.badgeKindBackend}\n </span>\n {ext.source === 'bundled' ? (\n <span className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\">\n {copy.badgeBundled}\n </span>\n ) : showSourceBadge ? (\n <span\n title={providerLabel(ext, copy)}\n className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\"\n >\n {installSourceBadgeLabel(ext, copy)}\n </span>\n ) : null}\n </div>\n </div>\n </div>\n </button>\n );\n}\n\nfunction ExtensionDetailDialog({\n extension: ext,\n copy,\n onClose,\n}: {\n extension: ExtensionApiRow;\n copy: AppsPageCopy;\n onClose: () => void;\n}) {\n const pages = ext.ui?.contributions?.pages ?? [];\n const settingsPanels = ext.ui?.contributions?.settingsPanels ?? [];\n const chatWidgets = ext.ui?.contributions?.chatWidgets ?? [];\n const sidebarPanels = ext.ui?.contributions?.sidebarPanels ?? [];\n const primaryPage: PageContribution | undefined = pages.find((p) => p.showInNav) ?? pages[0];\n const primarySettingsPanel = settingsPanels[0];\n const openPath = primaryPage ? extensionPagePath(ext.id, primaryPage) : null;\n const settingsPath = primarySettingsPanel\n ? `/settings/ext/${ext.id}/${primarySettingsPanel.id}`\n : ext.hasConfigSchema\n ? `/settings/ext/${ext.id}`\n : null;\n\n return (\n <Dialog.Root defaultOpen onOpenChange={(o) => !o && onClose()}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim\" />\n <Dialog.Content\n className=\"fixed left-1/2 top-1/2 z-[131] flex max-h-[min(90vh,44rem)] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n aria-label={copy.detailBack}\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <Dialog.Title className=\"min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg\">\n {copy.detailTitle}\n </Dialog.Title>\n <Dialog.Description className=\"sr-only\">\n {ext.name} ({ext.id})\n </Dialog.Description>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n aria-label={copy.detailClose}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto px-5 py-5\">\n <div className=\"flex flex-wrap items-start gap-4\">\n <div\n className=\"flex size-16 shrink-0 items-center justify-center rounded-2xl bg-accent-soft text-xl font-semibold text-accent-fg\"\n aria-hidden\n >\n {(ext.name || ext.id).charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-lg font-semibold text-fg\">{ext.name}</h3>\n <p className=\"mt-0.5 text-sm text-fg-muted\">\n {copy.detailProviderPrefix} {providerLabel(ext, copy)}\n </p>\n {ext.version ? (\n <p className=\"mt-1 text-xs text-fg-muted\">v{ext.version}</p>\n ) : null}\n </div>\n </div>\n\n <p className=\"mt-5 text-sm leading-relaxed text-fg\">\n {ext.description?.trim() || copy.detailNoDescription}\n </p>\n\n {!ext.hasUi ? (\n <p className=\"mt-3 text-xs text-fg-muted\">{copy.backendOnlyHint}</p>\n ) : null}\n\n <p className=\"mt-2 text-xs text-fg-muted\">{bundledRunCaption(ext, copy)}</p>\n\n {ext.source === 'bundled' ? (\n <p className=\"mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20\">\n {copy.builtinConfigHint}\n </p>\n ) : (\n <p className=\"mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20\">\n {copy.cliManageHint}\n </p>\n )}\n\n {ext.hasUi && (pages.length > 0 || settingsPanels.length > 0 || chatWidgets.length > 0) ? (\n <section className=\"mt-8\">\n <h4 className=\"mb-3 text-sm font-semibold text-fg\">{copy.detailSectionFeatures}</h4>\n <div className=\"flex flex-wrap gap-1.5\">\n <ContributionBadge\n template={copy.badgePages}\n count={pages.length}\n hidden={pages.length === 0}\n />\n <ContributionBadge\n template={copy.badgeSettings}\n count={settingsPanels.length}\n hidden={settingsPanels.length === 0}\n />\n <ContributionBadge\n template={copy.badgeWidgets}\n count={chatWidgets.length}\n hidden={chatWidgets.length === 0}\n />\n <ContributionBadge\n template={copy.badgeSidebar}\n count={sidebarPanels.length}\n hidden={sidebarPanels.length === 0}\n />\n </div>\n </section>\n ) : null}\n\n {extensionExposesGatewayShellUi(ext) && (openPath || settingsPath) ? (\n <div className=\"mt-6 flex flex-wrap gap-2 border-t border-edge-subtle pt-4\">\n {openPath ? (\n <Link\n to={openPath}\n onClick={onClose}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n )}\n >\n <ExternalLink className=\"size-4 shrink-0 opacity-80\" aria-hidden />\n {copy.open}\n </Link>\n ) : null}\n {settingsPath ? (\n <Link\n to={settingsPath}\n onClick={onClose}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n )}\n >\n <Settings className=\"size-4 shrink-0 opacity-80\" aria-hidden />\n {copy.openSettings}\n </Link>\n ) : null}\n </div>\n ) : null}\n\n <p className=\"mt-6 text-[11px] leading-relaxed text-fg-muted\">{copy.restartNote}</p>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n\nfunction ContributionBadge({\n template,\n count,\n hidden,\n}: {\n template: string;\n count: number;\n hidden: boolean;\n}) {\n if (hidden || count === 0) return null;\n return (\n <span className=\"inline-flex items-center rounded-md bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n {template.replace(/\\{\\{count\\}\\}/g, String(count))}\n </span>\n );\n}\n\nfunction AppsPageSkeleton() {\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel\">\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <div className=\"mb-6 h-8 w-40 max-w-full animate-pulse rounded-md bg-surface-hover\" />\n <div className=\"mb-2 h-4 w-full max-w-md animate-pulse rounded bg-surface-hover\" />\n <div className=\"mb-5 h-9 w-full max-w-lg animate-pulse rounded-full bg-surface-hover\" />\n <div className=\"mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {[0, 1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-36 animate-pulse rounded-xl border border-edge bg-surface-base\" />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nfunction EmptyAppsState({ message }: { message: string }) {\n return (\n <div className=\"flex min-h-[min(40vh,16rem)] flex-col items-center justify-center rounded-xl border border-dashed border-edge-subtle bg-surface-hover/40 px-4 py-12 text-center dark:bg-surface-hover/20\">\n <p className=\"text-sm text-fg-muted\">{message}</p>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"apps-page-CW1VZ5L2.js","names":[],"sources":["../../../../../web/src/features/apps/apps-page.constants.ts","../../../../../web/src/features/extensions/extension-marketplace.tsx","../../../../../web/src/pages/apps-page.tsx"],"sourcesContent":["export type AppsMainTab = 'marketplace' | 'builtin' | 'user';\n\nexport function parseAppsMainTab(raw: string | null): AppsMainTab {\n if (raw === 'builtin' || raw === 'user') return raw;\n return 'marketplace';\n}\n","import { CheckCircle, ExternalLink, Package, Search } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport useSWR from 'swr';\n\nimport { useGatewayStore } from '@/stores/gateway-store';\nimport { fetchJson } from '@/lib/fetch';\nimport { apiUrl } from '@/lib/url';\nimport { cn } from '@/lib/cn';\n\ntype RegistryEntry = {\n id: string;\n name: string;\n description?: string;\n npmPackage: string;\n version?: string;\n categories?: string[];\n tags?: string[];\n verified?: boolean;\n homepage?: string;\n author?: string;\n};\n\ntype MarketplaceResponse = { ok: boolean; extensions: RegistryEntry[] };\n\nexport function ExtensionMarketplacePanel({ className }: { className?: string }) {\n const hasToken = useGatewayStore((s) => Boolean(s.token));\n const [q, setQ] = useState('');\n const [debounced, setDebounced] = useState('');\n const key = hasToken ? `marketplace-${debounced}` : null;\n\n useEffect(() => {\n const t = window.setTimeout(() => setDebounced(q.trim()), 300);\n return () => window.clearTimeout(t);\n }, [q]);\n\n const { data, isLoading, error } = useSWR(\n key,\n async () => {\n const url =\n debounced.length > 0\n ? apiUrl(`/api/marketplace?q=${encodeURIComponent(debounced)}`)\n : apiUrl('/api/marketplace');\n return fetchJson<MarketplaceResponse>(url);\n },\n { revalidateOnFocus: false },\n );\n\n const extensions = data?.extensions ?? [];\n\n return (\n <div className={cn('flex flex-col gap-4', className)}>\n <div className=\"relative\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted\"\n strokeWidth={1.75}\n aria-hidden\n />\n <input\n type=\"search\"\n value={q}\n onChange={(e) => setQ(e.target.value)}\n placeholder=\"Search extensions…\"\n className=\"ui-input h-10 w-full rounded-lg border border-edge bg-surface-base pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted\"\n />\n </div>\n\n {error ? (\n <p className=\"text-sm text-fg-muted\">\n {error instanceof Error ? error.message : 'Failed to load marketplace'}\n </p>\n ) : null}\n\n {isLoading && !data ? (\n <p className=\"text-sm text-fg-muted\">Loading…</p>\n ) : (\n <ul className=\"flex flex-col gap-3\">\n {extensions.length === 0 ? (\n <li className=\"text-sm text-fg-muted\">No extensions from xopc-store.</li>\n ) : (\n extensions.map((e) => (\n <li\n key={e.id}\n className=\"rounded-xl border border-edge bg-surface-base p-4 shadow-surface\"\n >\n <div className=\"flex flex-wrap items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"font-semibold text-fg\">{e.name}</h3>\n {e.verified ? (\n <CheckCircle\n className=\"size-4 shrink-0 text-emerald-600 dark:text-emerald-400\"\n strokeWidth={1.75}\n aria-label=\"Verified\"\n />\n ) : null}\n {e.version ? (\n <span className=\"text-xs text-fg-muted\">{e.version}</span>\n ) : null}\n </div>\n {e.description ? (\n <p className=\"mt-1 text-sm text-fg-muted\">{e.description}</p>\n ) : null}\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n {(e.categories ?? []).map((c) => (\n <span\n key={c}\n className=\"rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-[11px] text-fg-muted\"\n >\n {c}\n </span>\n ))}\n </div>\n <p className=\"mt-2 flex items-center gap-1.5 text-xs text-fg-muted\">\n <Package className=\"size-3.5 shrink-0\" strokeWidth={1.75} aria-hidden />\n <code className=\"rounded bg-surface-panel px-1 py-0.5\">{e.npmPackage}</code>\n </p>\n {e.homepage ? (\n <a\n href={e.homepage}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"mt-2 inline-flex items-center gap-1 text-xs text-accent hover:underline\"\n >\n <ExternalLink className=\"size-3.5\" strokeWidth={1.75} aria-hidden />\n Homepage\n </a>\n ) : null}\n </div>\n </div>\n <p className=\"mt-3 text-[11px] text-fg-muted\">\n npm package:{' '}\n <code className=\"rounded bg-surface-panel px-1 py-0.5\">{e.npmPackage}</code>\n </p>\n </li>\n ))\n )}\n </ul>\n )}\n </div>\n );\n}\n","import * as Dialog from '@radix-ui/react-dialog';\nimport { ArrowLeft, Check, ExternalLink, Plus, Search, Settings, X } from 'lucide-react';\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { Link, useSearchParams } from 'react-router-dom';\n\nimport { parseAppsMainTab, type AppsMainTab } from '@/features/apps/apps-page.constants';\nimport {\n extensionExposesGatewayShellUi,\n useExtensions,\n useExtensionsLoading,\n} from '@/features/extensions/extension-provider';\nimport { ExtensionMarketplacePanel } from '@/features/extensions/extension-marketplace';\nimport { extensionPagePath } from '@/features/extensions/extension-paths';\nimport type { ExtensionApiRow, PageContribution } from '@/features/extensions/types';\nimport { messages } from '@/i18n/messages';\nimport type { MessageBundle } from '@/i18n/messages';\nimport { cn } from '@/lib/cn';\nimport { usePageHeaderStore } from '@/stores/page-header-store';\nimport { useLocaleStore } from '@/stores/locale-store';\n\ntype AppsPageCopy = MessageBundle['appsPage'];\n\nexport function AppsPage() {\n const language = useLocaleStore((s) => s.language);\n const m = messages(language);\n const setPageHeader = usePageHeaderStore((s) => s.setPageHeader);\n const clearPageHeader = usePageHeaderStore((s) => s.clearPageHeader);\n const extensions = useExtensions();\n const loading = useExtensionsLoading();\n const [searchParams, setSearchParams] = useSearchParams();\n\n const initialTab = parseAppsMainTab(searchParams.get('tab'));\n const initialQ = searchParams.get('q') ?? '';\n const [mainTab, setMainTab] = useState<AppsMainTab>(initialTab);\n const [search, setSearch] = useState(initialQ);\n const [detail, setDetail] = useState<ExtensionApiRow | null>(null);\n\n useEffect(() => {\n const nextTab = parseAppsMainTab(searchParams.get('tab'));\n const nextQ = searchParams.get('q') ?? '';\n setMainTab((prev) => (prev === nextTab ? prev : nextTab));\n setSearch((prev) => (prev === nextQ ? prev : nextQ));\n }, [searchParams]);\n\n useEffect(() => {\n setSearchParams(\n (prev) => {\n const params = new URLSearchParams(prev);\n const qq = search.trim();\n if (qq) params.set('q', qq);\n else params.delete('q');\n if (mainTab !== 'marketplace') params.set('tab', mainTab);\n else params.delete('tab');\n if (params.toString() === prev.toString()) return prev;\n return params;\n },\n { replace: true },\n );\n }, [mainTab, search, setSearchParams]);\n\n const bundledExtensions = useMemo(\n () => extensions.filter((e) => e.source === 'bundled'),\n [extensions],\n );\n const userExtensions = useMemo(\n () => extensions.filter((e) => e.source !== 'bundled'),\n [extensions],\n );\n\n const listForTab = mainTab === 'builtin' ? bundledExtensions : userExtensions;\n\n const filtered = useMemo(() => {\n const q = search.trim().toLowerCase();\n let list = listForTab;\n if (q) {\n list = list.filter(\n (e) =>\n (e.name ?? '').toLowerCase().includes(q) ||\n e.id.toLowerCase().includes(q) ||\n (e.description ?? '').toLowerCase().includes(q),\n );\n }\n return [...list].sort((a, b) => {\n if (a.hasUi !== b.hasUi) return a.hasUi ? -1 : 1;\n return (a.name || a.id).localeCompare(b.name || b.id, language);\n });\n }, [listForTab, search, language]);\n\n /** Keep dialog + cards in sync after SWR refetch (detail was a stale row reference). */\n useEffect(() => {\n setDetail((prev) => {\n if (!prev) return prev;\n const next = extensions.find((e) => e.id === prev.id);\n if (!next) return null;\n const eligPrev = activationEligibleFor(prev);\n const eligNext = activationEligibleFor(next);\n if (eligPrev === eligNext && prev.active === next.active) return prev;\n return next;\n });\n }, [extensions]);\n\n useLayoutEffect(() => {\n setPageHeader({\n startExtra: null,\n main: (\n <div className=\"w-full min-w-0 px-3 sm:px-5 xl:px-6\">\n <h1 className=\"min-w-0 truncate text-base font-semibold tracking-tight text-fg\">{m.appsPage.title}</h1>\n </div>\n ),\n end: null,\n });\n return () => clearPageHeader();\n }, [clearPageHeader, m.appsPage.title, setPageHeader]);\n\n if (loading && mainTab !== 'marketplace') {\n return <AppsPageSkeleton />;\n }\n\n const showSearch = mainTab !== 'marketplace' && listForTab.length > 0;\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel\">\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <header className=\"mb-6\">\n <h1 className=\"text-xl font-semibold text-fg\">{m.appsPage.title}</h1>\n <p className=\"mt-1 text-sm text-fg-muted\">{m.appsPage.subtitle}</p>\n </header>\n\n <div className=\"mb-5 flex flex-col gap-3 border-b border-edge-subtle pb-3 sm:flex-row sm:items-center sm:justify-between dark:border-edge-subtle\">\n <div\n className=\"flex flex-wrap gap-x-1 gap-y-1\"\n role=\"tablist\"\n aria-label={m.appsPage.appsNavAria}\n >\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'marketplace'}\n className={cn(\n 'relative max-w-full rounded-md px-3 py-2 text-left text-sm font-medium transition-colors sm:text-center',\n mainTab === 'marketplace' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'marketplace' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('marketplace')}\n >\n {m.appsPage.tabMarketplace}\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'builtin'}\n className={cn(\n 'relative rounded-md px-3 py-2 text-sm font-medium transition-colors',\n mainTab === 'builtin' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'builtin' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('builtin')}\n >\n {m.appsPage.tabBuiltin}\n <span className=\"ml-1 tabular-nums text-fg-muted\">({bundledExtensions.length})</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={mainTab === 'user'}\n className={cn(\n 'relative rounded-md px-3 py-2 text-sm font-medium transition-colors',\n mainTab === 'user' ? 'text-fg' : 'text-fg-muted hover:text-fg',\n mainTab === 'user' &&\n 'after:absolute after:bottom-0 after:left-1/2 after:h-0.5 after:w-9 after:-translate-x-1/2 after:rounded-full after:bg-accent',\n )}\n onClick={() => setMainTab('user')}\n >\n {m.appsPage.tabUser}\n <span className=\"ml-1 tabular-nums text-fg-muted\">({userExtensions.length})</span>\n </button>\n </div>\n {showSearch ? (\n <div className=\"relative w-full min-w-0 sm:max-w-xs\">\n <Search\n className=\"pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted\"\n aria-hidden\n />\n <input\n type=\"search\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={m.appsPage.searchPlaceholder}\n className=\"w-full rounded-lg border border-edge bg-surface-base py-2 pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n autoComplete=\"off\"\n />\n </div>\n ) : null}\n </div>\n\n {mainTab === 'marketplace' ? (\n <ExtensionMarketplacePanel />\n ) : mainTab === 'builtin' && bundledExtensions.length === 0 ? (\n <EmptyAppsState message={m.appsPage.emptyBuiltin} />\n ) : mainTab === 'user' && userExtensions.length === 0 ? (\n <EmptyAppsState message={m.appsPage.emptyUser} />\n ) : filtered.length === 0 ? (\n <p className=\"rounded-xl border border-dashed border-edge-subtle bg-surface-hover/30 px-4 py-8 text-center text-sm text-fg-muted dark:bg-surface-hover/15\">\n {m.appsPage.noSearchResults}\n </p>\n ) : (\n <div className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((ext) => (\n <ExtensionAppCard\n key={ext.id}\n extension={ext}\n copy={m.appsPage}\n showSourceBadge={mainTab === 'user'}\n onOpen={() => setDetail(ext)}\n />\n ))}\n </div>\n )}\n </div>\n\n {detail ? (\n <ExtensionDetailDialog key={detail.id} extension={detail} copy={m.appsPage} onClose={() => setDetail(null)} />\n ) : null}\n </div>\n );\n}\n\nfunction activationEligibleFor(ext: ExtensionApiRow): boolean {\n return ext.activationEligible ?? ext.active;\n}\n\nfunction providerLabel(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n if (ext.source === 'bundled') return copy.providerBundled;\n if (ext.source === 'global') return copy.providerGlobal;\n if (ext.source === 'workspace') return copy.providerWorkspace;\n return copy.providerOther;\n}\n\nfunction installSourceBadgeLabel(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n if (ext.source === 'global') return copy.badgeSourceGlobal;\n if (ext.source === 'workspace') return copy.badgeSourceWorkspace;\n return copy.badgeSourceOther;\n}\n\nfunction bundledRunCaption(ext: ExtensionApiRow, copy: AppsPageCopy): string {\n const eligible = activationEligibleFor(ext);\n if (eligible && ext.active) return copy.runStateLive;\n if (eligible && !ext.active) return copy.runStatePendingOn;\n if (!eligible && ext.active) return copy.runStatePendingOff;\n return copy.runStateOff;\n}\n\nfunction ExtensionAppCard({\n extension: ext,\n copy,\n showSourceBadge,\n onOpen,\n}: {\n extension: ExtensionApiRow;\n copy: AppsPageCopy;\n /** When true, show a short global/workspace/other pill (user-installed tab). */\n showSourceBadge: boolean;\n onOpen: () => void;\n}) {\n const eligible = activationEligibleFor(ext);\n const uiTitle = ext.hasUi ? copy.cardTooltipHasUi : copy.cardTooltipNoUi;\n\n return (\n <button\n type=\"button\"\n onClick={onOpen}\n className={cn(\n 'group flex w-full flex-col rounded-xl border border-edge bg-surface-base p-4 text-left shadow-sm transition-colors',\n 'hover:border-edge-subtle hover:bg-surface-hover/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n 'dark:hover:bg-surface-hover/25',\n )}\n >\n <div className=\"flex gap-3\">\n <div\n className=\"flex size-12 shrink-0 items-center justify-center rounded-xl bg-accent-soft text-base font-semibold text-accent-fg\"\n aria-hidden\n >\n {(ext.name || ext.id).charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h2 className=\"truncate text-sm font-semibold text-fg\">{ext.name}</h2>\n {ext.version ? (\n <span className=\"text-[11px] text-fg-muted\">v{ext.version}</span>\n ) : null}\n </div>\n {eligible ? (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n <Check className=\"size-3\" strokeWidth={2.5} aria-hidden />\n {copy.statusEnabled}\n </span>\n ) : (\n <span\n className=\"flex size-8 shrink-0 items-center justify-center rounded-full border-2 border-accent text-accent\"\n aria-hidden\n >\n <Plus className=\"size-4\" strokeWidth={2.5} />\n </span>\n )}\n </div>\n <p className=\"mt-2 line-clamp-2 text-xs leading-relaxed text-fg-muted\">\n {ext.description?.trim() || copy.cardNoDescription}\n </p>\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n <span\n title={uiTitle}\n className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\"\n >\n {ext.hasUi ? copy.badgeKindUi : copy.badgeKindBackend}\n </span>\n {ext.source === 'bundled' ? (\n <span className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\">\n {copy.badgeBundled}\n </span>\n ) : showSourceBadge ? (\n <span\n title={providerLabel(ext, copy)}\n className=\"rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted\"\n >\n {installSourceBadgeLabel(ext, copy)}\n </span>\n ) : null}\n </div>\n </div>\n </div>\n </button>\n );\n}\n\nfunction ExtensionDetailDialog({\n extension: ext,\n copy,\n onClose,\n}: {\n extension: ExtensionApiRow;\n copy: AppsPageCopy;\n onClose: () => void;\n}) {\n const pages = ext.ui?.contributions?.pages ?? [];\n const settingsPanels = ext.ui?.contributions?.settingsPanels ?? [];\n const chatWidgets = ext.ui?.contributions?.chatWidgets ?? [];\n const sidebarPanels = ext.ui?.contributions?.sidebarPanels ?? [];\n const primaryPage: PageContribution | undefined = pages.find((p) => p.showInNav) ?? pages[0];\n const primarySettingsPanel = settingsPanels[0];\n const openPath = primaryPage ? extensionPagePath(ext.id, primaryPage) : null;\n const settingsPath = primarySettingsPanel\n ? `/settings/ext/${ext.id}/${primarySettingsPanel.id}`\n : ext.hasConfigSchema\n ? `/settings/ext/${ext.id}`\n : null;\n\n return (\n <Dialog.Root defaultOpen onOpenChange={(o) => !o && onClose()}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim\" />\n <Dialog.Content\n className=\"fixed left-1/2 top-1/2 z-[131] flex max-h-[min(90vh,44rem)] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n aria-label={copy.detailBack}\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <Dialog.Title className=\"min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg\">\n {copy.detailTitle}\n </Dialog.Title>\n <Dialog.Description className=\"sr-only\">\n {ext.name} ({ext.id})\n </Dialog.Description>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent\"\n aria-label={copy.detailClose}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto px-5 py-5\">\n <div className=\"flex flex-wrap items-start gap-4\">\n <div\n className=\"flex size-16 shrink-0 items-center justify-center rounded-2xl bg-accent-soft text-xl font-semibold text-accent-fg\"\n aria-hidden\n >\n {(ext.name || ext.id).charAt(0).toUpperCase()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"text-lg font-semibold text-fg\">{ext.name}</h3>\n <p className=\"mt-0.5 text-sm text-fg-muted\">\n {copy.detailProviderPrefix} {providerLabel(ext, copy)}\n </p>\n {ext.version ? (\n <p className=\"mt-1 text-xs text-fg-muted\">v{ext.version}</p>\n ) : null}\n </div>\n </div>\n\n <p className=\"mt-5 text-sm leading-relaxed text-fg\">\n {ext.description?.trim() || copy.detailNoDescription}\n </p>\n\n {!ext.hasUi ? (\n <p className=\"mt-3 text-xs text-fg-muted\">{copy.backendOnlyHint}</p>\n ) : null}\n\n <p className=\"mt-2 text-xs text-fg-muted\">{bundledRunCaption(ext, copy)}</p>\n\n {ext.source === 'bundled' ? (\n <p className=\"mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20\">\n {copy.builtinConfigHint}\n </p>\n ) : (\n <p className=\"mt-4 rounded-lg border border-edge-subtle bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted dark:bg-surface-hover/20\">\n {copy.cliManageHint}\n </p>\n )}\n\n {ext.hasUi && (pages.length > 0 || settingsPanels.length > 0 || chatWidgets.length > 0) ? (\n <section className=\"mt-8\">\n <h4 className=\"mb-3 text-sm font-semibold text-fg\">{copy.detailSectionFeatures}</h4>\n <div className=\"flex flex-wrap gap-1.5\">\n <ContributionBadge\n template={copy.badgePages}\n count={pages.length}\n hidden={pages.length === 0}\n />\n <ContributionBadge\n template={copy.badgeSettings}\n count={settingsPanels.length}\n hidden={settingsPanels.length === 0}\n />\n <ContributionBadge\n template={copy.badgeWidgets}\n count={chatWidgets.length}\n hidden={chatWidgets.length === 0}\n />\n <ContributionBadge\n template={copy.badgeSidebar}\n count={sidebarPanels.length}\n hidden={sidebarPanels.length === 0}\n />\n </div>\n </section>\n ) : null}\n\n {extensionExposesGatewayShellUi(ext) && (openPath || settingsPath) ? (\n <div className=\"mt-6 flex flex-wrap gap-2 border-t border-edge-subtle pt-4\">\n {openPath ? (\n <Link\n to={openPath}\n onClick={onClose}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n )}\n >\n <ExternalLink className=\"size-4 shrink-0 opacity-80\" aria-hidden />\n {copy.open}\n </Link>\n ) : null}\n {settingsPath ? (\n <Link\n to={settingsPath}\n onClick={onClose}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg',\n 'hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent',\n )}\n >\n <Settings className=\"size-4 shrink-0 opacity-80\" aria-hidden />\n {copy.openSettings}\n </Link>\n ) : null}\n </div>\n ) : null}\n\n <p className=\"mt-6 text-[11px] leading-relaxed text-fg-muted\">{copy.restartNote}</p>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n );\n}\n\nfunction ContributionBadge({\n template,\n count,\n hidden,\n}: {\n template: string;\n count: number;\n hidden: boolean;\n}) {\n if (hidden || count === 0) return null;\n return (\n <span className=\"inline-flex items-center rounded-md bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted\">\n {template.replace(/\\{\\{count\\}\\}/g, String(count))}\n </span>\n );\n}\n\nfunction AppsPageSkeleton() {\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-surface-panel\">\n <div className=\"mx-auto w-full max-w-app-main px-4 py-8\">\n <div className=\"mb-6 h-8 w-40 max-w-full animate-pulse rounded-md bg-surface-hover\" />\n <div className=\"mb-2 h-4 w-full max-w-md animate-pulse rounded bg-surface-hover\" />\n <div className=\"mb-5 h-9 w-full max-w-lg animate-pulse rounded-full bg-surface-hover\" />\n <div className=\"mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {[0, 1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-36 animate-pulse rounded-xl border border-edge bg-surface-base\" />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nfunction EmptyAppsState({ message }: { message: string }) {\n return (\n <div className=\"flex min-h-[min(40vh,16rem)] flex-col items-center justify-center rounded-xl border border-dashed border-edge-subtle bg-surface-hover/40 px-4 py-12 text-center dark:bg-surface-hover/20\">\n <p className=\"text-sm text-fg-muted\">{message}</p>\n </div>\n );\n}\n"],"mappings":"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"}