@runfusion/fusion 0.2.7 → 0.4.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.
- package/dist/bin.js +55392 -51635
- package/dist/client/assets/{AgentDetailView-BMrHuWGs.css → AgentDetailView-C1b9PC5l.css} +1 -1
- package/dist/client/assets/{AgentDetailView-B4lRk--v.js → AgentDetailView-DJwWfkpv.js} +1 -1
- package/dist/client/assets/{AgentsView-yCYBY2km.js → AgentsView-DegK8aw-.js} +5 -5
- package/dist/client/assets/ChatView-CYpEShLS.js +1 -0
- package/dist/client/assets/{DevServerView-jXXtoQUx.js → DevServerView-DfCTA9fx.js} +2 -2
- package/dist/client/assets/{DirectoryPicker-izgMlS27.js → DirectoryPicker-B0qNpfLW.js} +1 -1
- package/dist/client/assets/DirectoryPicker-DzKVmxOf.css +1 -0
- package/dist/client/assets/{DocumentsView-DkkoHRwL.js → DocumentsView-CsQxuyz3.js} +1 -1
- package/dist/client/assets/{InsightsView-DaRtUPHX.js → InsightsView-Bzs7A2jv.js} +2 -2
- package/dist/client/assets/MemoryView-Cl5ASqjW.js +2 -0
- package/dist/client/assets/MemoryView-DiajLXby.css +1 -0
- package/dist/client/assets/{NodesView-BsUk_oiU.js → NodesView-BpiqRlvc.js} +1 -1
- package/dist/client/assets/PiExtensionsManager-Cr6EoC7S.js +11 -0
- package/dist/client/assets/PiExtensionsManager-kgTOHPE9.css +1 -0
- package/dist/client/assets/PluginManager-DRiIqol2.css +1 -0
- package/dist/client/assets/PluginManager-DXtQdfns.js +1 -0
- package/dist/client/assets/{RoadmapsView-SQol126Y.js → RoadmapsView-CYPLTTB0.js} +2 -2
- package/dist/client/assets/SettingsModal-CDWvhvrd.css +1 -0
- package/dist/client/assets/SettingsModal-CNdVTVqD.js +1 -0
- package/dist/client/assets/SettingsModal-CyCC7MzL.js +31 -0
- package/dist/client/assets/SettingsModal-G0ESQXRD.css +1 -0
- package/dist/client/assets/{SetupWizardModal-CQc1uGSq.js → SetupWizardModal-BLiljNn7.js} +1 -1
- package/dist/client/assets/SetupWizardModal-BMa6p24b.css +1 -0
- package/dist/client/assets/SkillsView-Dlpw5LKI.js +1 -0
- package/dist/client/assets/{folder-open-CI4TCD7P.js → folder-open-B_38R5AA.js} +1 -1
- package/dist/client/assets/index-DQKtk17v.js +616 -0
- package/dist/client/assets/index-DjOxzdj3.css +1 -0
- package/dist/client/assets/{upload-CAlKC4qI.js → upload-DNQF7XCK.js} +1 -1
- package/dist/client/assets/users-CG2_rCdk.js +6 -0
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -0
- package/dist/extension.js +3222 -937
- package/dist/pi-claude-cli/index.ts +72 -28
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/event-bridge.test.ts +34 -0
- package/dist/pi-claude-cli/src/__tests__/mcp-config.test.ts +22 -0
- package/dist/pi-claude-cli/src/__tests__/prompt-builder.test.ts +72 -10
- package/dist/pi-claude-cli/src/__tests__/provider.test.ts +9 -9
- package/dist/pi-claude-cli/src/event-bridge.ts +17 -6
- package/dist/pi-claude-cli/src/mcp-config.ts +36 -3
- package/dist/pi-claude-cli/src/prompt-builder.ts +111 -7
- package/dist/pi-claude-cli/src/provider.ts +17 -2
- package/package.json +17 -16
- package/skill/fusion/SKILL.md +6 -1
- package/skill/fusion/references/engine-tools.md +54 -0
- package/skill/fusion/references/extension-tools.md +83 -84
- package/skill/fusion/references/fusion-capabilities.md +33 -31
- package/LICENSE +0 -21
- package/dist/client/assets/ChatView-CH9T0dDs.js +0 -1
- package/dist/client/assets/MemoryView-85NKuU3h.js +0 -2
- package/dist/client/assets/MemoryView-DhinauGs.css +0 -1
- package/dist/client/assets/PiExtensionsManager-BF5pxrSE.js +0 -11
- package/dist/client/assets/PiExtensionsManager-K7HQ08L4.css +0 -1
- package/dist/client/assets/PluginManager-ccq3uK50.css +0 -1
- package/dist/client/assets/PluginManager-s6btydh5.js +0 -1
- package/dist/client/assets/SkillsView-BtUhs_QW.js +0 -1
- package/dist/client/assets/index-Ct-OqLpP.css +0 -1
- package/dist/client/assets/index-rNf7s96d.js +0 -649
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{r as l,j as e}from"./vendor-react-K0fH_qHe.js";import{c as A,cZ as Z,c_ as H,c$ as V,R as $,cQ as y,w as Y,K as T,D as ee,I as se,bJ as L,F as D,d0 as ae,d1 as te,d2 as _,X as ie}from"./index-DQKtk17v.js";import"./vendor-xterm-DzcZoU0P.js";/**
|
|
2
|
+
* @license lucide-react v1.7.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const ne=[["path",{d:"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z",key:"e79jfc"}],["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor",key:"1okk4w"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor",key:"f64h9f"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor",key:"qy21gx"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor",key:"fotxhn"}]],I=A("palette",ne);/**
|
|
7
|
+
* @license lucide-react v1.7.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const le=[["path",{d:"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z",key:"w46dr5"}]],M=A("puzzle",le);function ce(t){return t.replace(/-/g,"-")}function re(t){return{"fusion-global":"Fusion Global","pi-global":"Pi Global","fusion-project":"Fusion Project","pi-project":"Pi Project",package:"Package"}[t]??t}function oe(t){return t.startsWith("npm:")?"npm":t.startsWith("git:")?"git":"local"}function de(t){return t.replace(/^(npm:|git:)/,"")}function he({addToast:t,projectId:x}){const[c,G]=l.useState(null),[f,P]=l.useState(!0),[N,S]=l.useState(!1),[E,w]=l.useState(!1),[h,F]=l.useState(""),[K,O]=l.useState(new Set),[p,W]=l.useState([]),[b,z]=l.useState(!0),[q,C]=l.useState(!1),r=l.useCallback(async()=>{try{P(!0);const s=await Z();G(s)}catch(s){t(`Failed to load Pi settings: ${s instanceof Error?s.message:String(s)}`,"error")}finally{P(!1)}},[t]),m=l.useCallback(async()=>{try{z(!0);const s=await H(x);W(s.extensions)}catch(s){t(`Failed to load extensions: ${s instanceof Error?s.message:String(s)}`,"error")}finally{z(!1)}},[t,x]),B=l.useCallback(async s=>{try{C(!0);const i=s.enabled?[...p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id),s.id]:p.filter(a=>a.enabled&&a.id!==s.id).map(a=>a.id);await V(i,x),await m(),t(s.enabled?"Extension disabled":"Extension enabled","success")}catch(i){t(`Failed to update extension: ${i instanceof Error?i.message:String(i)}`,"error")}finally{C(!1)}},[p,x,m,t]);l.useEffect(()=>{r()},[r]),l.useEffect(()=>{m()},[m]);const J=s=>{O(i=>{const a=new Set(i);return a.has(s)?a.delete(s):a.add(s),a})},R=async()=>{if(!h.trim()){t("Please enter a package source","error");return}try{S(!0),await ae(h.trim()),t("Package installed successfully","success"),F(""),await r()}catch(s){t(`Failed to install package: ${s instanceof Error?s.message:String(s)}`,"error")}finally{S(!1)}},Q=async()=>{try{w(!0),await te(x),await Promise.all([r(),m()]),t("Fusion skill reinstalled successfully","success")}catch(s){t(`Failed to reinstall Fusion skill: ${s instanceof Error?s.message:String(s)}`,"error")}finally{w(!1)}},U=async s=>{if(!c)return;const i=c.packages.filter(a=>(typeof a=="string"?a:a.source)!==s);try{await _({packages:i}),t("Package removed","success"),await r()}catch(a){t(`Failed to remove package: ${a instanceof Error?a.message:String(a)}`,"error")}},X=async(s,i)=>{if(!c)return;const a=c[s].filter(n=>n!==i);try{await _({[s]:a}),t(`${s.slice(0,-1)} removed`,"success"),await r()}catch(n){t(`Failed to update settings: ${n instanceof Error?n.message:String(n)}`,"error")}},u=(s,i,a)=>!c||c[a].length===0?null:e.jsxs("div",{className:"pi-ext-section",children:[e.jsxs("div",{className:"pi-ext-section-header",children:[e.jsx(i,{size:14}),e.jsx("span",{children:s}),e.jsx("span",{className:"pi-ext-count",children:c[a].length})]}),e.jsx("div",{className:"pi-ext-resource-list",children:c[a].map((n,g)=>e.jsxs("span",{className:"pi-ext-resource-tag",children:[e.jsx("span",{className:"pi-ext-resource-path",children:n}),e.jsx("button",{className:"btn-icon touch-target pi-ext-resource-remove",onClick:()=>X(a,n),title:`Remove ${n}`,"aria-label":`Remove ${n}`,children:e.jsx(ie,{size:12})})]},g))})]});return e.jsxs("div",{className:"pi-ext-manager",children:[e.jsxs("div",{className:"pi-ext-manager-header",children:[e.jsx("h4",{className:"pi-ext-manager-title",children:"Pi Extensions"}),e.jsx("div",{className:"pi-ext-manager-actions",children:e.jsx("button",{className:"btn-icon",onClick:r,title:"Refresh",disabled:f,children:e.jsx($,{size:16,className:f?"spin":""})})})]}),f?e.jsx("div",{className:"loading-state",children:"Loading Pi settings…"}):c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"pi-ext-add-form",children:[e.jsxs("div",{className:"pi-ext-add-form-row",children:[e.jsx("input",{type:"text",className:"input",placeholder:"npm:pi-extension-name or git:https://github.com/...",value:h,onChange:s=>F(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),R())},disabled:N}),e.jsxs("button",{className:"btn btn-primary",onClick:R,disabled:N||!h.trim(),children:[e.jsx(Y,{size:14}),N?"Installing…":"Add"]})]}),e.jsx("div",{className:"pi-ext-add-form-row",children:e.jsx("button",{className:"btn",onClick:Q,disabled:E,children:E?"Reinstalling Fusion…":"Reinstall Fusion skill"})})]}),c.packages.length>0?e.jsx("div",{className:"pi-ext-package-list",children:c.packages.map((s,i)=>{const a=typeof s=="string"?s:s.source,n=oe(a),g=de(a),j=typeof s=="object"&&s!==null,v=j&&(s.extensions?.length??0)>0||(s.skills?.length??0)>0||(s.prompts?.length??0)>0||(s.themes?.length??0)>0,k=K.has(i);return e.jsxs("div",{className:"pi-ext-package-card",children:[e.jsxs("div",{className:"pi-ext-package-header",children:[j&&v?e.jsx("button",{className:"pi-ext-expand-btn",onClick:()=>J(i),"aria-expanded":k,children:k?e.jsx(T,{size:14}):e.jsx(ee,{size:14})}):e.jsx("span",{className:"pi-ext-expand-placeholder"}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${n}`,children:n}),e.jsx("span",{className:"pi-ext-package-source",children:g}),e.jsxs("div",{className:"pi-ext-package-actions",children:[j&&v&&e.jsxs("span",{className:"pi-ext-filter-hint",children:[s.extensions?.length??0," ext,"," ",s.skills?.length??0," skill,"," ",s.prompts?.length??0," prompt,"," ",s.themes?.length??0," theme"]}),e.jsx("button",{className:"btn-icon touch-target pi-ext-remove-btn",onClick:()=>U(a),title:"Remove package","aria-label":`Remove package ${g}`,children:e.jsx(se,{size:14})})]})]}),j&&v&&k&&e.jsxs("div",{className:"pi-ext-filter-list",children:[s.extensions?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(M,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Extensions:"}),s.extensions.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.skills?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(L,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Skills:"}),s.skills.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.prompts?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(D,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Prompts:"}),s.prompts.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null,s.themes?.length?e.jsxs("div",{className:"pi-ext-filter-section",children:[e.jsx(I,{size:12}),e.jsx("span",{className:"pi-ext-filter-label",children:"Themes:"}),s.themes.map((o,d)=>e.jsx("span",{className:"pi-ext-filter-tag",children:o},d))]}):null]})]},i)})}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No packages configured."}),e.jsx("p",{className:"text-muted",children:"Add a package source above to get started."})]}),e.jsxs("div",{className:"pi-ext-top-level",children:[u("Extensions",M,"extensions"),u("Skills",L,"skills"),u("Prompts",D,"prompts"),u("Themes",I,"themes")]})]}):e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"Failed to load Pi settings."})]}),e.jsxs("div",{className:"pi-ext-discovered-section",children:[e.jsxs("div",{className:"pi-ext-discovered-header",children:[e.jsx("h4",{children:"Discovered Extensions"}),e.jsx("button",{className:"btn-icon",onClick:m,disabled:b,title:"Refresh extensions",children:e.jsx($,{size:14,className:b?"spin":""})})]}),e.jsx("p",{className:"pi-ext-description",children:"Installed extensions resolved from packages and configured paths."}),b?e.jsx("div",{className:"loading-state",children:"Loading extensions…"}):p.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx(y,{size:32,className:"text-muted"}),e.jsx("p",{children:"No extensions discovered."})]}):e.jsx("div",{className:"pi-ext-list",children:p.map(s=>e.jsxs("div",{className:"pi-ext-item",children:[e.jsxs("div",{className:"pi-ext-item-content",children:[e.jsxs("div",{className:"pi-ext-info",children:[e.jsx("span",{className:"pi-ext-name",children:s.name}),e.jsx("span",{className:`pi-ext-source-badge pi-ext-source-badge--${ce(s.source)}`,children:re(s.source)})]}),e.jsx("span",{className:"pi-ext-path",children:s.path})]}),e.jsx("div",{className:"pi-ext-actions",children:e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>void B(s),disabled:q,"aria-label":`Toggle ${s.name}`}),e.jsx("span",{className:"toggle-slider"})]})})]},s.id))})]})]})}export{he as PiExtensionsManager};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.pi-ext-manager{display:flex;flex-direction:column;gap:var(--space-lg)}.pi-ext-manager-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--space-sm);border-bottom:1px solid var(--border)}.pi-ext-manager-title{margin:0;font-size:.9rem;font-weight:600;color:var(--text)}.pi-ext-manager-actions{display:flex;gap:var(--space-sm);align-items:center}.pi-ext-description{font-size:.82rem;color:var(--text-muted);line-height:1.45;margin:0}.pi-ext-item{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--space-sm) var(--space-md);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);transition:border-color var(--transition-fast);flex-wrap:wrap;gap:var(--space-sm)}.pi-ext-item:hover{border-color:var(--text-dim)}.pi-ext-item-content{display:flex;flex-direction:column;gap:var(--space-xs);min-width:0;flex:1}.pi-ext-info{display:flex;align-items:center;gap:var(--space-sm);flex-wrap:wrap}.pi-ext-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pi-ext-source-badge{display:inline-flex;align-items:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;background:color-mix(in srgb,currentColor 12%,transparent)}.pi-ext-source-badge--global{color:var(--color-info)}.pi-ext-source-badge--project{color:var(--color-success)}.pi-ext-path{font-size:.75rem;font-family:var(--font-mono);color:var(--text-dim);word-break:break-all;line-height:1.4}.pi-ext-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.pi-ext-manager .empty-state,.pi-ext-manager .loading-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-2xl);text-align:center;color:var(--text-muted)}.pi-ext-list{display:flex;flex-direction:column;gap:var(--space-sm)}.pi-ext-item{display:flex;align-items:center;gap:var(--space-sm);padding:var(--space-md);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md)}.pi-ext-add-form{display:flex;flex-direction:column;gap:var(--space-sm);margin-bottom:var(--space-md)}.pi-ext-add-form-row{display:flex;gap:var(--space-sm);align-items:center}.pi-ext-add-form-row .input{flex:1;min-width:0}.pi-ext-package-list{display:flex;flex-direction:column;gap:var(--space-sm)}.pi-ext-package-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden}.pi-ext-package-header{display:flex;align-items:center;gap:var(--space-sm);padding:calc(var(--space-sm) + 2px) var(--space-md);flex-wrap:wrap}.pi-ext-expand-btn{background:none;border:none;padding:var(--space-xs);cursor:pointer;color:var(--text-muted);display:flex;align-items:center;border-radius:var(--radius-sm);transition:color var(--transition-fast)}.pi-ext-expand-btn:hover{color:var(--text)}.pi-ext-expand-btn:focus-visible{box-shadow:var(--focus-ring-strong);outline:none}.pi-ext-expand-placeholder{width:18px;height:18px;flex-shrink:0}.pi-ext-source-badge--npm{color:var(--color-info);background:color-mix(in srgb,var(--color-info) 12%,transparent)}.pi-ext-source-badge--git{color:var(--color-success);background:color-mix(in srgb,var(--color-success) 12%,transparent)}.pi-ext-source-badge--local{color:var(--text-muted);background:color-mix(in srgb,var(--text-muted) 12%,transparent)}.pi-ext-package-source{font-family:var(--font-mono);font-size:.82rem;flex:1;min-width:0;word-break:break-all}.pi-ext-filter-hint{font-size:.72rem;color:var(--text-muted);flex-shrink:0}.pi-ext-package-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.pi-ext-remove-btn{background:none;border:none;padding:var(--space-xs);min-width:var(--space-2xl);min-height:var(--space-2xl);cursor:pointer;color:var(--text-muted);display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);transition:color var(--transition-fast),background-color var(--transition-fast)}.pi-ext-remove-btn:hover{color:var(--color-error);background:color-mix(in srgb,var(--color-error) 10%,transparent)}.pi-ext-remove-btn:focus-visible{box-shadow:var(--focus-ring-strong);outline:none}.pi-ext-filter-list{padding:var(--space-sm) var(--space-md);border-top:1px solid var(--border);background:var(--bg);display:flex;flex-direction:column;gap:var(--space-sm)}.pi-ext-filter-section{display:flex;align-items:center;gap:var(--space-xs);flex-wrap:wrap;color:var(--text-muted)}.pi-ext-filter-label{font-size:.72rem;font-weight:500}.pi-ext-filter-tag{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-xs) var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);font-size:.72rem;font-family:var(--font-mono);color:var(--text-muted)}.pi-ext-top-level{display:flex;flex-direction:column;gap:var(--space-md);margin-top:var(--space-md);padding-top:var(--space-md);border-top:1px solid var(--border)}.pi-ext-section{display:flex;flex-direction:column;gap:var(--space-sm)}.pi-ext-section-header{display:flex;align-items:center;gap:var(--space-xs);color:var(--text-muted);font-size:.82rem}.pi-ext-section-header span:first-of-type{font-weight:500}.pi-ext-count{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 var(--space-xs);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);font-size:.68rem;color:var(--text-dim)}.pi-ext-resource-list{display:flex;flex-wrap:wrap;gap:var(--space-xs)}.pi-ext-resource-tag{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-xs) var(--space-sm);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm)}.pi-ext-resource-path{font-size:.75rem;font-family:var(--font-mono);color:var(--text-muted);max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pi-ext-resource-remove{background:none;border:none;padding:var(--space-xs);min-width:var(--space-2xl);min-height:var(--space-2xl);cursor:pointer;color:var(--text-dim);display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);transition:color var(--transition-fast),background-color var(--transition-fast)}.pi-ext-resource-remove:hover{color:var(--color-error);background:color-mix(in srgb,var(--color-error) 10%,transparent)}.pi-ext-resource-remove:focus-visible{box-shadow:var(--focus-ring-strong);outline:none}@media(max-width:768px){.pi-ext-list{gap:var(--space-xs)}.pi-ext-item{padding:var(--space-sm)}.pi-ext-add-form-row{flex-direction:column;align-items:stretch}.pi-ext-add-form-row .btn,.pi-ext-add-form-row .btn-primary{width:100%}.pi-ext-package-header{padding:var(--space-sm) var(--space-md)}.pi-ext-resource-path{max-width:120px}}.pi-ext-discovered-section{margin-top:var(--space-lg);padding-top:var(--space-lg);border-top:1px solid var(--border)}.pi-ext-discovered-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-sm)}.pi-ext-discovered-header h4{margin:0;font-size:.9rem;font-weight:600}.pi-ext-source-badge--fusion-global{color:var(--color-info);background:color-mix(in srgb,var(--color-info) 12%,transparent)}.pi-ext-source-badge--pi-global{color:var(--color-warning);background:color-mix(in srgb,var(--color-warning) 12%,transparent)}.pi-ext-source-badge--fusion-project{color:var(--color-success);background:color-mix(in srgb,var(--color-success) 12%,transparent)}.pi-ext-source-badge--pi-project{color:var(--color-muted);background:color-mix(in srgb,var(--color-muted) 12%,transparent)}.pi-ext-source-badge--package{color:var(--in-progress);background:color-mix(in srgb,var(--in-progress) 12%,transparent)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.plugin-manager,.plugin-manager-detail{display:flex;flex-direction:column;gap:var(--space-lg)}.plugin-manager-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--space-sm);border-bottom:var(--btn-border-width) solid var(--border)}.plugin-manager-actions{display:flex;gap:var(--space-sm);align-items:center}.plugin-install-form{display:flex;flex-direction:column;gap:var(--space-sm);padding:var(--space-lg);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-install-hint{margin:0;font-size:.85rem;color:var(--text-secondary, var(--text-muted));line-height:1.45}.plugin-install-hint code{padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--text-muted) 12%,transparent);font-size:.85em}.plugin-install-actions{display:flex;gap:var(--space-sm);justify-content:flex-end}.plugin-list{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-item{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md) var(--space-lg);background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.plugin-item:hover{border-color:var(--text-dim)}.plugin-info{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-name{font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.plugin-version{font-size:.85rem}.plugin-state-badge{display:inline-flex;align-items:center;padding:var(--space-xs) var(--space-sm);border-radius:var(--radius-pill);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;background:color-mix(in srgb,currentColor 12%,transparent)}.plugin-actions{display:flex;align-items:center;gap:var(--space-xs);flex-shrink:0}.plugin-manager-detail-header,.plugin-detail-title{display:flex;align-items:center;gap:var(--space-md);flex-wrap:wrap}.plugin-detail-name{margin:0}.plugin-detail-content{display:flex;flex-direction:column;gap:var(--space-lg)}.plugin-detail-card{background:var(--surface);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);padding:var(--space-lg);display:flex;flex-direction:column;gap:var(--space-md)}.plugin-description{font-size:.95rem;color:var(--text-secondary, var(--text-muted));line-height:1.5}.plugin-detail-meta-row{display:flex;align-items:center;gap:var(--space-xs);font-size:.9rem;color:var(--text-muted)}.plugin-homepage a{display:inline-flex;align-items:center;gap:var(--space-xs);color:var(--color-info);font-size:.85rem}.plugin-detail-section-heading{margin:0;padding:0;border:0;font-size:.95rem}.plugin-settings-form{display:flex;flex-direction:column;gap:var(--space-lg);margin-top:var(--space-xs)}.plugin-settings-form .form-group{padding:0;margin:0}.plugin-settings-array{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-settings-array-item{display:flex;align-items:center;gap:var(--space-sm)}.plugin-settings-array-item input{flex:1}.plugin-detail-actions{display:flex;gap:var(--space-sm);padding-top:var(--space-md);border-top:var(--btn-border-width) solid var(--border);justify-content:flex-end}.plugin-manager .empty-state,.plugin-manager .loading-state,.plugin-manager .settings-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-sm);padding:var(--space-2xl);text-align:center;color:var(--text-muted)}.plugin-bundled-runtime-list{width:100%;display:flex;flex-direction:column;gap:var(--space-sm);margin-top:var(--space-sm)}.plugin-bundled-runtime-item{display:flex;align-items:center;justify-content:space-between;gap:var(--space-sm);padding:var(--space-sm) var(--space-md);border:var(--btn-border-width) solid var(--border);border-radius:var(--radius-md);background:var(--surface)}.plugin-bundled-runtime-meta{display:flex;align-items:center;gap:var(--space-sm);min-width:0}.plugin-bundled-runtime-name{color:var(--text);font-size:.9rem;font-weight:500}.plugin-bundled-runtime-badge{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);background:var(--status-in-review-bg);color:var(--in-review);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-section{display:flex;flex-direction:column;gap:var(--space-sm)}.plugin-bundled-runtime-header{display:flex;flex-direction:column;gap:var(--space-xs)}.plugin-bundled-runtime-heading{margin:0;font-size:.95rem}.plugin-bundled-runtime-description{margin:0;font-size:.85rem;color:var(--text-muted)}.plugin-bundled-runtime-status{display:inline-flex;align-items:center;padding:var(--btn-border-width) var(--space-xs);border-radius:var(--radius-pill);font-size:.75rem;font-weight:600;text-transform:uppercase}.plugin-bundled-runtime-status--installed{background:var(--status-done-bg);color:var(--done)}.plugin-bundled-runtime-status--available{background:var(--status-todo-bg);color:var(--todo)}@media(max-width:768px){.plugin-manager-detail-header{gap:var(--space-sm)}.plugin-detail-title{gap:var(--space-xs)}.plugin-detail-card{padding:var(--space-md);gap:var(--space-sm)}.plugin-list{gap:var(--space-xs)}.plugin-item{padding:var(--space-md);flex-direction:column;align-items:stretch;gap:var(--space-sm)}.plugin-info{width:100%;flex-wrap:wrap;row-gap:var(--space-xs)}.plugin-name{flex:1 1 100%;white-space:normal}.plugin-actions{width:100%;justify-content:flex-end;flex-wrap:wrap;gap:var(--space-sm)}.plugin-actions .btn-icon,.plugin-actions .toggle-switch{min-width:36px;min-height:36px}.plugin-actions .toggle-switch{display:inline-flex;align-items:center;justify-content:center}.plugin-detail-actions{flex-wrap:wrap;justify-content:flex-start}.plugin-detail-actions button{flex:1 1 auto;min-height:36px}.plugin-bundled-runtime-item{flex-direction:column;align-items:stretch}.plugin-bundled-runtime-item .btn{min-height:36px}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as o,j as e}from"./vendor-react-K0fH_qHe.js";import{cO as W,s as Y,X as U,ah as Z,w as k,cP as O,I as A,R as T,cQ as ee,aq as se,cR as ne,cS as te,cT as ie,cU as ae,cV as le,cW as V,cX as re}from"./index-DQKtk17v.js";import{D as ce}from"./DirectoryPicker-B0qNpfLW.js";import"./vendor-xterm-DzcZoU0P.js";import"./folder-open-B_38R5AA.js";const de=[{id:"fusion-plugin-hermes-runtime",name:"Hermes Runtime",path:"./plugins/fusion-plugin-hermes-runtime",experimental:!0},{id:"fusion-plugin-paperclip-runtime",name:"Paperclip Runtime",path:"./plugins/fusion-plugin-paperclip-runtime"},{id:"fusion-plugin-openclaw-runtime",name:"OpenClaw Runtime",path:"./plugins/fusion-plugin-openclaw-runtime",experimental:!0}],N={started:"var(--color-success)",loaded:"var(--color-warning)",error:"var(--color-error)",stopped:"var(--color-muted)",installed:"var(--color-info)"};function xe({addToast:l,projectId:c}){const[x,b]=o.useState([]),[S,w]=o.useState(!0),[_,f]=o.useState(!1),[j,v]=o.useState(""),[C,P]=o.useState(!1),[h,$]=o.useState(null),[i,y]=o.useState(null),[a,g]=o.useState({}),[H,I]=o.useState(!1),[R,E]=o.useState(null),u=o.useCallback(async()=>{try{w(!0);const s=await W(c);b(s)}catch(s){l(`Failed to load plugins: ${s instanceof Error?s.message:String(s)}`,"error")}finally{w(!1)}},[c,l]);o.useEffect(()=>{u()},[u]);const M=o.useRef([]);M.current=x,o.useEffect(()=>{const s=c?`?projectId=${encodeURIComponent(c)}`:"",n=p=>{try{const t=JSON.parse(p.data);if(c&&t.projectId&&t.projectId!==c)return;switch(t.transition){case"installing":case"enabled":case"disabled":case"settings-updated":b(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],enabled:t.enabled,state:t.state,settings:t.settings,error:t.error},r}else return u(),d});break;case"uninstalled":b(d=>d.filter(m=>m.id!==t.pluginId));break;case"error":b(d=>{const m=d.findIndex(r=>r.id===t.pluginId);if(m>=0){const r=[...d];return r[m]={...r[m],state:t.state,error:t.error},r}return d});break}}catch{}};return Y(`/api/events${s}`,{events:{"plugin:lifecycle":n},onReconnect:()=>{u()}})},[c,u]);const z=async()=>{if(!j.trim()){l("Please enter a plugin path","error");return}try{P(!0),await V({path:j},c),l("Plugin installed successfully","success"),f(!1),v(""),await u()}catch(s){l(`Failed to install plugin: ${s instanceof Error?s.message:String(s)}`,"error")}finally{P(!1)}},X=async s=>{try{E(s.id),await V({path:s.path},c),l(`${s.name} installed successfully`,"success"),await u()}catch(n){l(`Failed to install ${s.name}: ${n instanceof Error?n.message:String(n)}`,"error")}finally{E(null)}},F=async s=>{try{await ae(s.id,c),l(`${s.name} enabled`,"success"),await u()}catch(n){l(`Failed to enable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},B=async s=>{try{await ie(s.id,c),l(`${s.name} disabled`,"success"),await u()}catch(n){l(`Failed to disable plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},L=async s=>{try{$(s.id),await te(s.id,c),l(`${s.name} reloaded`,"success"),await u()}catch(n){l(`Failed to reload plugin: ${n instanceof Error?n.message:String(n)}`,"error")}finally{$(null)}},q=async s=>{if(confirm(`Are you sure you want to uninstall "${s.name}"?`))try{await le(s.id,c),l(`${s.name} uninstalled`,"success"),await u(),y(null)}catch(n){l(`Failed to uninstall plugin: ${n instanceof Error?n.message:String(n)}`,"error")}},G=async s=>{y(s);try{I(!0);const n=await re(s.id,c);g(n)}catch{g({})}finally{I(!1)}},J=async()=>{if(i)try{await ne(i.id,a,c),l("Settings saved","success")}catch(s){l(`Failed to save settings: ${s instanceof Error?s.message:String(s)}`,"error")}};if(i)return e.jsxs("div",{className:"plugin-manager-detail","data-testid":"plugin-manager-detail",children:[e.jsxs("div",{className:"plugin-manager-detail-header",children:[e.jsx("button",{className:"btn-icon",onClick:()=>y(null),"aria-label":"Back to plugin list",children:e.jsx(U,{size:16})}),e.jsxs("div",{className:"plugin-detail-title",children:[e.jsx("h4",{className:"plugin-detail-name",children:i.name}),e.jsx("span",{className:"plugin-state-badge",style:{color:N[i.state]||N.installed},children:i.state})]})]}),e.jsxs("div",{className:"plugin-detail-content",children:[e.jsxs("div",{className:"plugin-detail-card",children:[i.description&&e.jsx("p",{className:"plugin-description",children:i.description}),i.author&&e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Author:"}),i.author]}),i.homepage&&e.jsxs("p",{className:"plugin-detail-meta-row plugin-homepage",children:[e.jsx("span",{className:"text-muted",children:"Homepage:"}),e.jsxs("a",{href:i.homepage,target:"_blank",rel:"noopener noreferrer",children:[i.homepage,e.jsx(Z,{size:12})]})]}),e.jsxs("p",{className:"plugin-detail-meta-row",children:[e.jsx("span",{className:"text-muted",children:"Version:"}),i.version]})]}),e.jsxs("div",{className:"plugin-detail-card",children:[e.jsx("h5",{className:"plugin-detail-section-heading",children:"Settings"}),H?e.jsx("p",{className:"text-muted",children:"Loading..."}):i.settingsSchema&&Object.keys(i.settingsSchema).length>0?e.jsxs("div",{className:"plugin-settings-form",children:[Object.entries(i.settingsSchema).map(([s,n])=>{const p=`setting-${s}-help`;return e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{htmlFor:`setting-${s}`,children:[n.label||s,n.required&&" *"]}),n.type==="string"&&!n.multiline&&e.jsx("input",{type:"text",id:`setting-${s}`,value:a[s]??"",onChange:t=>g({...a,[s]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?p:void 0}),n.type==="string"&&n.multiline&&e.jsx("textarea",{id:`setting-${s}`,rows:4,value:a[s]??"",onChange:t=>g({...a,[s]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?p:void 0}),n.type==="password"&&e.jsx("input",{type:"password",id:`setting-${s}`,value:a[s]??"",onChange:t=>g({...a,[s]:t.target.value}),placeholder:n.description,"aria-describedby":n.description&&!n.required?p:void 0}),n.type==="number"&&e.jsx("input",{type:"number",id:`setting-${s}`,value:a[s]??"",onChange:t=>g({...a,[s]:Number(t.target.value)}),"aria-describedby":n.description&&!n.required?p:void 0}),n.type==="boolean"&&e.jsxs("label",{className:"checkbox-label",children:[e.jsx("input",{type:"checkbox",checked:a[s]??!1,onChange:t=>g({...a,[s]:t.target.checked})}),n.description]}),n.type==="enum"&&e.jsxs("select",{id:`setting-${s}`,value:a[s]??"",onChange:t=>g({...a,[s]:t.target.value}),"aria-describedby":n.description&&!n.required?p:void 0,children:[e.jsx("option",{value:"",children:"Select..."}),n.enumValues?.map(t=>e.jsx("option",{value:t,children:t},t))]}),n.type==="array"&&e.jsxs("div",{className:"plugin-settings-array",children:[a[s]?.map((t,d)=>e.jsxs("div",{className:"plugin-settings-array-item",children:[e.jsx("input",{type:n.itemType==="number"?"number":"text",value:t??"",onChange:m=>{const r=m.target.value,D=[...a[s]||[]];D[d]=n.itemType==="number"?Number(r):r,g({...a,[s]:D})}}),e.jsx("button",{className:"btn-icon",onClick:()=>{const r=[...a[s]||[]];r.splice(d,1),g({...a,[s]:r})},"aria-label":"Remove item",children:e.jsx(U,{size:14})})]},d)),e.jsxs("button",{className:"btn btn-secondary",onClick:()=>{const t=a[s]||[],d=n.itemType==="number"?0:"";g({...a,[s]:[...t,d]})},children:[e.jsx(k,{size:14})," Add Item"]})]}),n.description&&!n.required&&!n.multiline&&e.jsx("span",{id:p,className:"form-help",children:n.description})]},s)}),e.jsx("button",{className:"btn btn-primary",onClick:J,children:"Save Settings"})]}):e.jsx("p",{className:"text-muted",children:"No configurable settings."})]}),e.jsxs("div",{className:"plugin-detail-actions",children:[i.state==="started"&&e.jsxs("button",{className:"btn btn-secondary",onClick:()=>L(i),disabled:h===i.id,children:[e.jsx(O,{size:14,className:h===i.id?"spin":""}),h===i.id?"Reloading...":"Reload"]}),i.enabled?e.jsx("button",{className:"btn btn-secondary",onClick:()=>B(i),children:"Disable"}):e.jsx("button",{className:"btn btn-primary",onClick:()=>F(i),children:"Enable"}),e.jsxs("button",{className:"btn btn-danger",onClick:()=>q(i),children:[e.jsx(A,{size:14})," Uninstall"]})]})]})]});const K=new Set(x.map(s=>s.id)),Q=()=>e.jsxs("section",{className:"plugin-bundled-runtime-section","aria-label":"Bundled Runtime Plugins",children:[e.jsxs("div",{className:"plugin-bundled-runtime-header",children:[e.jsx("h4",{className:"plugin-bundled-runtime-heading",children:"Bundled Runtime Plugins"}),e.jsx("p",{className:"plugin-bundled-runtime-description",children:"Install Fusion's bundled runtimes directly from this screen."})]}),e.jsx("div",{className:"plugin-bundled-runtime-list","aria-label":"Bundled runtime plugin recommendations",children:de.map(s=>{const n=K.has(s.id);return e.jsxs("div",{className:"plugin-bundled-runtime-item",children:[e.jsxs("div",{className:"plugin-bundled-runtime-meta",children:[e.jsx("span",{className:"plugin-bundled-runtime-name",children:s.name}),s.experimental&&e.jsx("span",{className:"plugin-bundled-runtime-badge",children:"Experimental"}),e.jsx("span",{className:`plugin-bundled-runtime-status ${n?"plugin-bundled-runtime-status--installed":"plugin-bundled-runtime-status--available"}`,children:n?"Installed":"Not installed"})]}),e.jsx("button",{className:`btn ${n?"btn-secondary":"btn-primary"} btn-sm`,onClick:()=>X(s),disabled:n||R===s.id,children:n?"Installed":R===s.id?"Installing...":`Install ${s.name}`})]},s.id)})})]});return e.jsxs("div",{className:"plugin-manager","data-testid":"plugin-manager",children:[e.jsx("div",{className:"plugin-manager-header",children:e.jsxs("div",{className:"plugin-manager-actions",children:[e.jsx("button",{className:"btn-icon",onClick:u,title:"Refresh",children:e.jsx(T,{size:16,className:S?"spin":""})}),e.jsxs("button",{className:"btn btn-primary",onClick:()=>f(!0),children:[e.jsx(k,{size:14})," Install"]})]})}),_&&e.jsxs("div",{className:"plugin-install-form",children:[e.jsxs("p",{className:"plugin-install-hint",children:["Browse to a plugin package root (contains ",e.jsx("code",{children:"manifest.json"}),") or a built ",e.jsx("code",{children:"dist"})," directory."]}),e.jsx(ce,{value:j,onChange:v,placeholder:"Absolute path to plugin directory or dist folder",onInputKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),z())}}),e.jsxs("div",{className:"plugin-install-actions",children:[e.jsx("button",{className:"btn btn-primary",onClick:z,disabled:C||!j.trim(),children:C?"Installing...":"Install Plugin"}),e.jsx("button",{className:"btn btn-secondary",onClick:()=>{f(!1),v("")},children:"Cancel"})]})]}),S?e.jsx("div",{className:"settings-empty-state",children:"Loading plugins..."}):e.jsxs(e.Fragment,{children:[x.length===0?e.jsxs("div",{className:"settings-empty-state",children:[e.jsx(ee,{size:32,className:"text-muted"}),e.jsx("p",{children:"No plugins installed."}),e.jsx("p",{className:"text-muted",children:"Install a plugin to get started, or use a bundled runtime below."})]}):e.jsx("div",{className:"plugin-list",children:x.map(s=>e.jsxs("div",{className:"plugin-item",children:[e.jsxs("div",{className:"plugin-info",children:[e.jsx("span",{className:"plugin-name",children:s.name}),e.jsxs("span",{className:"plugin-version text-muted",children:["v",s.version]}),e.jsx("span",{className:"plugin-state-badge",style:{color:N[s.state]||N.installed},children:s.state})]}),e.jsxs("div",{className:"plugin-actions",children:[s.state==="started"&&e.jsx("button",{className:"btn-icon",onClick:()=>L(s),disabled:h===s.id,title:"Reload",children:e.jsx(O,{size:14,className:h===s.id?"spin":""})}),e.jsxs("label",{className:"toggle-switch",children:[e.jsx("input",{type:"checkbox",checked:s.enabled,onChange:()=>s.enabled?B(s):F(s)}),e.jsx("span",{className:"toggle-slider"})]}),e.jsx("button",{className:"btn-icon",onClick:()=>G(s),title:"Settings",children:e.jsx(se,{size:14})}),e.jsx("button",{className:"btn-icon",onClick:()=>q(s),title:"Uninstall",children:e.jsx(A,{size:14})})]})]},s.id))}),Q()]})]})}export{xe as PluginManager,N as STATE_COLORS};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{c as St,
|
|
1
|
+
import{r as a,j as e}from"./vendor-react-K0fH_qHe.js";import{c as St,aN as Et,aO as kt,aP as Ft,aQ as Dt,aR as Mt,aS as tt,aT as Rt,aU as It,aV as at,aW as $t,aX as zt,aY as At,aZ as Ot,a_ as Bt,a$ as Ht,b0 as Tt,b1 as Gt,aF as Pt,w as Ae,b2 as me,X as ae,as as Ee,I as Le,a7 as Lt,ad as ut,ar as rt,a4 as Vt,b3 as Ye,b4 as Ut}from"./index-DQKtk17v.js";import"./vendor-xterm-DzcZoU0P.js";/**
|
|
2
2
|
* @license lucide-react v1.7.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Kt=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],Wt=St("loader",Kt);function Yt(l){const n=l?.projectId,[j,f]=a.useState([]),[b,C]=a.useState(null),[S,m]=a.useState(null),[I,E]=a.useState([]),[_,y]=a.useState({}),[re,z]=a.useState(!1),[W,A]=a.useState(null),[ke,se]=a.useState(null),[ge,ne]=a.useState(!1),[Oe,ie]=a.useState(null),[he,R]=a.useState([]),[J,oe]=a.useState(!1),[X,B]=a.useState({}),[Fe,le]=a.useState({}),P=a.useRef(X),De=a.useRef(Fe),Y=a.useRef(he);P.current=X,De.current=Fe,Y.current=he;const Me=a.useRef(n),F=a.useRef(0),Q=a.useRef(0),Be=a.useRef(j),v=a.useRef(b),He=a.useRef(I),fe=a.useRef(_),M=a.useRef(n),Z=a.useRef(ke);Be.current=j,v.current=b,He.current=I,fe.current=_,M.current=n,Z.current=ke,a.useEffect(()=>{Me.current!==n&&(Me.current=n,F.current++,C(null),m(null),E([]),y({}),se(null),ie(null),R([]),oe(!1),B({}),le({}))},[n]);const be=a.useCallback(async()=>{z(!0),A(null);try{const r=await Et(n);f(r)}catch(r){A(r instanceof Error?r:new Error("Failed to fetch roadmaps"))}finally{z(!1)}},[n]),N=a.useCallback(async r=>{try{const c=await kt(r,n);m(c),E(c.milestones||[]);const i={};for(const s of c.milestones||[])i[s.id]=s.features||[];y(i)}catch(c){A(c instanceof Error?c:new Error("Failed to fetch roadmap"))}},[n]);a.useEffect(()=>{be()},[be]),a.useEffect(()=>{b?N(b):(m(null),E([]),y({}))},[b,N]);const ve=a.useCallback(async(r,c)=>{try{const i=await Ft(r,M.current);f(s=>[...s,i]),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to create roadmap");throw c?.onError?.(s),s}},[]),Ge=a.useCallback(async(r,c,i)=>{try{const s=await Dt(r,c,M.current);f(d=>d.map(o=>o.id===r?s:o)),v.current===r&&m(d=>d?{...d,...s}:null),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update roadmap");throw i?.onError?.(d),d}},[]),h=a.useCallback(async(r,c)=>{try{await Mt(r,M.current),f(i=>i.filter(s=>s.id!==r)),v.current===r&&(C(null),m(null),E([]),y({})),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete roadmap");throw c?.onError?.(s),s}},[]),$=a.useCallback(r=>{C(r)},[]),H=a.useCallback(async(r,c)=>{const i=v.current;if(!i){const s=new Error("No roadmap selected");throw c?.onError?.(s),s}try{const s=await tt(i,r,M.current);E(d=>[...d,s]),y(d=>({...d,[s.id]:[]})),v.current&&N(v.current),c?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create milestone");throw c?.onError?.(d),d}},[N]),xe=a.useCallback(async(r,c,i)=>{try{const s=await Rt(r,c,M.current);E(d=>d.map(o=>o.id===r?s:o)),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update milestone");throw i?.onError?.(d),d}},[N]),Ve=a.useCallback(async(r,c)=>{try{await It(r,M.current),E(i=>i.filter(s=>s.id!==r)),y(i=>{const s={...i};return delete s[r],s}),v.current&&N(v.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete milestone");throw c?.onError?.(s),s}},[N]),Re=a.useCallback(async(r,c,i)=>{try{const s=await at(r,c,M.current);y(d=>({...d,[r]:[...d[r]||[],s]})),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create feature");throw i?.onError?.(d),d}},[N]),D=a.useCallback(async(r,c,i)=>{try{const s=await $t(r,c,M.current);y(d=>{const o={};for(const[g,p]of Object.entries(d))o[g]=p.map(x=>x.id===r?s:x);return o}),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update feature");throw i?.onError?.(d),d}},[N]),G=a.useCallback(async(r,c)=>{try{await zt(r,M.current),y(i=>{const s={};for(const[d,o]of Object.entries(i))s[d]=o.filter(g=>g.id!==r);return s}),v.current&&N(v.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete feature");throw c?.onError?.(s),s}},[N]),ee=a.useCallback(async(r,c,i)=>{const s=He.current,d=c.map(o=>s.find(g=>g.id===o)).filter(o=>o!==void 0).map((o,g)=>({...o,orderIndex:g}));E(d);try{await At(r,c,M.current),v.current&&N(v.current),i?.onSuccess?.()}catch(o){E(s);const g=o instanceof Error?o:new Error("Failed to reorder milestones");throw i?.onError?.(g),g}},[N]),q=a.useCallback(async(r,c,i)=>{const s=fe.current[r]||[],d=s.map(p=>p.id);if(JSON.stringify(d)===JSON.stringify(c)){i?.onSuccess?.();return}const o=fe.current,g=c.map(p=>s.find(x=>x.id===p)).filter(p=>p!==void 0).map((p,x)=>({...p,orderIndex:x}));y(p=>({...p,[r]:g}));try{await Ot(r,c,M.current),v.current&&N(v.current),i?.onSuccess?.()}catch(p){y(o);const x=p instanceof Error?p:new Error("Failed to reorder features");throw i?.onError?.(x),x}},[N]),we=a.useCallback(async(r,c,i,s)=>{const d=fe.current;let o=null;for(const[k,U]of Object.entries(d))if(U.some(Ue=>Ue.id===r)){o=k;break}if(!o){const k=new Error("Feature not found");throw s?.onError?.(k),k}if(o===c){const k=d[o]||[],U=Math.max(0,Math.min(i,k.length-1));if(k.findIndex(We=>We.id===r)===U){s?.onSuccess?.();return}}const g=d[o]||[],p=d[c]||[],x=g.find(k=>k.id===r);if(!x){const k=new Error("Feature not found");throw s?.onError?.(k),k}const V=g.filter(k=>k.id!==r).map((k,U)=>({...k,orderIndex:U})),te={...x,milestoneId:c,orderIndex:i},Ce=[...p];Ce.splice(i,0,te);const Ke=Ce.map((k,U)=>({...k,orderIndex:U}));y(o===c?k=>({...k,[o]:Ke}):k=>({...k,[o]:V,[c]:Ke}));try{await Bt(r,c,i,n),v.current&&N(v.current),s?.onSuccess?.()}catch(k){y(d);const U=k instanceof Error?k:new Error("Failed to move feature");throw s?.onError?.(U),U}},[N,n]);function ce(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`draft-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}const Ie=a.useCallback(async(r,c=5,i)=>{const s=v.current;if(!s){const g=new Error("No roadmap selected");throw i?.onError?.(g),g}const d=F.current,o=M.current;oe(!0);try{const g=await Ht(s,r,c,o);if(F.current!==d)return;const p=g.suggestions.map(x=>({id:ce(),title:x.title,description:x.description}));R(p),i?.onSuccess?.()}catch(g){if(F.current!==d)return;const p=g instanceof Error?g:new Error("Failed to generate suggestions");throw i?.onError?.(p),p}finally{F.current===d&&oe(!1)}},[]),de=a.useCallback((r,c)=>{const s=Y.current.map(d=>d.id===r?{...d,...c}:d);Y.current=s,R(d=>d.map(o=>o.id===r?{...o,...c}:o))},[]),L=a.useCallback(async(r,c)=>{const i=v.current;if(!i){const p=new Error("No roadmap selected");throw c?.onError?.(p),p}const s=F.current,d=Y.current,o=d.findIndex(p=>p.id===r);if(o===-1){const p=new Error("Suggestion draft not found");throw c?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw c?.onError?.(p),p}R(p=>p.filter(x=>x.id!==r));try{if(await tt(i,{title:g.title,description:g.description},M.current),F.current!==s){R(p=>{const x=[...p];return x.splice(o,0,g),x});return}v.current&&N(v.current),c?.onSuccess?.()}catch(p){R(V=>{const te=[...V];return te.splice(o,0,g),te});const x=p instanceof Error?p:new Error("Failed to accept suggestion");throw c?.onError?.(x),x}},[N]),qe=a.useCallback(async r=>{const c=v.current;if(!c){const o=new Error("No roadmap selected");throw r?.onError?.(o),o}const i=[...Y.current];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw r?.onError?.(o),o}R([]);const d=F.current;for(let o=0;o<i.length&&F.current===d;o++){const g=i[o];try{await tt(c,{title:g.title,description:g.description},M.current)}catch(p){const x=p instanceof Error?p:new Error("Failed to accept all suggestions");throw r?.onError?.(x),x}}F.current===d&&(v.current&&N(v.current),r?.onSuccess?.())},[N]),Te=a.useCallback(r=>De.current[r]??!1,[]),je=a.useCallback(async(r,c,i)=>{const s=F.current,d=M.current;le(o=>({...o,[r]:!0}));try{const o=await Gt(r,c,d);if(F.current!==s)return;const g=o.suggestions.map(p=>({id:ce(),title:p.title,description:p.description}));B(p=>({...p,[r]:g})),i?.onSuccess?.()}catch(o){if(F.current!==s)return;const g=o instanceof Error?o:new Error("Failed to generate feature suggestions");throw i?.onError?.(g),g}finally{F.current===s&&le(o=>({...o,[r]:!1}))}},[]),Pe=a.useCallback((r,c,i)=>{const d=(P.current[r]||[]).map(o=>o.id===c?{...o,...i}:o);P.current={...P.current,[r]:d},B(o=>({...o,[r]:o[r]?.map(g=>g.id===c?{...g,...i}:g)||[]}))},[]),Je=a.useCallback(async(r,c,i)=>{const s=F.current,d=P.current[r]||[],o=d.findIndex(p=>p.id===c);if(o===-1){const p=new Error("Suggestion draft not found");throw i?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw i?.onError?.(p),p}B(p=>({...p,[r]:p[r]?.filter(x=>x.id!==c)||[]}));try{if(await at(r,{title:g.title,description:g.description},M.current),F.current!==s){B(p=>{const V=[...p[r]||[]];return V.splice(o,0,g),{...p,[r]:V}});return}v.current&&N(v.current),i?.onSuccess?.()}catch(p){B(V=>{const Ce=[...V[r]||[]];return Ce.splice(o,0,g),{...V,[r]:Ce}});const x=p instanceof Error?p:new Error("Failed to accept suggestion");throw i?.onError?.(x),x}},[N]),_e=a.useCallback(async(r,c)=>{const i=[...P.current[r]||[]];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw c?.onError?.(o),o}B(o=>({...o,[r]:[]}));const d=F.current;for(let o=0;o<i.length&&F.current===d;o++){const g=i[o];try{await at(r,{title:g.title,description:g.description},M.current)}catch(p){const x=p instanceof Error?p:new Error("Failed to accept all suggestions");throw c?.onError?.(x),x}}F.current===d&&(v.current&&N(v.current),c?.onSuccess?.())},[N]),Xe=a.useCallback(()=>{R([]),oe(!1)},[]),ue=a.useCallback(r=>{B(c=>{const i={...c};return delete i[r],i}),le(c=>{const i={...c};return delete i[r],i})},[]),$e=a.useCallback(async(r,c)=>{const i=++Q.current,s=n;ne(!0),ie(null);try{const d=await Tt(r,s);if(Q.current!==i||n!==s)return;se(d),c?.onSuccess?.()}catch(d){if(Q.current!==i||n!==s)return;const o=d instanceof Error?d:new Error(String(d));ie(o),se(null),c?.onError?.(o)}finally{Q.current===i&&ne(!1)}},[n]),Qe=a.useCallback(()=>{se(null),ie(null),ne(!1)},[]),pe=a.useCallback(async()=>{await be(),v.current&&await N(v.current)},[be,N]);return{roadmaps:j,selectedRoadmapId:b,selectedRoadmap:S,milestones:I,featuresByMilestoneId:_,loading:re,error:W,createRoadmap:ve,updateRoadmap:Ge,deleteRoadmap:h,selectRoadmap:$,createMilestone:H,updateMilestone:xe,deleteMilestone:Ve,reorderMilestones:ee,createFeature:Re,updateFeature:D,deleteFeature:G,reorderFeatures:q,moveFeature:we,milestoneSuggestions:he,isGeneratingSuggestions:J,generateMilestoneSuggestions:Ie,updateMilestoneSuggestionDraft:de,acceptMilestoneSuggestion:L,acceptAllMilestoneSuggestions:qe,clearMilestoneSuggestions:Xe,featureSuggestionsByMilestoneId:X,isGeneratingFeatureSuggestions:Te,generateFeatureSuggestions:je,updateFeatureSuggestionDraft:Pe,acceptFeatureSuggestion:Je,acceptAllFeatureSuggestions:_e,clearFeatureSuggestions:ue,handoffPayload:ke,isFetchingHandoff:ge,handoffError:Oe,fetchHandoff:$e,clearHandoff:Qe,refresh:pe}}function qt({isOpen:l,onClose:n,roadmapTitle:j,handoffPayload:f,isLoading:b,error:C,onFetchHandoff:S,onCopyToClipboard:m}){return l?e.jsx("div",{className:"modal-overlay open",onClick:n,role:"presentation",children:e.jsxs("div",{className:"modal modal-lg",onClick:I=>I.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"handoff-modal-title",children:[e.jsxs("div",{className:"modal-header",children:[e.jsxs("h2",{id:"handoff-modal-title",children:["Export Roadmap: ",j]}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close modal",children:e.jsx(ae,{size:18})})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("p",{className:"text-muted",style:{marginBottom:"var(--space-lg)"},children:"Export roadmap data for use in mission and task planning flows. This is a read-only export — no missions or tasks will be created."}),C&&e.jsxs("div",{className:"form-error",style:{marginBottom:"var(--space-lg)"},children:["Error loading handoff data: ",C.message]}),!f&&!b&&e.jsx("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:e.jsxs("button",{className:"btn btn-primary",onClick:S,children:[e.jsx(rt,{size:16,style:{marginRight:"var(--space-sm)"}}),"Load Handoff Data"]})}),b&&e.jsxs("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:[e.jsx(Wt,{size:24,className:"spin"}),e.jsx("p",{style:{marginTop:"var(--space-md)"},children:"Loading handoff data..."})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsx("h3",{style:{marginBottom:"var(--space-sm)"},children:"Mission Planning Handoff"}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"200px",overflow:"auto"},children:JSON.stringify(f.mission,null,2)})})]}),e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsxs("h3",{style:{marginBottom:"var(--space-sm)"},children:["Feature Task Planning Handoffs (",f.features.length,")"]}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"300px",overflow:"auto"},children:JSON.stringify(f.features,null,2)})})]})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("div",{className:"modal-actions-left",children:f&&e.jsxs("button",{className:"btn btn-sm",onClick:m,children:[e.jsx(Ut,{size:14,style:{marginRight:"var(--space-xs)"}}),"Copy to Clipboard"]})}),e.jsx("div",{className:"modal-actions-right",children:e.jsx("button",{className:"btn",onClick:n,children:"Close"})})]})]})}):null}function Jt({roadmap:l,isSelected:n,onSelect:j,onEdit:f,onDelete:b,onExport:C}){const S=_=>{_.key==="Enter"&&j()},m=_=>{_.stopPropagation(),f()},I=_=>{_.stopPropagation(),b()},E=_=>{_.stopPropagation(),C()};return e.jsxs("div",{className:`roadmaps-view__sidebar-item${n?" roadmaps-view__sidebar-item--active":""}`,onClick:j,onKeyDown:S,role:"button",tabIndex:0,"aria-selected":n,"data-testid":`roadmap-item-${l.id}`,children:[e.jsxs("div",{className:"roadmaps-view__sidebar-item-content",children:[e.jsx("div",{className:"roadmaps-view__sidebar-item-title",children:l.title}),l.description&&e.jsx("div",{className:"roadmaps-view__sidebar-item-desc",children:l.description})]}),e.jsxs("div",{className:"roadmaps-view__sidebar-item-actions",onClick:m,role:"presentation",children:[e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:E,role:"button",title:"Export roadmap","aria-label":"Export roadmap","data-testid":`roadmap-export-${l.id}`,tabIndex:0,children:e.jsx(rt,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:m,role:"button",title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`roadmap-edit-${l.id}`,tabIndex:0,children:e.jsx(Ee,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:I,role:"button",title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`roadmap-delete-${l.id}`,tabIndex:0,children:e.jsx(Le,{size:14})})]})]})}function Xt({roadmaps:l,selectedRoadmapId:n,onSelect:j,onCreate:f,onEdit:b,onDelete:C,onExport:S,showCreateForm:m,onCancelCreate:I,onSaveCreate:E}){return e.jsxs("div",{className:"roadmaps-view__mobile-list","data-testid":"roadmaps-view__mobile-list",children:[e.jsxs("div",{className:"roadmaps-view__mobile-list-header",children:[e.jsx("h2",{className:"roadmaps-view__mobile-list-title",children:"Roadmaps"}),!m&&e.jsx("button",{className:"roadmaps-view__mobile-add-btn",onClick:f,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-create-roadmap-btn",children:e.jsx(Ae,{size:18})})]}),m&&e.jsx("div",{className:"roadmaps-view__mobile-create-form",children:e.jsx(pt,{onSave:E,onCancel:I})}),l.length===0&&!m?e.jsxs("div",{className:"roadmaps-view__mobile-empty",children:[e.jsx("p",{children:"No roadmaps yet."}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Create Roadmap"})]})]}):e.jsx("div",{className:"roadmaps-view__mobile-list-items",children:l.map(_=>e.jsxs("div",{className:`roadmaps-view__mobile-item${_.id===n?" roadmaps-view__mobile-item--active":""}`,onClick:()=>j(_.id),role:"button",tabIndex:0,onKeyDown:y=>{y.key==="Enter"&&j(_.id)},"data-testid":`mobile-roadmap-item-${_.id}`,children:[e.jsxs("div",{className:"roadmaps-view__mobile-item-content",children:[e.jsx("span",{className:"roadmaps-view__mobile-item-title",children:_.title}),_.description&&e.jsx("span",{className:"roadmaps-view__mobile-item-desc",children:_.description})]}),e.jsxs("div",{className:"roadmaps-view__mobile-item-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),S(_)},title:"Export roadmap","aria-label":"Export roadmap","data-testid":`mobile-roadmap-export-${_.id}`,children:e.jsx(rt,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),b(_)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`mobile-roadmap-edit-${_.id}`,children:e.jsx(Ee,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:y=>{y.stopPropagation(),C(_.id)},title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`mobile-roadmap-delete-${_.id}`,children:e.jsx(Le,{size:16})})]})]},_.id))})]})}function Qt({roadmapTitle:l,onBack:n,onEdit:j,onDelete:f,onCreate:b}){return e.jsxs("div",{className:"roadmaps-view__mobile-header","data-testid":"roadmaps-view__mobile-header",children:[e.jsx("button",{className:"roadmaps-view__mobile-back-btn",onClick:n,title:"Back to roadmap list","aria-label":"Back to roadmap list","data-testid":"mobile-back-btn",children:e.jsx(Vt,{size:20})}),e.jsx("h2",{className:"roadmaps-view__mobile-header-title",children:l}),e.jsxs("div",{className:"roadmaps-view__mobile-header-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:b,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-header-create-btn",children:e.jsx(Ae,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:j,title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"mobile-header-edit-btn",children:e.jsx(Ee,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:f,title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"mobile-header-delete-btn",children:e.jsx(Le,{size:18})})]})]})}function Zt({milestone:l,features:n,onEditMilestone:j,onDeleteMilestone:f,onAddFeature:b,onEditFeature:C,onDeleteFeature:S,milestoneEdit:m,onStartMilestoneEdit:I,onCancelMilestoneEdit:E,onSaveMilestoneEdit:_,featureEdit:y,onStartFeatureEdit:re,onCancelFeatureEdit:z,onSaveFeatureEdit:W,projectId:A,addToast:ke,isMilestoneDragging:se,isMilestoneDropTarget:ge,milestoneDropPosition:ne,onMilestoneDragStart:Oe,onMilestoneDragEnd:ie,onMilestoneDragOver:he,onMilestoneDrop:R,onMilestoneDragLeave:J,isFeatureDragging:oe,isFeatureDropTarget:X,featureDropIndex:B,onFeatureDragStart:Fe,onFeatureDragEnd:le,onFeatureDragOver:P,onFeatureDrop:De,onFeatureDragLeave:Y,onFeatureDropOnMilestone:Me,featureSuggestions:F,isGeneratingFeatureSuggestions:Q,onGenerateFeatureSuggestions:Be,onAcceptFeatureSuggestion:v,onAcceptAllFeatureSuggestions:He,onUpdateFeatureSuggestionDraft:fe,onClearFeatureSuggestions:M}){const Z=m?.milestoneId===l.id,be=h=>{h.key==="Enter"?(h.preventDefault(),m&&_({title:m.value})):h.key==="Escape"&&E()},N=h=>{h.key==="Escape"&&E()},ve=["roadmaps-view__milestone",se?"roadmaps-view__milestone--dragging":"",ge?"roadmaps-view__milestone--drop-target":"",ge&&ne==="before"?"roadmaps-view__milestone--drop-before":"",ge&&ne==="after"?"roadmaps-view__milestone--drop-after":""].filter(Boolean).join(" "),Ge=["roadmaps-view__feature-list",X?"roadmaps-view__feature-list--drop-target":""].filter(Boolean).join(" ");return e.jsxs("div",{className:ve,draggable:!Z,onDragStart:h=>{Z||(Oe(l.id),h.dataTransfer.setData("text/plain",`milestone:${l.id}`),h.dataTransfer.effectAllowed="move")},onDragEnd:ie,onDragOver:h=>{h.dataTransfer.types.includes("text/plain")&&h.dataTransfer.types.includes("text/plain")&&(h.preventDefault(),h.dataTransfer.dropEffect="move",he(l.id))},onDrop:h=>{h.preventDefault(),h.dataTransfer.getData("text/plain")?.startsWith("feature:")||R(l.id)},onDragLeave:J,"data-testid":`milestone-card-${l.id}`,children:[e.jsx("div",{className:"roadmaps-view__milestone-header",children:Z?e.jsxs("div",{className:"roadmaps-view__inline-edit",children:[e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:m.value,onChange:()=>I(),onKeyDown:be,placeholder:"Milestone title",autoFocus:!0,"data-testid":`milestone-title-input-${l.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>_({title:m.value}),"aria-label":"Save milestone title",title:"Save",children:e.jsx(me,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:E,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(ae,{size:14})})]}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:m.field==="description"?m.value:l.description||"",onChange:()=>{},onKeyDown:N,placeholder:"Milestone description (optional)",rows:2,"data-testid":`milestone-desc-input-${l.id}`})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__milestone-title-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("h3",{className:"roadmaps-view__milestone-title",children:l.title}),e.jsxs("div",{className:"roadmaps-view__milestone-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:j,title:"Edit milestone","aria-label":"Edit milestone","data-testid":`milestone-edit-${l.id}`,children:e.jsx(Ee,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:f,title:"Delete milestone","aria-label":"Delete milestone","data-testid":`milestone-delete-${l.id}`,children:e.jsx(Le,{size:14})})]})]}),l.description&&e.jsx("p",{className:"roadmaps-view__milestone-desc",children:l.description})]})}),e.jsxs("div",{className:"roadmaps-view__milestone-actions-bar",children:[e.jsxs("button",{className:"roadmaps-view__add-feature-btn",onClick:b,title:"Add feature","aria-label":"Add feature","data-testid":`add-feature-${l.id}`,children:[e.jsx(Ae,{size:12}),e.jsx("span",{children:"Add Feature"})]}),e.jsxs("button",{className:"roadmaps-view__suggest-btn",onClick:()=>{Be?.()},disabled:Q??!1,title:"Generate feature suggestions with AI","aria-label":"Generate feature suggestions","data-testid":`generate-features-${l.id}`,children:[e.jsx(ut,{size:12}),e.jsx("span",{children:Q?"Generating...":"AI Suggestions"})]})]}),e.jsxs("div",{className:Ge,onDragOver:h=>{h.preventDefault(),h.dataTransfer.dropEffect="move",h.dataTransfer.getData("text/plain")?.startsWith("feature:")&&Me()},onDrop:h=>{h.preventDefault();const $=h.dataTransfer.getData("text/plain");$?.startsWith("feature:")&&De($.split(":")[1],n.length)},onDragLeave:Y,children:[n.length===0?e.jsx("p",{className:"roadmaps-view__empty-features",children:"No features yet."}):n.map((h,$)=>{const H=y?.featureId===h.id,xe=oe(h.id),Ve=D=>{D.key==="Enter"?(D.preventDefault(),y&&W({title:y.value})):D.key==="Escape"&&z()},Re=["roadmaps-view__feature-item",xe?"roadmaps-view__feature-item--dragging":"",X&&B===$?"roadmaps-view__feature-item--drop-before":"",X&&B===$+1?"roadmaps-view__feature-item--drop-after":""].filter(Boolean).join(" ");return e.jsx("div",{className:Re,draggable:!H,onDragStart:D=>{H||(Fe(h.id,l.id),D.dataTransfer.setData("text/plain",`feature:${h.id}`),D.dataTransfer.effectAllowed="move")},onDragEnd:le,onDragOver:D=>{if(D.preventDefault(),D.stopPropagation(),D.dataTransfer.dropEffect="move",D.dataTransfer.getData("text/plain")?.startsWith("feature:")){const ee=D.currentTarget.getBoundingClientRect(),q=ee.top+ee.height/2,we=D.clientY<q?"before":"after";P(h.id,we)}},onDrop:D=>{D.preventDefault(),D.stopPropagation();const G=D.dataTransfer.getData("text/plain");if(G?.startsWith("feature:")){const ee=G.split(":")[1],q=D.currentTarget.getBoundingClientRect(),we=q.top+q.height/2,ce=D.clientY<we?"before":"after";let Ie=$;ce==="after"&&(Ie=$+1),De(ee,Ie)}},onDragLeave:Y,"data-testid":`feature-item-${h.id}`,children:H?e.jsx("div",{className:"roadmaps-view__inline-edit roadmaps-view__inline-edit--compact",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:y.value,onChange:()=>{},onKeyDown:Ve,placeholder:"Feature title",autoFocus:!0,"data-testid":`feature-title-input-${h.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>W({title:y.value}),"aria-label":"Save feature title",title:"Save",children:e.jsx(me,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:z,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(ae,{size:14})})]})}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsxs("div",{className:"roadmaps-view__feature-content",children:[e.jsx("span",{className:"roadmaps-view__feature-title",children:h.title}),h.description&&e.jsx("p",{className:"roadmaps-view__feature-desc",children:h.description})]}),e.jsxs("div",{className:"roadmaps-view__feature-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>C(h.id),title:"Edit feature","aria-label":"Edit feature","data-testid":`feature-edit-${h.id}`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>S(h.id),title:"Delete feature","aria-label":"Delete feature","data-testid":`feature-delete-${h.id}`,children:e.jsx(Le,{size:12})})]})]})},h.id)}),F&&F.length>0&&e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h4",{className:"roadmap-suggestion-title",children:"AI Feature Suggestions"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-accept-all-btn",onClick:()=>He?.(),title:"Accept all suggestions","aria-label":"Accept all","data-testid":`accept-all-features-${l.id}`,children:"Accept All"}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:()=>M?.(),title:"Clear suggestions","aria-label":"Clear","data-testid":`clear-features-${l.id}`,children:"Clear"})]})]}),e.jsx("div",{className:"roadmap-suggestion-list",children:F.map(h=>e.jsx(ea,{suggestion:h,onUpdateDraft:$=>fe?.(l.id,h.id,$),onAccept:()=>{v?.(l.id,h.id)},testIdPrefix:`feature-suggestion-${l.id}`},h.id))})]})]})]})}function ea({suggestion:l,onUpdateDraft:n,onAccept:j,testIdPrefix:f}){const[b,C]=a.useState(!1),[S,m]=a.useState(l.title),[I,E]=a.useState(l.description||""),_=()=>{m(l.title),E(l.description||""),C(!0)},y=()=>{n({title:S.trim(),description:I.trim()||void 0}),C(!1)},re=()=>{m(l.title),E(l.description||""),C(!1)},z=()=>{l.title.trim()&&j()},W=l.title.trim().length>0;return b?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:A=>m(A.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:I,onChange:A=>E(A.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(me,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:re,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(ae,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:_,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:z,disabled:!W,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(me,{size:12})})]})]})}function dt({suggestion:l,onUpdateDraft:n,onAccept:j,testIdPrefix:f}){const[b,C]=a.useState(!1),[S,m]=a.useState(l.title),[I,E]=a.useState(l.description||""),_=()=>{m(l.title),E(l.description||""),C(!0)},y=()=>{n({title:S.trim(),description:I.trim()||void 0}),C(!1)},re=()=>{m(l.title),E(l.description||""),C(!1)},z=()=>{l.title.trim()&&j()},W=l.title.trim().length>0;return b?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:A=>m(A.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:I,onChange:A=>E(A.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(me,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:re,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(ae,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:_,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:z,disabled:!W,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(me,{size:12})})]})]})}function pt({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form","data-testid":"create-roadmap-form",children:e.jsxs("form",{onSubmit:S,children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Roadmap title",autoFocus:!0,"data-testid":"create-roadmap-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Roadmap description (optional)",rows:2,"data-testid":"create-roadmap-description"}),e.jsxs("div",{className:"roadmaps-view__create-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__btn roadmaps-view__btn--primary",disabled:!j.trim(),"data-testid":"create-roadmap-submit",children:"Create"}),e.jsx("button",{type:"button",className:"roadmaps-view__btn",onClick:n,"data-testid":"create-roadmap-cancel",children:"Cancel"})]})]})})}function ta({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-milestone-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":"create-milestone-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-milestone-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!j.trim(),"aria-label":"Save milestone",title:"Save","data-testid":"create-milestone-submit",children:e.jsx(me,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-milestone-cancel",children:e.jsx(ae,{size:14})})]})]})})}function aa({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-feature-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":"create-feature-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-feature-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!j.trim(),"aria-label":"Save feature",title:"Save","data-testid":"create-feature-submit",children:e.jsx(me,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-feature-cancel",children:e.jsx(ae,{size:14})})]})]})})}function oa({projectId:l,addToast:n}){const j=Pt()==="mobile",{roadmaps:f,selectedRoadmapId:b,selectedRoadmap:C,milestones:S,featuresByMilestoneId:m,loading:I,error:E,createRoadmap:_,updateRoadmap:y,deleteRoadmap:re,selectRoadmap:z,createMilestone:W,updateMilestone:A,deleteMilestone:ke,createFeature:se,updateFeature:ge,deleteFeature:ne,reorderMilestones:Oe,reorderFeatures:ie,moveFeature:he,milestoneSuggestions:R,isGeneratingSuggestions:J,generateMilestoneSuggestions:oe,updateMilestoneSuggestionDraft:X,acceptMilestoneSuggestion:B,acceptAllMilestoneSuggestions:Fe,clearMilestoneSuggestions:le,featureSuggestionsByMilestoneId:P,isGeneratingFeatureSuggestions:De,generateFeatureSuggestions:Y,updateFeatureSuggestionDraft:Me,acceptFeatureSuggestion:F,acceptAllFeatureSuggestions:Q,clearFeatureSuggestions:Be,handoffPayload:v,isFetchingHandoff:He,handoffError:fe,fetchHandoff:M,clearHandoff:Z}=Yt({projectId:l}),[be,N]=a.useState(!1),[ve,Ge]=a.useState(null),[h,$]=a.useState(""),[H,xe]=a.useState(""),[Ve,Re]=a.useState(!1),D=a.useRef(null);a.useEffect(()=>{D.current!==null&&D.current!==b&&Re(!1),D.current=b},[b]);const[G,ee]=a.useState({roadmapId:null,field:null,value:""}),[q,we]=a.useState({milestoneId:null,field:null,value:""}),[ce,Ie]=a.useState({featureId:null,field:null,value:""}),[de,L]=a.useState({type:null,parentId:void 0,title:"",description:""}),[qe,Te]=a.useState(!1),[je,Pe]=a.useState({draggingId:null,dropTargetId:null,dropPosition:null}),Je=a.useCallback(t=>{Pe(u=>({...u,draggingId:t}))},[]),_e=a.useCallback(()=>{Pe({draggingId:null,dropTargetId:null,dropPosition:null})},[]),Xe=a.useCallback(t=>{Pe(u=>u.draggingId===t?u:{...u,dropTargetId:t,dropPosition:null})},[]),[ue,$e]=a.useState({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}),Qe=a.useCallback((t,u)=>{$e(w=>({...w,draggingId:t,draggingMilestoneId:u}))},[]),pe=a.useCallback(()=>{$e({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null})},[]),r=a.useCallback((t,u)=>{$e(w=>{if(w.draggingId===t)return w;const T=(m[w.draggingMilestoneId||""]||[]).findIndex(Ne=>Ne.id===t);let K;return u==="before"?K=T:K=T+1,{...w,dropTargetMilestoneId:w.draggingMilestoneId,dropTargetIndex:K,dropPosition:u}})},[m]),c=a.useCallback(()=>{$e(t=>({...t,dropTargetMilestoneId:t.draggingMilestoneId,dropTargetIndex:(m[t.draggingMilestoneId||""]||[]).length}))},[m]),i=a.useCallback(async(t,u)=>{const{draggingMilestoneId:w,dropTargetMilestoneId:O}=ue;if(!w){pe();return}const T=O||w,K=m[w]||[],Ne=K.find(Se=>Se.id===t);if(!Ne){pe();return}if(w!==T){if(w===T){pe();return}try{await he(t,T,u,{onError:Se=>{n(`Failed to move feature: ${Se.message}`,"error")}})}catch{}}else{const Se=[...K],yt=Se.findIndex(ze=>ze.id===t);Se.splice(yt,1),Se.splice(u,0,Ne);const ct=Se.map(ze=>ze.id),Nt=K.map(ze=>ze.id);if(ct.join(",")===Nt.join(",")){pe();return}try{await ie(w,ct,{onError:ze=>{n(`Failed to reorder features: ${ze.message}`,"error")}})}catch{}}pe()},[ue,m,ie,he,n,pe]),s=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),w=t.clientX,O=t.clientY;(w<u.left||w>u.right||O<u.top||O>u.bottom)&&$e(T=>({...T,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}))},[]),d=a.useCallback(t=>ue.draggingId===t,[ue.draggingId]),o=a.useCallback(async t=>{const{draggingId:u}=je;if(!u||u===t){_e();return}const w=S.map(Ne=>Ne.id),O=w.indexOf(u),T=w.indexOf(t);if(O===-1||T===-1){_e();return}const K=[...w];if(K.splice(O,1),K.splice(T,0,u),K.join(",")===w.join(",")){_e();return}try{await Oe(b,K,{onError:Ne=>{n(`Failed to reorder milestones: ${Ne.message}`,"error")}})}catch{}_e()},[je,S,b,Oe,n,_e]),g=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),w=t.clientX,O=t.clientY;(w<u.left||w>u.right||O<u.top||O>u.bottom)&&Pe(T=>({...T,dropTargetId:null,dropPosition:null}))},[]),p=a.useCallback(t=>{z(t.id),ee({roadmapId:t.id,field:"title",value:t.title})},[z]),x=a.useCallback(()=>{ee({roadmapId:null,field:null,value:""})},[]),V=a.useCallback(async t=>{if(G.roadmapId)try{await y(G.roadmapId,t,{onError:u=>n(u.message,"error")}),x()}catch{}},[G.roadmapId,y,x,n]),te=a.useCallback(async t=>{if(window.confirm("Delete this roadmap? This cannot be undone."))try{await re(t,{onError:u=>n(u.message,"error")}),n("Roadmap deleted","success")}catch{}},[re,n]),Ce=a.useCallback((t,u)=>{Ge(t),$(u),N(!0),Z()},[Z]),Ke=a.useCallback(()=>{N(!1),Ge(null),$(""),Z()},[Z]),k=a.useCallback(()=>{ve&&M(ve,{onError:t=>n(`Failed to load handoff: ${t.message}`,"error")})},[ve,M,n]),U=a.useCallback(()=>{if(v){const t=JSON.stringify(v,null,2);navigator.clipboard.writeText(t).then(()=>{n("Handoff data copied to clipboard","success")}).catch(()=>{n("Failed to copy to clipboard","error")})}},[v,n]),Ue=a.useCallback(async t=>{try{await _(t,{onError:u=>n(u.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Roadmap created","success")}catch{}},[_,n]),We=a.useCallback(t=>{we({milestoneId:t.id,field:"title",value:t.title})},[]),Ze=a.useCallback(()=>{we({milestoneId:null,field:null,value:""})},[]),mt=a.useCallback(async t=>{if(q.milestoneId)try{await A(q.milestoneId,t,{onError:u=>n(u.message,"error")}),Ze()}catch{}},[q.milestoneId,A,Ze,n]),gt=a.useCallback(async t=>{if(window.confirm("Delete this milestone and all its features?"))try{await ke(t,{onError:u=>n(u.message,"error")}),n("Milestone deleted","success")}catch{}},[ke,n]),ht=a.useCallback(async t=>{try{await W(t,{onError:u=>n(u.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Milestone created","success")}catch{}},[W,n]),st=a.useCallback((t,u,w)=>{Ie({featureId:t,field:"title",value:u})},[]),et=a.useCallback(()=>{Ie({featureId:null,field:null,value:""})},[]),ft=a.useCallback(async t=>{if(ce.featureId)try{await ge(ce.featureId,t,{onError:u=>n(u.message,"error")}),et()}catch{}},[ce.featureId,ge,et,n]),bt=a.useCallback(async t=>{if(window.confirm("Delete this feature?"))try{await ne(t,{onError:u=>n(u.message,"error")}),n("Feature deleted","success")}catch{}},[ne,n]),nt=a.useCallback(async()=>{if(H.trim())try{await oe(H,5,{onError:t=>n(t.message,"error")})}catch{}},[H,oe,n]),it=a.useCallback(async t=>{try{await B(t,{onError:u=>n(u.message,"error")}),n("Milestone added","success")}catch{}},[B,n]),ot=a.useCallback(async()=>{try{await Fe({onError:t=>n(t.message,"error")}),n(`${R.length} milestones added`,"success"),xe("")}catch{}},[Fe,R.length,n]),lt=a.useCallback(()=>{le(),xe("")},[le]),vt=a.useCallback(async t=>{try{await Y(t,{count:5},{onError:u=>n(u.message,"error")})}catch{}},[Y,n]),xt=a.useCallback(async(t,u)=>{try{await F(t,u,{onError:w=>n(w.message,"error")}),n("Feature added","success")}catch{}},[F,n]),wt=a.useCallback((t,u,w)=>{Me(t,u,w)},[Me]),jt=a.useCallback(async t=>{const u=P[t]||[];try{await Q(t,{onError:w=>n(w.message,"error")}),n(`${u.length} features added`,"success")}catch{}},[Q,P,n]),_t=a.useCallback(t=>{Be(t)},[Be]),Ct=a.useCallback(async(t,u)=>{try{await se(t,u,{onError:w=>n(w.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Feature created","success")}catch{}},[se,n]),ye=b;return I&&f.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--loading",children:e.jsx("div",{className:"roadmaps-view__loading-state",children:"Loading roadmaps..."})}):E&&f.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--error",children:e.jsxs("div",{className:"roadmaps-view__error-state",children:[e.jsx("p",{children:"Failed to load roadmaps"}),e.jsx("p",{className:"roadmaps-view__error-msg",children:E.message})]})}):e.jsxs("div",{className:"roadmaps-view",children:[j&&!ye&&e.jsx(Xt,{roadmaps:f,selectedRoadmapId:ye,onSelect:t=>z(t),onCreate:()=>Te(!0),onEdit:p,onDelete:te,onExport:t=>Ce(t.id,t.title),showCreateForm:qe,onCancelCreate:()=>Te(!1),onSaveCreate:async t=>{await Ue(t),Te(!1)}}),!j&&e.jsxs("aside",{className:"roadmaps-view__sidebar","aria-label":"Roadmaps",children:[e.jsxs("div",{className:"roadmaps-view__sidebar-header",children:[e.jsx("h2",{className:"roadmaps-view__sidebar-title",children:"Roadmaps"}),e.jsx("button",{className:"roadmaps-view__add-btn",onClick:()=>L({type:"roadmap",title:"",description:""}),title:"Create roadmap","aria-label":"Create roadmap","data-testid":"create-roadmap-btn",children:e.jsx(Ae,{size:16})})]}),de.type==="roadmap"&&e.jsx(pt,{onSave:Ue,onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})}),e.jsx("div",{className:"roadmaps-view__sidebar-list",children:f.length===0?e.jsx("p",{className:"roadmaps-view__empty-sidebar",children:"No roadmaps yet. Click + to create one."}):f.map(t=>e.jsx(Jt,{roadmap:t,isSelected:t.id===ye,onSelect:()=>z(t.id),onEdit:()=>p(t),onDelete:()=>te(t.id),onExport:()=>Ce(t.id,t.title)},t.id))})]}),e.jsxs("main",{className:"roadmaps-view__main","aria-label":"Roadmap content",children:[j&&ye&&e.jsx(Qt,{roadmapTitle:C?.title||"Untitled Roadmap",onBack:()=>z(null),onEdit:()=>{C&&p(C)},onDelete:()=>te(ye),onCreate:()=>Te(!0)}),ye?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"roadmaps-view__roadmap-header",children:G.roadmapId===ye?e.jsx("div",{className:"roadmaps-view__inline-edit",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input roadmaps-view__inline-input--large",value:G.value,onChange:t=>ee(u=>({...u,value:t.target.value})),onKeyDown:t=>{t.key==="Enter"?V({title:G.value}):t.key==="Escape"&&x()},placeholder:"Roadmap title",autoFocus:!0,"data-testid":"roadmap-title-input"}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>V({title:G.value}),"aria-label":"Save",title:"Save",children:e.jsx(me,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:x,"aria-label":"Cancel",title:"Cancel",children:e.jsx(ae,{size:16})})]})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__roadmap-title-row",children:[e.jsx("h1",{className:"roadmaps-view__roadmap-title",children:C?.title||"Untitled Roadmap"}),e.jsxs("div",{className:"roadmaps-view__roadmap-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>{C&&p(C)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"edit-roadmap-btn",children:e.jsx(Ee,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>te(ye),title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"delete-roadmap-btn",children:e.jsx(Le,{size:16})})]})]}),C?.description&&e.jsx("p",{className:"roadmaps-view__roadmap-desc",children:C.description})]})}),j?Ve?e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"}),e.jsx("button",{className:"roadmap-suggestion-collapse-btn",onClick:()=>Re(!1),"aria-label":"Collapse suggestion panel","data-testid":"collapse-suggestion-panel-btn",children:e.jsx(Lt,{size:16})})]}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:H,onChange:t=>xe(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:J||!b,"data-testid":"goal-prompt-input",autoFocus:!0}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:nt,disabled:!H.trim()||J||!b,"data-testid":"generate-suggestions-btn",children:J?"Generating...":"Generate Milestones"}),R.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:ot,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",R.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:lt,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(ae,{size:14})})]})]})]}),R.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:R.map(t=>e.jsx(dt,{suggestion:t,onUpdateDraft:u=>X(t.id,u),onAccept:()=>it(t.id),testIdPrefix:"suggestion"},t.id))})]}):e.jsx("div",{className:"roadmap-suggestion-section",children:e.jsxs("button",{className:"roadmap-suggestion-expand-btn",onClick:()=>Re(!0),disabled:!b,"data-testid":"expand-suggestion-panel-btn",children:[e.jsx(ut,{size:16}),"Generate Milestone Ideas"]})}):e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsx("div",{className:"roadmap-suggestion-header",children:e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"})}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:H,onChange:t=>xe(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:J||!b,"data-testid":"goal-prompt-input"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:nt,disabled:!H.trim()||J||!b,"data-testid":"generate-suggestions-btn",children:J?"Generating...":"Generate Milestones"}),R.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:ot,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",R.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:lt,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(ae,{size:14})})]})]})]}),R.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:R.map(t=>e.jsx(dt,{suggestion:t,onUpdateDraft:u=>X(t.id,u),onAccept:()=>it(t.id),testIdPrefix:"suggestion"},t.id))})]}),e.jsxs("div",{className:"roadmaps-view__milestone-lanes",children:[de.type==="milestone"&&e.jsx(ta,{onSave:ht,onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})}),S.length===0&&de.type!=="milestone"?e.jsxs("div",{className:"roadmaps-view__empty-milestones",children:[e.jsx("p",{children:"This roadmap has no milestones."}),e.jsxs("button",{className:"roadmaps-view__add-milestone-btn",onClick:()=>L({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn-empty",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]})]}):e.jsxs(e.Fragment,{children:[de.type!=="milestone"&&e.jsxs("button",{className:"roadmaps-view__add-milestone-fab",onClick:()=>L({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]}),S.map(t=>e.jsx(Zt,{milestone:t,features:m[t.id]||[],onEditMilestone:()=>We(t),onDeleteMilestone:()=>gt(t.id),onAddFeature:()=>L({type:"feature",parentId:t.id,title:"",description:""}),onEditFeature:u=>{const w=m[t.id]?.find(O=>O.id===u);w&&st(u,w.title,w.description)},onDeleteFeature:bt,milestoneEdit:q,onStartMilestoneEdit:()=>We(t),onCancelMilestoneEdit:Ze,onSaveMilestoneEdit:mt,featureEdit:ce,onStartFeatureEdit:st,onCancelFeatureEdit:et,onSaveFeatureEdit:ft,projectId:l,addToast:n,isMilestoneDragging:je.draggingId===t.id,isMilestoneDropTarget:je.dropTargetId===t.id,milestoneDropPosition:je.dropTargetId===t.id?je.dropPosition:null,onMilestoneDragStart:Je,onMilestoneDragEnd:_e,onMilestoneDragOver:Xe,onMilestoneDrop:o,onMilestoneDragLeave:g,isFeatureDragging:d,isFeatureDropTarget:ue.dropTargetMilestoneId===t.id,featureDropIndex:ue.dropTargetMilestoneId===t.id?ue.dropTargetIndex:null,onFeatureDragStart:Qe,onFeatureDragEnd:pe,onFeatureDragOver:r,onFeatureDrop:i,onFeatureDragLeave:s,onFeatureDropOnMilestone:c,featureSuggestions:P[t.id],isGeneratingFeatureSuggestions:De(t.id),onGenerateFeatureSuggestions:()=>vt(t.id),onAcceptFeatureSuggestion:u=>xt(t.id,u),onAcceptAllFeatureSuggestions:()=>jt(t.id),onUpdateFeatureSuggestionDraft:(u,w,O)=>wt(u,w,O),onClearFeatureSuggestions:()=>_t(t.id)},t.id))]})]})]}):e.jsx("div",{className:"roadmaps-view__empty-main",children:e.jsx("p",{children:"Select a roadmap from the sidebar to view its milestones."})})]}),de.type==="feature"&&de.parentId&&e.jsx("div",{className:"roadmaps-view__feature-create-overlay",children:e.jsx(aa,{onSave:t=>Ct(de.parentId,t),onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})})}),e.jsx(qt,{isOpen:be,onClose:Ke,roadmapId:ve||"",roadmapTitle:h,handoffPayload:v,isLoading:He,error:fe,onFetchHandoff:k,onCopyToClipboard:U})]})}export{oa as RoadmapsView};
|
|
6
|
+
*/const Kt=[["path",{d:"M12 2v4",key:"3427ic"}],["path",{d:"m16.2 7.8 2.9-2.9",key:"r700ao"}],["path",{d:"M18 12h4",key:"wj9ykh"}],["path",{d:"m16.2 16.2 2.9 2.9",key:"1bxg5t"}],["path",{d:"M12 18v4",key:"jadmvz"}],["path",{d:"m4.9 19.1 2.9-2.9",key:"bwix9q"}],["path",{d:"M2 12h4",key:"j09sii"}],["path",{d:"m4.9 4.9 2.9 2.9",key:"giyufr"}]],Wt=St("loader",Kt);function Yt(l){const n=l?.projectId,[j,f]=a.useState([]),[b,C]=a.useState(null),[S,m]=a.useState(null),[I,E]=a.useState([]),[_,y]=a.useState({}),[re,z]=a.useState(!1),[W,A]=a.useState(null),[ke,se]=a.useState(null),[ge,ne]=a.useState(!1),[Oe,ie]=a.useState(null),[he,R]=a.useState([]),[J,oe]=a.useState(!1),[X,B]=a.useState({}),[Fe,le]=a.useState({}),P=a.useRef(X),De=a.useRef(Fe),Y=a.useRef(he);P.current=X,De.current=Fe,Y.current=he;const Me=a.useRef(n),F=a.useRef(0),Q=a.useRef(0),Be=a.useRef(j),v=a.useRef(b),He=a.useRef(I),fe=a.useRef(_),M=a.useRef(n),Z=a.useRef(ke);Be.current=j,v.current=b,He.current=I,fe.current=_,M.current=n,Z.current=ke,a.useEffect(()=>{Me.current!==n&&(Me.current=n,F.current++,C(null),m(null),E([]),y({}),se(null),ie(null),R([]),oe(!1),B({}),le({}))},[n]);const be=a.useCallback(async()=>{z(!0),A(null);try{const r=await Et(n);f(r)}catch(r){A(r instanceof Error?r:new Error("Failed to fetch roadmaps"))}finally{z(!1)}},[n]),N=a.useCallback(async r=>{try{const c=await kt(r,n);m(c),E(c.milestones||[]);const i={};for(const s of c.milestones||[])i[s.id]=s.features||[];y(i)}catch(c){A(c instanceof Error?c:new Error("Failed to fetch roadmap"))}},[n]);a.useEffect(()=>{be()},[be]),a.useEffect(()=>{b?N(b):(m(null),E([]),y({}))},[b,N]);const ve=a.useCallback(async(r,c)=>{try{const i=await Ft(r,M.current);f(s=>[...s,i]),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to create roadmap");throw c?.onError?.(s),s}},[]),Te=a.useCallback(async(r,c,i)=>{try{const s=await Dt(r,c,M.current);f(d=>d.map(o=>o.id===r?s:o)),v.current===r&&m(d=>d?{...d,...s}:null),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update roadmap");throw i?.onError?.(d),d}},[]),h=a.useCallback(async(r,c)=>{try{await Mt(r,M.current),f(i=>i.filter(s=>s.id!==r)),v.current===r&&(C(null),m(null),E([]),y({})),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete roadmap");throw c?.onError?.(s),s}},[]),$=a.useCallback(r=>{C(r)},[]),H=a.useCallback(async(r,c)=>{const i=v.current;if(!i){const s=new Error("No roadmap selected");throw c?.onError?.(s),s}try{const s=await tt(i,r,M.current);E(d=>[...d,s]),y(d=>({...d,[s.id]:[]})),v.current&&N(v.current),c?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create milestone");throw c?.onError?.(d),d}},[N]),xe=a.useCallback(async(r,c,i)=>{try{const s=await Rt(r,c,M.current);E(d=>d.map(o=>o.id===r?s:o)),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update milestone");throw i?.onError?.(d),d}},[N]),Ve=a.useCallback(async(r,c)=>{try{await It(r,M.current),E(i=>i.filter(s=>s.id!==r)),y(i=>{const s={...i};return delete s[r],s}),v.current&&N(v.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete milestone");throw c?.onError?.(s),s}},[N]),Re=a.useCallback(async(r,c,i)=>{try{const s=await at(r,c,M.current);y(d=>({...d,[r]:[...d[r]||[],s]})),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to create feature");throw i?.onError?.(d),d}},[N]),D=a.useCallback(async(r,c,i)=>{try{const s=await $t(r,c,M.current);y(d=>{const o={};for(const[g,p]of Object.entries(d))o[g]=p.map(x=>x.id===r?s:x);return o}),v.current&&N(v.current),i?.onSuccess?.()}catch(s){const d=s instanceof Error?s:new Error("Failed to update feature");throw i?.onError?.(d),d}},[N]),T=a.useCallback(async(r,c)=>{try{await zt(r,M.current),y(i=>{const s={};for(const[d,o]of Object.entries(i))s[d]=o.filter(g=>g.id!==r);return s}),v.current&&N(v.current),c?.onSuccess?.()}catch(i){const s=i instanceof Error?i:new Error("Failed to delete feature");throw c?.onError?.(s),s}},[N]),ee=a.useCallback(async(r,c,i)=>{const s=He.current,d=c.map(o=>s.find(g=>g.id===o)).filter(o=>o!==void 0).map((o,g)=>({...o,orderIndex:g}));E(d);try{await At(r,c,M.current),v.current&&N(v.current),i?.onSuccess?.()}catch(o){E(s);const g=o instanceof Error?o:new Error("Failed to reorder milestones");throw i?.onError?.(g),g}},[N]),q=a.useCallback(async(r,c,i)=>{const s=fe.current[r]||[],d=s.map(p=>p.id);if(JSON.stringify(d)===JSON.stringify(c)){i?.onSuccess?.();return}const o=fe.current,g=c.map(p=>s.find(x=>x.id===p)).filter(p=>p!==void 0).map((p,x)=>({...p,orderIndex:x}));y(p=>({...p,[r]:g}));try{await Ot(r,c,M.current),v.current&&N(v.current),i?.onSuccess?.()}catch(p){y(o);const x=p instanceof Error?p:new Error("Failed to reorder features");throw i?.onError?.(x),x}},[N]),we=a.useCallback(async(r,c,i,s)=>{const d=fe.current;let o=null;for(const[k,U]of Object.entries(d))if(U.some(Ue=>Ue.id===r)){o=k;break}if(!o){const k=new Error("Feature not found");throw s?.onError?.(k),k}if(o===c){const k=d[o]||[],U=Math.max(0,Math.min(i,k.length-1));if(k.findIndex(We=>We.id===r)===U){s?.onSuccess?.();return}}const g=d[o]||[],p=d[c]||[],x=g.find(k=>k.id===r);if(!x){const k=new Error("Feature not found");throw s?.onError?.(k),k}const V=g.filter(k=>k.id!==r).map((k,U)=>({...k,orderIndex:U})),te={...x,milestoneId:c,orderIndex:i},Ce=[...p];Ce.splice(i,0,te);const Ke=Ce.map((k,U)=>({...k,orderIndex:U}));y(o===c?k=>({...k,[o]:Ke}):k=>({...k,[o]:V,[c]:Ke}));try{await Bt(r,c,i,n),v.current&&N(v.current),s?.onSuccess?.()}catch(k){y(d);const U=k instanceof Error?k:new Error("Failed to move feature");throw s?.onError?.(U),U}},[N,n]);function ce(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`draft-${Date.now()}-${Math.random().toString(36).slice(2,11)}`}const Ie=a.useCallback(async(r,c=5,i)=>{const s=v.current;if(!s){const g=new Error("No roadmap selected");throw i?.onError?.(g),g}const d=F.current,o=M.current;oe(!0);try{const g=await Ht(s,r,c,o);if(F.current!==d)return;const p=g.suggestions.map(x=>({id:ce(),title:x.title,description:x.description}));R(p),i?.onSuccess?.()}catch(g){if(F.current!==d)return;const p=g instanceof Error?g:new Error("Failed to generate suggestions");throw i?.onError?.(p),p}finally{F.current===d&&oe(!1)}},[]),de=a.useCallback((r,c)=>{const s=Y.current.map(d=>d.id===r?{...d,...c}:d);Y.current=s,R(d=>d.map(o=>o.id===r?{...o,...c}:o))},[]),L=a.useCallback(async(r,c)=>{const i=v.current;if(!i){const p=new Error("No roadmap selected");throw c?.onError?.(p),p}const s=F.current,d=Y.current,o=d.findIndex(p=>p.id===r);if(o===-1){const p=new Error("Suggestion draft not found");throw c?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw c?.onError?.(p),p}R(p=>p.filter(x=>x.id!==r));try{if(await tt(i,{title:g.title,description:g.description},M.current),F.current!==s){R(p=>{const x=[...p];return x.splice(o,0,g),x});return}v.current&&N(v.current),c?.onSuccess?.()}catch(p){R(V=>{const te=[...V];return te.splice(o,0,g),te});const x=p instanceof Error?p:new Error("Failed to accept suggestion");throw c?.onError?.(x),x}},[N]),qe=a.useCallback(async r=>{const c=v.current;if(!c){const o=new Error("No roadmap selected");throw r?.onError?.(o),o}const i=[...Y.current];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw r?.onError?.(o),o}R([]);const d=F.current;for(let o=0;o<i.length&&F.current===d;o++){const g=i[o];try{await tt(c,{title:g.title,description:g.description},M.current)}catch(p){const x=p instanceof Error?p:new Error("Failed to accept all suggestions");throw r?.onError?.(x),x}}F.current===d&&(v.current&&N(v.current),r?.onSuccess?.())},[N]),Ge=a.useCallback(r=>De.current[r]??!1,[]),je=a.useCallback(async(r,c,i)=>{const s=F.current,d=M.current;le(o=>({...o,[r]:!0}));try{const o=await Tt(r,c,d);if(F.current!==s)return;const g=o.suggestions.map(p=>({id:ce(),title:p.title,description:p.description}));B(p=>({...p,[r]:g})),i?.onSuccess?.()}catch(o){if(F.current!==s)return;const g=o instanceof Error?o:new Error("Failed to generate feature suggestions");throw i?.onError?.(g),g}finally{F.current===s&&le(o=>({...o,[r]:!1}))}},[]),Pe=a.useCallback((r,c,i)=>{const d=(P.current[r]||[]).map(o=>o.id===c?{...o,...i}:o);P.current={...P.current,[r]:d},B(o=>({...o,[r]:o[r]?.map(g=>g.id===c?{...g,...i}:g)||[]}))},[]),Je=a.useCallback(async(r,c,i)=>{const s=F.current,d=P.current[r]||[],o=d.findIndex(p=>p.id===c);if(o===-1){const p=new Error("Suggestion draft not found");throw i?.onError?.(p),p}const g=d[o];if(!g.title.trim()){const p=new Error("Title cannot be empty");throw i?.onError?.(p),p}B(p=>({...p,[r]:p[r]?.filter(x=>x.id!==c)||[]}));try{if(await at(r,{title:g.title,description:g.description},M.current),F.current!==s){B(p=>{const V=[...p[r]||[]];return V.splice(o,0,g),{...p,[r]:V}});return}v.current&&N(v.current),i?.onSuccess?.()}catch(p){B(V=>{const Ce=[...V[r]||[]];return Ce.splice(o,0,g),{...V,[r]:Ce}});const x=p instanceof Error?p:new Error("Failed to accept suggestion");throw i?.onError?.(x),x}},[N]),_e=a.useCallback(async(r,c)=>{const i=[...P.current[r]||[]];if(i.length===0)return;const s=i.findIndex(o=>!o.title.trim());if(s!==-1){const o=new Error(`Title cannot be empty at position ${s+1}`);throw c?.onError?.(o),o}B(o=>({...o,[r]:[]}));const d=F.current;for(let o=0;o<i.length&&F.current===d;o++){const g=i[o];try{await at(r,{title:g.title,description:g.description},M.current)}catch(p){const x=p instanceof Error?p:new Error("Failed to accept all suggestions");throw c?.onError?.(x),x}}F.current===d&&(v.current&&N(v.current),c?.onSuccess?.())},[N]),Xe=a.useCallback(()=>{R([]),oe(!1)},[]),ue=a.useCallback(r=>{B(c=>{const i={...c};return delete i[r],i}),le(c=>{const i={...c};return delete i[r],i})},[]),$e=a.useCallback(async(r,c)=>{const i=++Q.current,s=n;ne(!0),ie(null);try{const d=await Gt(r,s);if(Q.current!==i||n!==s)return;se(d),c?.onSuccess?.()}catch(d){if(Q.current!==i||n!==s)return;const o=d instanceof Error?d:new Error(String(d));ie(o),se(null),c?.onError?.(o)}finally{Q.current===i&&ne(!1)}},[n]),Qe=a.useCallback(()=>{se(null),ie(null),ne(!1)},[]),pe=a.useCallback(async()=>{await be(),v.current&&await N(v.current)},[be,N]);return{roadmaps:j,selectedRoadmapId:b,selectedRoadmap:S,milestones:I,featuresByMilestoneId:_,loading:re,error:W,createRoadmap:ve,updateRoadmap:Te,deleteRoadmap:h,selectRoadmap:$,createMilestone:H,updateMilestone:xe,deleteMilestone:Ve,reorderMilestones:ee,createFeature:Re,updateFeature:D,deleteFeature:T,reorderFeatures:q,moveFeature:we,milestoneSuggestions:he,isGeneratingSuggestions:J,generateMilestoneSuggestions:Ie,updateMilestoneSuggestionDraft:de,acceptMilestoneSuggestion:L,acceptAllMilestoneSuggestions:qe,clearMilestoneSuggestions:Xe,featureSuggestionsByMilestoneId:X,isGeneratingFeatureSuggestions:Ge,generateFeatureSuggestions:je,updateFeatureSuggestionDraft:Pe,acceptFeatureSuggestion:Je,acceptAllFeatureSuggestions:_e,clearFeatureSuggestions:ue,handoffPayload:ke,isFetchingHandoff:ge,handoffError:Oe,fetchHandoff:$e,clearHandoff:Qe,refresh:pe}}function qt({isOpen:l,onClose:n,roadmapTitle:j,handoffPayload:f,isLoading:b,error:C,onFetchHandoff:S,onCopyToClipboard:m}){return l?e.jsx("div",{className:"modal-overlay open",onClick:n,role:"presentation",children:e.jsxs("div",{className:"modal modal-lg",onClick:I=>I.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":"handoff-modal-title",children:[e.jsxs("div",{className:"modal-header",children:[e.jsxs("h2",{id:"handoff-modal-title",children:["Export Roadmap: ",j]}),e.jsx("button",{className:"modal-close",onClick:n,"aria-label":"Close modal",children:e.jsx(ae,{size:18})})]}),e.jsxs("div",{className:"modal-body",children:[e.jsx("p",{className:"text-muted",style:{marginBottom:"var(--space-lg)"},children:"Export roadmap data for use in mission and task planning flows. This is a read-only export — no missions or tasks will be created."}),C&&e.jsxs("div",{className:"form-error",style:{marginBottom:"var(--space-lg)"},children:["Error loading handoff data: ",C.message]}),!f&&!b&&e.jsx("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:e.jsxs("button",{className:"btn btn-primary",onClick:S,children:[e.jsx(rt,{size:16,style:{marginRight:"var(--space-sm)"}}),"Load Handoff Data"]})}),b&&e.jsxs("div",{style:{textAlign:"center",padding:"var(--space-xl)"},children:[e.jsx(Wt,{size:24,className:"spin"}),e.jsx("p",{style:{marginTop:"var(--space-md)"},children:"Loading handoff data..."})]}),f&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsx("h3",{style:{marginBottom:"var(--space-sm)"},children:"Mission Planning Handoff"}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"200px",overflow:"auto"},children:JSON.stringify(f.mission,null,2)})})]}),e.jsxs("div",{style:{marginBottom:"var(--space-lg)"},children:[e.jsxs("h3",{style:{marginBottom:"var(--space-sm)"},children:["Feature Task Planning Handoffs (",f.features.length,")"]}),e.jsx("div",{className:"card",style:{padding:"var(--space-md)"},children:e.jsx("pre",{style:{whiteSpace:"pre-wrap",fontSize:"12px",maxHeight:"300px",overflow:"auto"},children:JSON.stringify(f.features,null,2)})})]})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("div",{className:"modal-actions-left",children:f&&e.jsxs("button",{className:"btn btn-sm",onClick:m,children:[e.jsx(Ut,{size:14,style:{marginRight:"var(--space-xs)"}}),"Copy to Clipboard"]})}),e.jsx("div",{className:"modal-actions-right",children:e.jsx("button",{className:"btn",onClick:n,children:"Close"})})]})]})}):null}function Jt({roadmap:l,isSelected:n,onSelect:j,onEdit:f,onDelete:b,onExport:C}){const S=_=>{_.key==="Enter"&&j()},m=_=>{_.stopPropagation(),f()},I=_=>{_.stopPropagation(),b()},E=_=>{_.stopPropagation(),C()};return e.jsxs("div",{className:`roadmaps-view__sidebar-item${n?" roadmaps-view__sidebar-item--active":""}`,onClick:j,onKeyDown:S,role:"button",tabIndex:0,"aria-selected":n,"data-testid":`roadmap-item-${l.id}`,children:[e.jsxs("div",{className:"roadmaps-view__sidebar-item-content",children:[e.jsx("div",{className:"roadmaps-view__sidebar-item-title",children:l.title}),l.description&&e.jsx("div",{className:"roadmaps-view__sidebar-item-desc",children:l.description})]}),e.jsxs("div",{className:"roadmaps-view__sidebar-item-actions",onClick:m,role:"presentation",children:[e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:E,role:"button",title:"Export roadmap","aria-label":"Export roadmap","data-testid":`roadmap-export-${l.id}`,tabIndex:0,children:e.jsx(rt,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn",onClick:m,role:"button",title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`roadmap-edit-${l.id}`,tabIndex:0,children:e.jsx(Ee,{size:14})}),e.jsx("span",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:I,role:"button",title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`roadmap-delete-${l.id}`,tabIndex:0,children:e.jsx(Le,{size:14})})]})]})}function Xt({roadmaps:l,selectedRoadmapId:n,onSelect:j,onCreate:f,onEdit:b,onDelete:C,onExport:S,showCreateForm:m,onCancelCreate:I,onSaveCreate:E}){return e.jsxs("div",{className:"roadmaps-view__mobile-list","data-testid":"roadmaps-view__mobile-list",children:[e.jsxs("div",{className:"roadmaps-view__mobile-list-header",children:[e.jsx("h2",{className:"roadmaps-view__mobile-list-title",children:"Roadmaps"}),!m&&e.jsx("button",{className:"roadmaps-view__mobile-add-btn",onClick:f,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-create-roadmap-btn",children:e.jsx(Ae,{size:18})})]}),m&&e.jsx("div",{className:"roadmaps-view__mobile-create-form",children:e.jsx(pt,{onSave:E,onCancel:I})}),l.length===0&&!m?e.jsxs("div",{className:"roadmaps-view__mobile-empty",children:[e.jsx("p",{children:"No roadmaps yet."}),e.jsxs("button",{className:"btn btn-primary btn-sm",onClick:f,children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Create Roadmap"})]})]}):e.jsx("div",{className:"roadmaps-view__mobile-list-items",children:l.map(_=>e.jsxs("div",{className:`roadmaps-view__mobile-item${_.id===n?" roadmaps-view__mobile-item--active":""}`,onClick:()=>j(_.id),role:"button",tabIndex:0,onKeyDown:y=>{y.key==="Enter"&&j(_.id)},"data-testid":`mobile-roadmap-item-${_.id}`,children:[e.jsxs("div",{className:"roadmaps-view__mobile-item-content",children:[e.jsx("span",{className:"roadmaps-view__mobile-item-title",children:_.title}),_.description&&e.jsx("span",{className:"roadmaps-view__mobile-item-desc",children:_.description})]}),e.jsxs("div",{className:"roadmaps-view__mobile-item-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),S(_)},title:"Export roadmap","aria-label":"Export roadmap","data-testid":`mobile-roadmap-export-${_.id}`,children:e.jsx(rt,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:y=>{y.stopPropagation(),b(_)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":`mobile-roadmap-edit-${_.id}`,children:e.jsx(Ee,{size:16})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:y=>{y.stopPropagation(),C(_.id)},title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":`mobile-roadmap-delete-${_.id}`,children:e.jsx(Le,{size:16})})]})]},_.id))})]})}function Qt({roadmapTitle:l,onBack:n,onEdit:j,onDelete:f,onCreate:b}){return e.jsxs("div",{className:"roadmaps-view__mobile-header","data-testid":"roadmaps-view__mobile-header",children:[e.jsx("button",{className:"roadmaps-view__mobile-back-btn",onClick:n,title:"Back to roadmap list","aria-label":"Back to roadmap list","data-testid":"mobile-back-btn",children:e.jsx(Vt,{size:20})}),e.jsx("h2",{className:"roadmaps-view__mobile-header-title",children:l}),e.jsxs("div",{className:"roadmaps-view__mobile-header-actions",children:[e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:b,title:"Create roadmap","aria-label":"Create roadmap","data-testid":"mobile-header-create-btn",children:e.jsx(Ae,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn",onClick:j,title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"mobile-header-edit-btn",children:e.jsx(Ee,{size:18})}),e.jsx("button",{className:"roadmaps-view__mobile-action-btn roadmaps-view__mobile-action-btn--danger",onClick:f,title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"mobile-header-delete-btn",children:e.jsx(Le,{size:18})})]})]})}function Zt({milestone:l,features:n,onEditMilestone:j,onDeleteMilestone:f,onAddFeature:b,onEditFeature:C,onDeleteFeature:S,milestoneEdit:m,onStartMilestoneEdit:I,onCancelMilestoneEdit:E,onSaveMilestoneEdit:_,featureEdit:y,onStartFeatureEdit:re,onCancelFeatureEdit:z,onSaveFeatureEdit:W,projectId:A,addToast:ke,isMilestoneDragging:se,isMilestoneDropTarget:ge,milestoneDropPosition:ne,onMilestoneDragStart:Oe,onMilestoneDragEnd:ie,onMilestoneDragOver:he,onMilestoneDrop:R,onMilestoneDragLeave:J,isFeatureDragging:oe,isFeatureDropTarget:X,featureDropIndex:B,onFeatureDragStart:Fe,onFeatureDragEnd:le,onFeatureDragOver:P,onFeatureDrop:De,onFeatureDragLeave:Y,onFeatureDropOnMilestone:Me,featureSuggestions:F,isGeneratingFeatureSuggestions:Q,onGenerateFeatureSuggestions:Be,onAcceptFeatureSuggestion:v,onAcceptAllFeatureSuggestions:He,onUpdateFeatureSuggestionDraft:fe,onClearFeatureSuggestions:M}){const Z=m?.milestoneId===l.id,be=h=>{h.key==="Enter"?(h.preventDefault(),m&&_({title:m.value})):h.key==="Escape"&&E()},N=h=>{h.key==="Escape"&&E()},ve=["roadmaps-view__milestone",se?"roadmaps-view__milestone--dragging":"",ge?"roadmaps-view__milestone--drop-target":"",ge&&ne==="before"?"roadmaps-view__milestone--drop-before":"",ge&&ne==="after"?"roadmaps-view__milestone--drop-after":""].filter(Boolean).join(" "),Te=["roadmaps-view__feature-list",X?"roadmaps-view__feature-list--drop-target":""].filter(Boolean).join(" ");return e.jsxs("div",{className:ve,draggable:!Z,onDragStart:h=>{Z||(Oe(l.id),h.dataTransfer.setData("text/plain",`milestone:${l.id}`),h.dataTransfer.effectAllowed="move")},onDragEnd:ie,onDragOver:h=>{h.dataTransfer.types.includes("text/plain")&&h.dataTransfer.types.includes("text/plain")&&(h.preventDefault(),h.dataTransfer.dropEffect="move",he(l.id))},onDrop:h=>{h.preventDefault(),h.dataTransfer.getData("text/plain")?.startsWith("feature:")||R(l.id)},onDragLeave:J,"data-testid":`milestone-card-${l.id}`,children:[e.jsx("div",{className:"roadmaps-view__milestone-header",children:Z?e.jsxs("div",{className:"roadmaps-view__inline-edit",children:[e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:m.value,onChange:()=>I(),onKeyDown:be,placeholder:"Milestone title",autoFocus:!0,"data-testid":`milestone-title-input-${l.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>_({title:m.value}),"aria-label":"Save milestone title",title:"Save",children:e.jsx(me,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:E,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(ae,{size:14})})]}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:m.field==="description"?m.value:l.description||"",onChange:()=>{},onKeyDown:N,placeholder:"Milestone description (optional)",rows:2,"data-testid":`milestone-desc-input-${l.id}`})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__milestone-title-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`milestone-drag-handle-${l.id}`,children:e.jsx(Ye,{size:14})}),e.jsx("h3",{className:"roadmaps-view__milestone-title",children:l.title}),e.jsxs("div",{className:"roadmaps-view__milestone-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:j,title:"Edit milestone","aria-label":"Edit milestone","data-testid":`milestone-edit-${l.id}`,children:e.jsx(Ee,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:f,title:"Delete milestone","aria-label":"Delete milestone","data-testid":`milestone-delete-${l.id}`,children:e.jsx(Le,{size:14})})]})]}),l.description&&e.jsx("p",{className:"roadmaps-view__milestone-desc",children:l.description})]})}),e.jsxs("div",{className:"roadmaps-view__milestone-actions-bar",children:[e.jsxs("button",{className:"roadmaps-view__add-feature-btn",onClick:b,title:"Add feature","aria-label":"Add feature","data-testid":`add-feature-${l.id}`,children:[e.jsx(Ae,{size:12}),e.jsx("span",{children:"Add Feature"})]}),e.jsxs("button",{className:"roadmaps-view__suggest-btn",onClick:()=>{Be?.()},disabled:Q??!1,title:"Generate feature suggestions with AI","aria-label":"Generate feature suggestions","data-testid":`generate-features-${l.id}`,children:[e.jsx(ut,{size:12}),e.jsx("span",{children:Q?"Generating...":"AI Suggestions"})]})]}),e.jsxs("div",{className:Te,onDragOver:h=>{h.preventDefault(),h.dataTransfer.dropEffect="move",h.dataTransfer.getData("text/plain")?.startsWith("feature:")&&Me()},onDrop:h=>{h.preventDefault();const $=h.dataTransfer.getData("text/plain");$?.startsWith("feature:")&&De($.split(":")[1],n.length)},onDragLeave:Y,children:[n.length===0?e.jsx("p",{className:"roadmaps-view__empty-features",children:"No features yet."}):n.map((h,$)=>{const H=y?.featureId===h.id,xe=oe(h.id),Ve=D=>{D.key==="Enter"?(D.preventDefault(),y&&W({title:y.value})):D.key==="Escape"&&z()},Re=["roadmaps-view__feature-item",xe?"roadmaps-view__feature-item--dragging":"",X&&B===$?"roadmaps-view__feature-item--drop-before":"",X&&B===$+1?"roadmaps-view__feature-item--drop-after":""].filter(Boolean).join(" ");return e.jsx("div",{className:Re,draggable:!H,onDragStart:D=>{H||(Fe(h.id,l.id),D.dataTransfer.setData("text/plain",`feature:${h.id}`),D.dataTransfer.effectAllowed="move")},onDragEnd:le,onDragOver:D=>{if(D.preventDefault(),D.stopPropagation(),D.dataTransfer.dropEffect="move",D.dataTransfer.getData("text/plain")?.startsWith("feature:")){const ee=D.currentTarget.getBoundingClientRect(),q=ee.top+ee.height/2,we=D.clientY<q?"before":"after";P(h.id,we)}},onDrop:D=>{D.preventDefault(),D.stopPropagation();const T=D.dataTransfer.getData("text/plain");if(T?.startsWith("feature:")){const ee=T.split(":")[1],q=D.currentTarget.getBoundingClientRect(),we=q.top+q.height/2,ce=D.clientY<we?"before":"after";let Ie=$;ce==="after"&&(Ie=$+1),De(ee,Ie)}},onDragLeave:Y,"data-testid":`feature-item-${h.id}`,children:H?e.jsx("div",{className:"roadmaps-view__inline-edit roadmaps-view__inline-edit--compact",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:y.value,onChange:()=>{},onKeyDown:Ve,placeholder:"Feature title",autoFocus:!0,"data-testid":`feature-title-input-${h.id}`}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>W({title:y.value}),"aria-label":"Save feature title",title:"Save",children:e.jsx(me,{size:14})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:z,"aria-label":"Cancel editing",title:"Cancel",children:e.jsx(ae,{size:14})})]})}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"roadmaps-view__drag-handle roadmaps-view__drag-handle--feature",title:"Drag to reorder","aria-label":"Drag to reorder","data-testid":`feature-drag-handle-${h.id}`,children:e.jsx(Ye,{size:12})}),e.jsxs("div",{className:"roadmaps-view__feature-content",children:[e.jsx("span",{className:"roadmaps-view__feature-title",children:h.title}),h.description&&e.jsx("p",{className:"roadmaps-view__feature-desc",children:h.description})]}),e.jsxs("div",{className:"roadmaps-view__feature-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>C(h.id),title:"Edit feature","aria-label":"Edit feature","data-testid":`feature-edit-${h.id}`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>S(h.id),title:"Delete feature","aria-label":"Delete feature","data-testid":`feature-delete-${h.id}`,children:e.jsx(Le,{size:12})})]})]})},h.id)}),F&&F.length>0&&e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h4",{className:"roadmap-suggestion-title",children:"AI Feature Suggestions"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-accept-all-btn",onClick:()=>He?.(),title:"Accept all suggestions","aria-label":"Accept all","data-testid":`accept-all-features-${l.id}`,children:"Accept All"}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:()=>M?.(),title:"Clear suggestions","aria-label":"Clear","data-testid":`clear-features-${l.id}`,children:"Clear"})]})]}),e.jsx("div",{className:"roadmap-suggestion-list",children:F.map(h=>e.jsx(ea,{suggestion:h,onUpdateDraft:$=>fe?.(l.id,h.id,$),onAccept:()=>{v?.(l.id,h.id)},testIdPrefix:`feature-suggestion-${l.id}`},h.id))})]})]})]})}function ea({suggestion:l,onUpdateDraft:n,onAccept:j,testIdPrefix:f}){const[b,C]=a.useState(!1),[S,m]=a.useState(l.title),[I,E]=a.useState(l.description||""),_=()=>{m(l.title),E(l.description||""),C(!0)},y=()=>{n({title:S.trim(),description:I.trim()||void 0}),C(!1)},re=()=>{m(l.title),E(l.description||""),C(!1)},z=()=>{l.title.trim()&&j()},W=l.title.trim().length>0;return b?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:A=>m(A.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:I,onChange:A=>E(A.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(me,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:re,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(ae,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:_,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:z,disabled:!W,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(me,{size:12})})]})]})}function dt({suggestion:l,onUpdateDraft:n,onAccept:j,testIdPrefix:f}){const[b,C]=a.useState(!1),[S,m]=a.useState(l.title),[I,E]=a.useState(l.description||""),_=()=>{m(l.title),E(l.description||""),C(!0)},y=()=>{n({title:S.trim(),description:I.trim()||void 0}),C(!1)},re=()=>{m(l.title),E(l.description||""),C(!1)},z=()=>{l.title.trim()&&j()},W=l.title.trim().length>0;return b?e.jsx("div",{className:"roadmap-suggestion-card roadmap-suggestion-card--editing",children:e.jsxs("div",{className:"roadmap-suggestion-edit-form",children:[e.jsx("input",{type:"text",className:"roadmap-suggestion-input",value:S,onChange:A=>m(A.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":`${f}-${l.id}-title-input`}),e.jsx("textarea",{className:"roadmap-suggestion-textarea",value:I,onChange:A=>E(A.target.value),placeholder:"Description (optional)",rows:2,"data-testid":`${f}-${l.id}-desc-input`}),e.jsxs("div",{className:"roadmap-suggestion-edit-actions",children:[e.jsx("button",{className:"roadmap-suggestion-save-btn",onClick:y,disabled:!S.trim(),title:"Save","data-testid":`${f}-${l.id}-save`,children:e.jsx(me,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-cancel-btn",onClick:re,title:"Cancel","data-testid":`${f}-${l.id}-cancel`,children:e.jsx(ae,{size:12})})]})]})}):e.jsxs("div",{className:"roadmap-suggestion-card","data-testid":`${f}-${l.id}`,children:[e.jsxs("div",{className:"roadmap-suggestion-content",children:[e.jsx("span",{className:"roadmap-suggestion-card-title",children:l.title}),l.description&&e.jsx("p",{className:"roadmap-suggestion-card-desc",children:l.description})]}),e.jsxs("div",{className:"roadmap-suggestion-card-actions",children:[e.jsx("button",{className:"roadmap-suggestion-edit-btn",onClick:_,title:"Edit suggestion","aria-label":"Edit","data-testid":`${f}-${l.id}-edit`,children:e.jsx(Ee,{size:12})}),e.jsx("button",{className:"roadmap-suggestion-accept-btn",onClick:z,disabled:!W,title:"Accept this suggestion","aria-label":"Accept","data-testid":`${f}-${l.id}-accept`,children:e.jsx(me,{size:12})})]})]})}function pt({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form","data-testid":"create-roadmap-form",children:e.jsxs("form",{onSubmit:S,children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Roadmap title",autoFocus:!0,"data-testid":"create-roadmap-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Roadmap description (optional)",rows:2,"data-testid":"create-roadmap-description"}),e.jsxs("div",{className:"roadmaps-view__create-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__btn roadmaps-view__btn--primary",disabled:!j.trim(),"data-testid":"create-roadmap-submit",children:"Create"}),e.jsx("button",{type:"button",className:"roadmaps-view__btn",onClick:n,"data-testid":"create-roadmap-cancel",children:"Cancel"})]})]})})}function ta({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-milestone-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Milestone title",autoFocus:!0,"data-testid":"create-milestone-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-milestone-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!j.trim(),"aria-label":"Save milestone",title:"Save","data-testid":"create-milestone-submit",children:e.jsx(me,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-milestone-cancel",children:e.jsx(ae,{size:14})})]})]})})}function aa({onSave:l,onCancel:n}){const[j,f]=a.useState(""),[b,C]=a.useState(""),S=m=>{m.preventDefault(),j.trim()&&l({title:j.trim(),description:b.trim()||void 0})};return e.jsx("div",{className:"roadmaps-view__create-form roadmaps-view__create-form--inline","data-testid":"create-feature-form",children:e.jsxs("form",{onSubmit:S,className:"roadmaps-view__inline-form",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input",value:j,onChange:m=>f(m.target.value),placeholder:"Feature title",autoFocus:!0,"data-testid":"create-feature-title"}),e.jsx("textarea",{className:"roadmaps-view__inline-textarea",value:b,onChange:m=>C(m.target.value),placeholder:"Description (optional)",rows:1,"data-testid":"create-feature-description"}),e.jsxs("div",{className:"roadmaps-view__inline-form-actions",children:[e.jsx("button",{type:"submit",className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",disabled:!j.trim(),"aria-label":"Save feature",title:"Save","data-testid":"create-feature-submit",children:e.jsx(me,{size:14})}),e.jsx("button",{type:"button",className:"roadmaps-view__icon-btn",onClick:n,"aria-label":"Cancel",title:"Cancel","data-testid":"create-feature-cancel",children:e.jsx(ae,{size:14})})]})]})})}function oa({projectId:l,addToast:n}){const j=Pt()==="mobile",{roadmaps:f,selectedRoadmapId:b,selectedRoadmap:C,milestones:S,featuresByMilestoneId:m,loading:I,error:E,createRoadmap:_,updateRoadmap:y,deleteRoadmap:re,selectRoadmap:z,createMilestone:W,updateMilestone:A,deleteMilestone:ke,createFeature:se,updateFeature:ge,deleteFeature:ne,reorderMilestones:Oe,reorderFeatures:ie,moveFeature:he,milestoneSuggestions:R,isGeneratingSuggestions:J,generateMilestoneSuggestions:oe,updateMilestoneSuggestionDraft:X,acceptMilestoneSuggestion:B,acceptAllMilestoneSuggestions:Fe,clearMilestoneSuggestions:le,featureSuggestionsByMilestoneId:P,isGeneratingFeatureSuggestions:De,generateFeatureSuggestions:Y,updateFeatureSuggestionDraft:Me,acceptFeatureSuggestion:F,acceptAllFeatureSuggestions:Q,clearFeatureSuggestions:Be,handoffPayload:v,isFetchingHandoff:He,handoffError:fe,fetchHandoff:M,clearHandoff:Z}=Yt({projectId:l}),[be,N]=a.useState(!1),[ve,Te]=a.useState(null),[h,$]=a.useState(""),[H,xe]=a.useState(""),[Ve,Re]=a.useState(!1),D=a.useRef(null);a.useEffect(()=>{D.current!==null&&D.current!==b&&Re(!1),D.current=b},[b]);const[T,ee]=a.useState({roadmapId:null,field:null,value:""}),[q,we]=a.useState({milestoneId:null,field:null,value:""}),[ce,Ie]=a.useState({featureId:null,field:null,value:""}),[de,L]=a.useState({type:null,parentId:void 0,title:"",description:""}),[qe,Ge]=a.useState(!1),[je,Pe]=a.useState({draggingId:null,dropTargetId:null,dropPosition:null}),Je=a.useCallback(t=>{Pe(u=>({...u,draggingId:t}))},[]),_e=a.useCallback(()=>{Pe({draggingId:null,dropTargetId:null,dropPosition:null})},[]),Xe=a.useCallback(t=>{Pe(u=>u.draggingId===t?u:{...u,dropTargetId:t,dropPosition:null})},[]),[ue,$e]=a.useState({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}),Qe=a.useCallback((t,u)=>{$e(w=>({...w,draggingId:t,draggingMilestoneId:u}))},[]),pe=a.useCallback(()=>{$e({draggingId:null,draggingMilestoneId:null,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null})},[]),r=a.useCallback((t,u)=>{$e(w=>{if(w.draggingId===t)return w;const G=(m[w.draggingMilestoneId||""]||[]).findIndex(Ne=>Ne.id===t);let K;return u==="before"?K=G:K=G+1,{...w,dropTargetMilestoneId:w.draggingMilestoneId,dropTargetIndex:K,dropPosition:u}})},[m]),c=a.useCallback(()=>{$e(t=>({...t,dropTargetMilestoneId:t.draggingMilestoneId,dropTargetIndex:(m[t.draggingMilestoneId||""]||[]).length}))},[m]),i=a.useCallback(async(t,u)=>{const{draggingMilestoneId:w,dropTargetMilestoneId:O}=ue;if(!w){pe();return}const G=O||w,K=m[w]||[],Ne=K.find(Se=>Se.id===t);if(!Ne){pe();return}if(w!==G){if(w===G){pe();return}try{await he(t,G,u,{onError:Se=>{n(`Failed to move feature: ${Se.message}`,"error")}})}catch{}}else{const Se=[...K],yt=Se.findIndex(ze=>ze.id===t);Se.splice(yt,1),Se.splice(u,0,Ne);const ct=Se.map(ze=>ze.id),Nt=K.map(ze=>ze.id);if(ct.join(",")===Nt.join(",")){pe();return}try{await ie(w,ct,{onError:ze=>{n(`Failed to reorder features: ${ze.message}`,"error")}})}catch{}}pe()},[ue,m,ie,he,n,pe]),s=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),w=t.clientX,O=t.clientY;(w<u.left||w>u.right||O<u.top||O>u.bottom)&&$e(G=>({...G,dropTargetMilestoneId:null,dropTargetIndex:null,dropPosition:null}))},[]),d=a.useCallback(t=>ue.draggingId===t,[ue.draggingId]),o=a.useCallback(async t=>{const{draggingId:u}=je;if(!u||u===t){_e();return}const w=S.map(Ne=>Ne.id),O=w.indexOf(u),G=w.indexOf(t);if(O===-1||G===-1){_e();return}const K=[...w];if(K.splice(O,1),K.splice(G,0,u),K.join(",")===w.join(",")){_e();return}try{await Oe(b,K,{onError:Ne=>{n(`Failed to reorder milestones: ${Ne.message}`,"error")}})}catch{}_e()},[je,S,b,Oe,n,_e]),g=a.useCallback(t=>{const u=t.currentTarget.getBoundingClientRect(),w=t.clientX,O=t.clientY;(w<u.left||w>u.right||O<u.top||O>u.bottom)&&Pe(G=>({...G,dropTargetId:null,dropPosition:null}))},[]),p=a.useCallback(t=>{z(t.id),ee({roadmapId:t.id,field:"title",value:t.title})},[z]),x=a.useCallback(()=>{ee({roadmapId:null,field:null,value:""})},[]),V=a.useCallback(async t=>{if(T.roadmapId)try{await y(T.roadmapId,t,{onError:u=>n(u.message,"error")}),x()}catch{}},[T.roadmapId,y,x,n]),te=a.useCallback(async t=>{if(window.confirm("Delete this roadmap? This cannot be undone."))try{await re(t,{onError:u=>n(u.message,"error")}),n("Roadmap deleted","success")}catch{}},[re,n]),Ce=a.useCallback((t,u)=>{Te(t),$(u),N(!0),Z()},[Z]),Ke=a.useCallback(()=>{N(!1),Te(null),$(""),Z()},[Z]),k=a.useCallback(()=>{ve&&M(ve,{onError:t=>n(`Failed to load handoff: ${t.message}`,"error")})},[ve,M,n]),U=a.useCallback(()=>{if(v){const t=JSON.stringify(v,null,2);navigator.clipboard.writeText(t).then(()=>{n("Handoff data copied to clipboard","success")}).catch(()=>{n("Failed to copy to clipboard","error")})}},[v,n]),Ue=a.useCallback(async t=>{try{await _(t,{onError:u=>n(u.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Roadmap created","success")}catch{}},[_,n]),We=a.useCallback(t=>{we({milestoneId:t.id,field:"title",value:t.title})},[]),Ze=a.useCallback(()=>{we({milestoneId:null,field:null,value:""})},[]),mt=a.useCallback(async t=>{if(q.milestoneId)try{await A(q.milestoneId,t,{onError:u=>n(u.message,"error")}),Ze()}catch{}},[q.milestoneId,A,Ze,n]),gt=a.useCallback(async t=>{if(window.confirm("Delete this milestone and all its features?"))try{await ke(t,{onError:u=>n(u.message,"error")}),n("Milestone deleted","success")}catch{}},[ke,n]),ht=a.useCallback(async t=>{try{await W(t,{onError:u=>n(u.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Milestone created","success")}catch{}},[W,n]),st=a.useCallback((t,u,w)=>{Ie({featureId:t,field:"title",value:u})},[]),et=a.useCallback(()=>{Ie({featureId:null,field:null,value:""})},[]),ft=a.useCallback(async t=>{if(ce.featureId)try{await ge(ce.featureId,t,{onError:u=>n(u.message,"error")}),et()}catch{}},[ce.featureId,ge,et,n]),bt=a.useCallback(async t=>{if(window.confirm("Delete this feature?"))try{await ne(t,{onError:u=>n(u.message,"error")}),n("Feature deleted","success")}catch{}},[ne,n]),nt=a.useCallback(async()=>{if(H.trim())try{await oe(H,5,{onError:t=>n(t.message,"error")})}catch{}},[H,oe,n]),it=a.useCallback(async t=>{try{await B(t,{onError:u=>n(u.message,"error")}),n("Milestone added","success")}catch{}},[B,n]),ot=a.useCallback(async()=>{try{await Fe({onError:t=>n(t.message,"error")}),n(`${R.length} milestones added`,"success"),xe("")}catch{}},[Fe,R.length,n]),lt=a.useCallback(()=>{le(),xe("")},[le]),vt=a.useCallback(async t=>{try{await Y(t,{count:5},{onError:u=>n(u.message,"error")})}catch{}},[Y,n]),xt=a.useCallback(async(t,u)=>{try{await F(t,u,{onError:w=>n(w.message,"error")}),n("Feature added","success")}catch{}},[F,n]),wt=a.useCallback((t,u,w)=>{Me(t,u,w)},[Me]),jt=a.useCallback(async t=>{const u=P[t]||[];try{await Q(t,{onError:w=>n(w.message,"error")}),n(`${u.length} features added`,"success")}catch{}},[Q,P,n]),_t=a.useCallback(t=>{Be(t)},[Be]),Ct=a.useCallback(async(t,u)=>{try{await se(t,u,{onError:w=>n(w.message,"error")}),L({type:null,parentId:void 0,title:"",description:""}),n("Feature created","success")}catch{}},[se,n]),ye=b;return I&&f.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--loading",children:e.jsx("div",{className:"roadmaps-view__loading-state",children:"Loading roadmaps..."})}):E&&f.length===0?e.jsx("div",{className:"roadmaps-view roadmaps-view--error",children:e.jsxs("div",{className:"roadmaps-view__error-state",children:[e.jsx("p",{children:"Failed to load roadmaps"}),e.jsx("p",{className:"roadmaps-view__error-msg",children:E.message})]})}):e.jsxs("div",{className:"roadmaps-view",children:[j&&!ye&&e.jsx(Xt,{roadmaps:f,selectedRoadmapId:ye,onSelect:t=>z(t),onCreate:()=>Ge(!0),onEdit:p,onDelete:te,onExport:t=>Ce(t.id,t.title),showCreateForm:qe,onCancelCreate:()=>Ge(!1),onSaveCreate:async t=>{await Ue(t),Ge(!1)}}),!j&&e.jsxs("aside",{className:"roadmaps-view__sidebar","aria-label":"Roadmaps",children:[e.jsxs("div",{className:"roadmaps-view__sidebar-header",children:[e.jsx("h2",{className:"roadmaps-view__sidebar-title",children:"Roadmaps"}),e.jsx("button",{className:"roadmaps-view__add-btn",onClick:()=>L({type:"roadmap",title:"",description:""}),title:"Create roadmap","aria-label":"Create roadmap","data-testid":"create-roadmap-btn",children:e.jsx(Ae,{size:16})})]}),de.type==="roadmap"&&e.jsx(pt,{onSave:Ue,onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})}),e.jsx("div",{className:"roadmaps-view__sidebar-list",children:f.length===0?e.jsx("p",{className:"roadmaps-view__empty-sidebar",children:"No roadmaps yet. Click + to create one."}):f.map(t=>e.jsx(Jt,{roadmap:t,isSelected:t.id===ye,onSelect:()=>z(t.id),onEdit:()=>p(t),onDelete:()=>te(t.id),onExport:()=>Ce(t.id,t.title)},t.id))})]}),e.jsxs("main",{className:"roadmaps-view__main","aria-label":"Roadmap content",children:[j&&ye&&e.jsx(Qt,{roadmapTitle:C?.title||"Untitled Roadmap",onBack:()=>z(null),onEdit:()=>{C&&p(C)},onDelete:()=>te(ye),onCreate:()=>Ge(!0)}),ye?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"roadmaps-view__roadmap-header",children:T.roadmapId===ye?e.jsx("div",{className:"roadmaps-view__inline-edit",children:e.jsxs("div",{className:"roadmaps-view__inline-edit-row",children:[e.jsx("input",{type:"text",className:"roadmaps-view__inline-input roadmaps-view__inline-input--large",value:T.value,onChange:t=>ee(u=>({...u,value:t.target.value})),onKeyDown:t=>{t.key==="Enter"?V({title:T.value}):t.key==="Escape"&&x()},placeholder:"Roadmap title",autoFocus:!0,"data-testid":"roadmap-title-input"}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--success",onClick:()=>V({title:T.value}),"aria-label":"Save",title:"Save",children:e.jsx(me,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:x,"aria-label":"Cancel",title:"Cancel",children:e.jsx(ae,{size:16})})]})}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"roadmaps-view__roadmap-title-row",children:[e.jsx("h1",{className:"roadmaps-view__roadmap-title",children:C?.title||"Untitled Roadmap"}),e.jsxs("div",{className:"roadmaps-view__roadmap-actions",children:[e.jsx("button",{className:"roadmaps-view__icon-btn",onClick:()=>{C&&p(C)},title:"Edit roadmap","aria-label":"Edit roadmap","data-testid":"edit-roadmap-btn",children:e.jsx(Ee,{size:16})}),e.jsx("button",{className:"roadmaps-view__icon-btn roadmaps-view__icon-btn--danger",onClick:()=>te(ye),title:"Delete roadmap","aria-label":"Delete roadmap","data-testid":"delete-roadmap-btn",children:e.jsx(Le,{size:16})})]})]}),C?.description&&e.jsx("p",{className:"roadmaps-view__roadmap-desc",children:C.description})]})}),j?Ve?e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsxs("div",{className:"roadmap-suggestion-header",children:[e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"}),e.jsx("button",{className:"roadmap-suggestion-collapse-btn",onClick:()=>Re(!1),"aria-label":"Collapse suggestion panel","data-testid":"collapse-suggestion-panel-btn",children:e.jsx(Lt,{size:16})})]}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:H,onChange:t=>xe(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:J||!b,"data-testid":"goal-prompt-input",autoFocus:!0}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:nt,disabled:!H.trim()||J||!b,"data-testid":"generate-suggestions-btn",children:J?"Generating...":"Generate Milestones"}),R.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:ot,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",R.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:lt,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(ae,{size:14})})]})]})]}),R.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:R.map(t=>e.jsx(dt,{suggestion:t,onUpdateDraft:u=>X(t.id,u),onAccept:()=>it(t.id),testIdPrefix:"suggestion"},t.id))})]}):e.jsx("div",{className:"roadmap-suggestion-section",children:e.jsxs("button",{className:"roadmap-suggestion-expand-btn",onClick:()=>Re(!0),disabled:!b,"data-testid":"expand-suggestion-panel-btn",children:[e.jsx(ut,{size:16}),"Generate Milestone Ideas"]})}):e.jsxs("div",{className:"roadmap-suggestion-section",children:[e.jsx("div",{className:"roadmap-suggestion-header",children:e.jsx("h3",{className:"roadmap-suggestion-title",children:"Generate Milestone Ideas"})}),e.jsxs("div",{className:"roadmap-suggestion-form",children:[e.jsx("textarea",{className:"roadmap-suggestion-input",value:H,onChange:t=>xe(t.target.value),placeholder:"Describe your roadmap goal (e.g., 'Build a user authentication system with OAuth, profiles, and admin dashboard')",rows:2,disabled:J||!b,"data-testid":"goal-prompt-input"}),e.jsxs("div",{className:"roadmap-suggestion-actions",children:[e.jsx("button",{className:"roadmap-suggestion-generate-btn",onClick:nt,disabled:!H.trim()||J||!b,"data-testid":"generate-suggestions-btn",children:J?"Generating...":"Generate Milestones"}),R.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"roadmap-suggestion-accept-all-btn",onClick:ot,"data-testid":"accept-all-suggestions-btn",children:["Accept All (",R.length,")"]}),e.jsx("button",{className:"roadmap-suggestion-clear-btn",onClick:lt,title:"Clear suggestions","aria-label":"Clear suggestions","data-testid":"clear-suggestions-btn",children:e.jsx(ae,{size:14})})]})]})]}),R.length>0&&e.jsx("div",{className:"roadmap-suggestion-list",children:R.map(t=>e.jsx(dt,{suggestion:t,onUpdateDraft:u=>X(t.id,u),onAccept:()=>it(t.id),testIdPrefix:"suggestion"},t.id))})]}),e.jsxs("div",{className:"roadmaps-view__milestone-lanes",children:[de.type==="milestone"&&e.jsx(ta,{onSave:ht,onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})}),S.length===0&&de.type!=="milestone"?e.jsxs("div",{className:"roadmaps-view__empty-milestones",children:[e.jsx("p",{children:"This roadmap has no milestones."}),e.jsxs("button",{className:"roadmaps-view__add-milestone-btn",onClick:()=>L({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn-empty",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]})]}):e.jsxs(e.Fragment,{children:[de.type!=="milestone"&&e.jsxs("button",{className:"roadmaps-view__add-milestone-fab",onClick:()=>L({type:"milestone",title:"",description:""}),"data-testid":"add-milestone-btn",children:[e.jsx(Ae,{size:14}),e.jsx("span",{children:"Add Milestone"})]}),S.map(t=>e.jsx(Zt,{milestone:t,features:m[t.id]||[],onEditMilestone:()=>We(t),onDeleteMilestone:()=>gt(t.id),onAddFeature:()=>L({type:"feature",parentId:t.id,title:"",description:""}),onEditFeature:u=>{const w=m[t.id]?.find(O=>O.id===u);w&&st(u,w.title,w.description)},onDeleteFeature:bt,milestoneEdit:q,onStartMilestoneEdit:()=>We(t),onCancelMilestoneEdit:Ze,onSaveMilestoneEdit:mt,featureEdit:ce,onStartFeatureEdit:st,onCancelFeatureEdit:et,onSaveFeatureEdit:ft,projectId:l,addToast:n,isMilestoneDragging:je.draggingId===t.id,isMilestoneDropTarget:je.dropTargetId===t.id,milestoneDropPosition:je.dropTargetId===t.id?je.dropPosition:null,onMilestoneDragStart:Je,onMilestoneDragEnd:_e,onMilestoneDragOver:Xe,onMilestoneDrop:o,onMilestoneDragLeave:g,isFeatureDragging:d,isFeatureDropTarget:ue.dropTargetMilestoneId===t.id,featureDropIndex:ue.dropTargetMilestoneId===t.id?ue.dropTargetIndex:null,onFeatureDragStart:Qe,onFeatureDragEnd:pe,onFeatureDragOver:r,onFeatureDrop:i,onFeatureDragLeave:s,onFeatureDropOnMilestone:c,featureSuggestions:P[t.id],isGeneratingFeatureSuggestions:De(t.id),onGenerateFeatureSuggestions:()=>vt(t.id),onAcceptFeatureSuggestion:u=>xt(t.id,u),onAcceptAllFeatureSuggestions:()=>jt(t.id),onUpdateFeatureSuggestionDraft:(u,w,O)=>wt(u,w,O),onClearFeatureSuggestions:()=>_t(t.id)},t.id))]})]})]}):e.jsx("div",{className:"roadmaps-view__empty-main",children:e.jsx("p",{children:"Select a roadmap from the sidebar to view its milestones."})})]}),de.type==="feature"&&de.parentId&&e.jsx("div",{className:"roadmaps-view__feature-create-overlay",children:e.jsx(aa,{onSave:t=>Ct(de.parentId,t),onCancel:()=>L({type:null,parentId:void 0,title:"",description:""})})}),e.jsx(qt,{isOpen:be,onClose:Ke,roadmapId:ve||"",roadmapTitle:h,handoffPayload:v,isLoading:He,error:fe,onFetchHandoff:k,onCopyToClipboard:U})]})}export{oa as RoadmapsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.prompt-manager{display:flex;flex-direction:column;gap:var(--space-md);padding:0 20px;margin-top:var(--space-md)}.prompt-manager-tabs{display:flex;gap:var(--space-xs);border-bottom:1px solid var(--border);padding-bottom:var(--space-sm)}.prompt-manager-tab{display:inline-flex;align-items:center;gap:var(--space-xs);padding:var(--space-sm) var(--space-md);background:none;border:1px solid transparent;border-radius:var(--radius-md);color:var(--text-muted);font-size:13px;cursor:pointer;transition:all var(--transition-fast)}.prompt-manager-tab:hover{color:var(--text);background:var(--surface)}.prompt-manager-tab.active{color:var(--text);background:var(--surface);border-color:var(--border)}.prompt-manager-content{min-height:200px}.prompt-manager-templates-tab,.prompt-manager-assignments-tab,.prompt-manager-overrides-tab{display:flex;flex-direction:column;gap:var(--space-lg)}.prompt-template-section{display:flex;flex-direction:column;gap:var(--space-md)}.prompt-template-section-title{font-size:14px;font-weight:600;color:var(--text);margin:0}.prompt-template-section-desc{font-size:12px;color:var(--text-muted);margin:0}.prompt-template-list{display:flex;flex-direction:column;gap:var(--space-md)}.prompt-template-card{padding:var(--space-md);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);transition:border-color var(--transition-fast)}.prompt-template-card:hover{border-color:var(--text-dim)}.prompt-template-card-header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-md);margin-bottom:var(--space-sm)}.prompt-template-card-info{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-sm)}.prompt-template-card-name{font-weight:600;color:var(--text);font-size:14px}.prompt-template-badge-built-in,.prompt-template-badge-custom,.prompt-template-badge-override{display:inline-flex;align-items:center;padding:2px 6px;font-size:10px;font-weight:500;border-radius:var(--radius-sm);text-transform:uppercase;letter-spacing:.02em}.prompt-template-badge-built-in{background:var(--surface);color:var(--text-muted);border:1px solid var(--border)}.prompt-template-badge-custom{background:color-mix(in srgb,var(--ws-info) 15%,transparent);color:var(--ws-info)}.prompt-template-badge-override{background:color-mix(in srgb,var(--ws-warning) 15%,transparent);color:var(--ws-warning)}.prompt-template-badge-role{display:inline-flex;align-items:center;padding:2px 6px;font-size:10px;font-weight:500;border-radius:var(--radius-sm)}.prompt-template-card-actions{display:flex;gap:var(--space-xs)}.prompt-template-card-actions .btn-icon{padding:var(--space-xs)}.prompt-template-card-description{font-size:12px;color:var(--text-muted);margin:0 0 var(--space-sm) 0;line-height:1.4}.prompt-template-card-preview{background:var(--surface);border-radius:var(--radius-sm);padding:var(--space-sm);overflow:hidden}.prompt-template-card-preview code{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted);font-family:var(--font-mono);white-space:pre-wrap;word-break:break-word;display:block;max-height:120px;overflow-y:auto}.prompt-template-empty{padding:var(--space-lg);text-align:center;color:var(--text-muted);font-size:13px;background:var(--surface);border:1px dashed var(--border);border-radius:var(--radius-md)}.prompt-template-add-btn{align-self:flex-start;margin-top:var(--space-sm)}.prompt-template-editor{padding:var(--space-lg);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);margin-bottom:var(--space-lg)}.prompt-template-editor-title{font-size:14px;font-weight:600;color:var(--text);margin:0 0 var(--space-md) 0}.prompt-template-editor-fields{display:flex;flex-direction:column;gap:var(--space-md)}.prompt-template-field{display:flex;flex-direction:column;gap:var(--space-xs)}.prompt-template-field label{font-size:12px;font-weight:500;color:var(--text-muted)}.prompt-template-field input,.prompt-template-field select,.prompt-template-prompt-textarea{padding:var(--space-sm) var(--space-md);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);color:var(--text);font-size:13px;transition:border-color var(--transition-fast)}.prompt-template-field input:focus,.prompt-template-field select:focus,.prompt-template-prompt-textarea:focus{outline:none;border-color:var(--todo)}.prompt-template-prompt-textarea{font-family:var(--font-mono);font-size:12px;line-height:1.5;resize:vertical;min-height:120px}.prompt-template-error{padding:var(--space-sm);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid var(--color-error);border-radius:var(--radius-sm);color:var(--color-error);font-size:12px}.prompt-template-editor-actions{display:flex;gap:var(--space-sm);justify-content:flex-end;margin-top:var(--space-sm)}.prompt-template-delete-confirm{padding:var(--space-md);background:color-mix(in srgb,var(--color-error) 10%,transparent);border:1px solid var(--color-error);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:var(--space-sm)}.prompt-template-delete-confirm p{margin:0;font-size:13px;color:var(--text)}.prompt-template-delete-actions{display:flex;gap:var(--space-sm)}.prompt-assignments-desc{font-size:12px;color:var(--text-muted);margin:0}.prompt-role-assignment-list{display:flex;flex-direction:column;gap:var(--space-md)}.prompt-role-assignment-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-lg);padding:var(--space-md);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md)}.prompt-role-assignment-label{display:flex;align-items:center;gap:var(--space-md)}.prompt-role-badge{display:inline-flex;align-items:center;padding:var(--space-xs) var(--space-sm);font-size:12px;font-weight:600;border-radius:var(--radius-sm)}.prompt-role-assignment-status{font-size:12px;color:var(--text-muted)}.prompt-role-select{min-width:200px;padding:var(--space-sm) var(--space-md);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);color:var(--text);font-size:13px;cursor:pointer}.prompt-role-select:focus{outline:none;border-color:var(--todo)}.prompt-assignments-note{margin-top:var(--space-md);padding:var(--space-md);background:var(--surface);border-radius:var(--radius-md);font-size:12px;color:var(--text-muted);line-height:1.5}.prompt-assignments-note strong{color:var(--text)}.prompt-overrides-desc{font-size:12px;color:var(--text-muted);margin:0}.prompt-overrides-list{display:flex;flex-direction:column;gap:var(--space-md)}.prompt-override-item{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden}.prompt-override-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-md);cursor:pointer;transition:background var(--transition-fast)}.prompt-override-header:hover{background:var(--card-hover)}.prompt-override-info{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-sm)}.prompt-override-name{font-weight:600;color:var(--text);font-size:13px}.prompt-override-key{font-size:11px;font-family:var(--font-mono);color:var(--text-muted);padding:2px 4px;background:var(--surface);border-radius:var(--radius-sm)}.prompt-override-badge{display:inline-flex;align-items:center;padding:2px 6px;font-size:10px;font-weight:500;background:color-mix(in srgb,var(--ws-warning) 15%,transparent);color:var(--ws-warning);border-radius:var(--radius-sm)}.prompt-override-expand-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-sm);transition:color var(--transition-fast),background var(--transition-fast)}.prompt-override-expand-btn:hover{color:var(--text);background:var(--surface)}.prompt-override-description{font-size:12px;color:var(--text-muted);margin:0;padding:0 var(--space-md) var(--space-md);line-height:1.4}.prompt-override-editor{padding:var(--space-md);border-top:1px solid var(--border);background:var(--surface);display:flex;flex-direction:column;gap:var(--space-sm)}.prompt-override-textarea{padding:var(--space-sm) var(--space-md);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-md);color:var(--text);font-size:12px;font-family:var(--font-mono);line-height:1.5;resize:vertical;min-height:80px;transition:border-color var(--transition-fast)}.prompt-override-textarea:focus{outline:none;border-color:var(--todo)}.prompt-override-footer{display:flex;align-items:center;gap:var(--space-md)}.prompt-override-hint{font-size:calc(var(--space-sm) + var(--space-xs) * .75);color:var(--text-muted)}.prompt-override-header-actions{display:flex;align-items:center;gap:var(--space-xs)}.prompt-override-fullscreen-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-sm);transition:color var(--transition-fast),background var(--transition-fast)}.prompt-override-fullscreen-btn:hover{color:var(--text);background:var(--surface)}.prompt-override-fullscreen{position:fixed;inset:0;z-index:10000;background:var(--surface);padding:var(--space-lg);display:flex;flex-direction:column}.prompt-override-fullscreen-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-md);flex-shrink:0}.prompt-override-fullscreen-title{font-size:13px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:var(--space-sm)}.prompt-override-fullscreen-close{display:flex;align-items:center;justify-content:center;gap:var(--space-xs);padding:var(--space-xs) var(--space-sm);background:none;border:1px solid var(--border);border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;font-size:12px;transition:all var(--transition-fast)}.prompt-override-fullscreen-close:hover{color:var(--text);border-color:var(--text-muted)}.prompt-override-fullscreen-close:focus-visible{outline:none;box-shadow:var(--focus-ring-strong)}.prompt-override-fullscreen textarea{flex:1;min-height:unset;resize:none;border-radius:var(--radius-md);font-size:14px;line-height:1.6}.prompt-template-fullscreen-pre{flex:1;font-family:var(--font-mono);font-size:13px;line-height:1.6;color:var(--text);white-space:pre-wrap;word-break:break-word;overflow-y:auto;padding:var(--space-md);background:var(--bg);border-radius:var(--radius-md);border:1px solid var(--border);margin:0}.prompt-override-fullscreen .prompt-override-footer{flex-shrink:0;padding-top:var(--space-sm)}.prompt-template-prompt-label-row{display:flex;align-items:center;gap:var(--space-sm);margin-bottom:var(--space-xs)}.prompt-template-prompt-label-row label{display:block}.prompt-template-fullscreen-btn{vertical-align:middle}.prompt-template-prompt-label-row .prompt-template-fullscreen-btn{margin-left:var(--space-xs)}@media(max-width:768px){.prompt-manager{padding:0 14px}.prompt-manager-tabs{flex-wrap:wrap}.prompt-manager-tab{flex:1;justify-content:center;min-width:calc(50% - var(--space-xs))}.prompt-role-assignment-row{flex-direction:column;align-items:stretch;gap:var(--space-sm)}.prompt-role-select{width:100%}.prompt-template-editor-actions{flex-direction:column}.prompt-template-editor-actions .btn{width:100%}.prompt-override-fullscreen{padding:var(--space-md)}.prompt-override-fullscreen textarea{font-size:16px}}.new-task-modal .form-group small{display:block;margin-top:var(--space-sm);font-size:12px;color:var(--text-muted);line-height:1.4}.new-task-modal textarea{min-height:80px;transition:height .1s ease-out}.selected-deps{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--space-sm);padding:2px 0}.dep-chip{display:inline-flex;align-items:center;gap:var(--space-xs);padding:3px 8px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);font-size:12px;color:var(--text);font-family:var(--font-mono);max-width:100%}.dep-chip-remove{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:12px;line-height:1;padding:0;margin-left:2px;border-radius:50%;transition:background .1s,color .1s}.dep-chip-remove:hover{color:var(--color-error);background:color-mix(in srgb,var(--color-error) 10%,transparent)}.model-select-row{display:flex;align-items:center;gap:var(--space-md);margin-bottom:var(--space-md)}.model-select-row:last-child{margin-bottom:0}.model-select-label{width:70px;flex-shrink:0;font-size:13px;color:var(--text-muted);text-align:right}@media(max-width:768px){.model-select-row{flex-direction:column;align-items:stretch;gap:var(--space-xs)}.model-select-label{width:auto;text-align:left}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./vendor-react-K0fH_qHe.js";import{cj as C}from"./index-DQKtk17v.js";function x(k={}){const{projectId:d,pollInterval:b=6e4,autoRefresh:p=!1,enabled:t=!0}=k,[S,o]=e.useState(null),[m,l]=e.useState(t),[E,c]=e.useState(null),[R,v]=e.useState(null),r=e.useRef(null),n=e.useRef(null),a=e.useRef(!0),s=e.useCallback(async()=>{if(!t){l(!1),c(null),o(null);return}r.current&&r.current.abort(),r.current=new AbortController,l(!0),c(null),o(null);try{const u=await C(d);if(!a.current)return;o(u),c(null),v(new Date),l(!1)}catch(u){if(u instanceof Error&&u.name==="AbortError"||!a.current)return;const A=u instanceof Error?u.message:"Failed to fetch memory backend status";c(A),l(!1)}},[t,d]);e.useEffect(()=>(a.current=!0,t?(s(),()=>{a.current=!1}):(r.current&&r.current.abort(),o(null),c(null),l(!1),()=>{a.current=!1})),[t,s]),e.useEffect(()=>{if(!(!t||!p))return n.current=setInterval(()=>{s()},b),()=>{n.current&&(clearInterval(n.current),n.current=null)}},[t,p,b,s]),e.useEffect(()=>()=>{a.current=!1,r.current&&r.current.abort(),n.current&&(clearInterval(n.current),n.current=null)},[]);const h=e.useCallback(()=>s(),[s]),f=m?null:S,B=f?.currentBackend??null,i=f?.capabilities??null,y=f?.availableBackends??[],I=i?.readable??!1,g=i?.writable??!1,w=i?.supportsAtomicWrite??!1;return{status:f,currentBackend:B,capabilities:i,availableBackends:y,isReadable:I,isWritable:g,supportsAtomicWrite:w,loading:m,error:E,lastUpdated:R,refresh:h}}export{x as u};
|