hanoman 0.6.0 → 0.7.1
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/build-info.json +3 -3
- package/dist/cli.js +74 -11
- package/dist/server.js +3433 -1236
- package/docs/agent-integration.md +5 -0
- package/package.json +1 -1
- package/web/assets/ChangelogScreen-D6brfukI.js +1 -0
- package/web/assets/DalangHanomanScreen-C8GIJv8X.js +1 -0
- package/web/assets/{DocPreviewModal-BTwj2rmX.js → DocPreviewModal-4m5Afjx2.js} +1 -1
- package/web/assets/DocsWorkspace-8U-UYo4-.js +3 -0
- package/web/assets/IdeScreen-8QAVPotm.js +2 -0
- package/web/assets/LeadScreen-CRs2p9QY.js +1 -0
- package/web/assets/ReviewScreen-CBmaRAHG.js +1 -0
- package/web/assets/SchedulerScreen-C1dPfo1w.js +1 -0
- package/web/assets/{SettingsScreen-D1Fop_V6.js → SettingsScreen-rE_jbjMw.js} +8 -8
- package/web/assets/TeamScreen-Dz0rA4Tk.js +1 -0
- package/web/assets/TerminalScreen-Ca7K60wq.js +2 -0
- package/web/assets/TriageScreen-BZQvccje.js +1 -0
- package/web/assets/VpsScreen-CPlPXExd.js +2 -0
- package/web/assets/index-C_btxEiC.js +931 -0
- package/web/assets/{index-NgKosv8R.css → index-ezlZRsLF.css} +32 -1
- package/web/assets/{live-BlNZnTbo.js → live-BWD2sDTC.js} +1 -1
- package/web/index.html +3 -2
- package/web/assets/ChangelogScreen-DVMpzy2Y.js +0 -1
- package/web/assets/DalangHanomanScreen-aY89PmaJ.js +0 -1
- package/web/assets/DocsWorkspace-CgM5rgcr.js +0 -3
- package/web/assets/IdeScreen-B7oDlNQ0.js +0 -2
- package/web/assets/LeadScreen-BzNU_kBC.js +0 -1
- package/web/assets/ReviewScreen-Dk0Zy4jJ.js +0 -1
- package/web/assets/SchedulerScreen-CxYqEqnw.js +0 -1
- package/web/assets/TeamScreen-DwtrDuZG.js +0 -1
- package/web/assets/TerminalScreen-6GBZ9nXN.css +0 -32
- package/web/assets/TerminalScreen-CViC7rot.js +0 -9
- package/web/assets/TriageScreen-DjCXx0F4.js +0 -1
- package/web/assets/VpsScreen-C2WoJQ_j.js +0 -2
- package/web/assets/diff-view-Bep86yt6.js +0 -2
- package/web/assets/index-Bd9gXx1g.js +0 -923
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{T as Ae,j as t,F as G,L as lt,B as ae,I as X,a as B,S as M,u as Ue,M as xe,c as $,d as O,H as ot,e as w,P as Te,E as dt,s as ct,f as H,g as de,h as A,o as we,k as ut,l as mt,m as pt,R as gt,n as ht,p as ce,q as ft}from"./index-Bd9gXx1g.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as xt}from"./live-BlNZnTbo.js";import"./markdown-CWEY34jk.js";const bt={backlog:"Backlog",doing:"Dikerjakan",review:"Review",done:"Selesai"},K=Ae.map(e=>({key:e,label:bt[e]})),vt=()=>Object.fromEntries(Ae.map(e=>[e,[]])),pe=(e,a)=>e!==a,He=e=>e.length===0?0:e.reduce((a,n)=>n.order>a?n.order:a,-1/0)+1;function yt(e,a,n,r){if(!pe(n,r))return null;const l=e[n].find(g=>g.id===a);if(!l)return null;const o={status:r,order:He(e[r])},d={...e};return d[n]=e[n].filter(g=>g.id!==a),d[r]=[...e[r],{...l,...o}],{board:d,patch:o}}function ue(e,a){const n={...e};return n[a.status]=e[a.status].map(r=>r.id===a.id?a:r),n}const De=e=>e?e.slice(0,10):"",Ee=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)?`${e}T12:00:00.000Z`:null,F=864e5,ee=e=>Math.floor(e/F)*F,Me=e=>{if(!e)return null;const a=new Date(e).getTime();return Number.isFinite(a)?a:null};function Y(e){const a=Me(e.startDate),n=Me(e.dueDate);if(a===null&&n===null)return null;const r=a??n,l=n??a;return{start:ee(Math.min(r,l)),end:ee(Math.max(r,l))+F,invalid:l<r}}const jt=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),Be=e=>e?jt.format(new Date(e)):null;function Q(e){const a=Be(e.startDate),n=Be(e.dueDate);return a&&n?`${a} → ${n}`:n?`→ ${n}`:a}const Le=["day","week","month"],Ke={day:{cell:34,minTicks:14},week:{cell:56,minTicks:8},month:{cell:84,minTicks:6}},kt=e=>Ke[e].cell,St=120,It=(e,a)=>{const n=ee(e);if(a==="day")return n;if(a==="week")return n-(new Date(n).getUTCDay()+6)%7*F;const r=new Date(n);return Date.UTC(r.getUTCFullYear(),r.getUTCMonth(),1)},Ct=(e,a)=>{if(a==="day")return e+F;if(a==="week")return e+7*F;const n=new Date(e);return Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,1)},Tt=new Intl.DateTimeFormat("id-ID",{day:"numeric",timeZone:"UTC"}),$e=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),wt=new Intl.DateTimeFormat("id-ID",{month:"short",timeZone:"UTC"}),Dt=new Intl.DateTimeFormat("id-ID",{month:"short",year:"2-digit",timeZone:"UTC"}),Et=(e,a)=>{const n=new Date(e);return a==="day"?n.getUTCDate()===1:a==="week"?n.getUTCDate()<=7:n.getUTCMonth()===0},Mt=(e,a,n)=>{const r=new Date(e);return a==="day"?(n?$e:Tt).format(r):a==="week"?$e.format(r):(n?Dt:wt).format(r)};function Ge(e,a,n){const r=ee(n);let l=r,o=r+F;for(const c of e)c.start<l&&(l=c.start),c.end>o&&(o=c.end);const d=It(l,a),{minTicks:g}=Ke[a],u=[];let i=d;for(;u.length<St&&(i<o||u.length<g);){const c=Et(i,a);u.push({start:i,label:Mt(i,a,c),major:c}),i=Ct(i,a)}return{from:d,to:i,zoom:a,ticks:u}}function Ye(e,a){const n=a.to-a.from;if(n<=0||e.end<=a.from||e.start>=a.to)return null;const r=Math.max(e.start,a.from),l=Math.min(e.end,a.to);return{left:(r-a.from)/n*100,width:(l-r)/n*100,clippedStart:e.start<a.from,clippedEnd:e.end>a.to,invalid:e.invalid}}function ge(e,a){const n=Y(e);return n?Ye(n,a):null}function Bt(e){let a=1/0,n=-1/0,r=!1;for(const l of e){const o=Y(l);o&&(o.start<a&&(a=o.start),o.end>n&&(n=o.end),o.invalid&&(r=!0))}return a===1/0?null:{start:a,end:n,invalid:r}}function Lt(e,a){const n=ee(a);return n<e.from||n>=e.to?null:(n-e.from)/(e.to-e.from)*100}function $t(e,a){const n=[],r=[],l=[];for(const o of e){const d=Y(o);if(!d){r.push(o);continue}const g=ge(o,a);if(!g){l.push(o);continue}n.push({task:o,geometry:g,start:d.start})}return n.sort((o,d)=>o.start-d.start||o.task.title.localeCompare(d.task.title,"id")||o.task.id.localeCompare(d.task.id)),{rows:n.map(({task:o,geometry:d})=>({task:o,geometry:d})),unscheduled:r,outside:l}}const ze=(e,a)=>e.title.localeCompare(a.title,"id")||e.id.localeCompare(a.id);function zt(e,a,n){const r=Symbol("no-project"),l=new Map;for(const u of e){const i=u.projectId??r,c=l.get(i);c?c.tasks.push(u):l.set(i,{projectId:u.projectId,tasks:[u]})}const o=[...l.values()].map(({projectId:u,tasks:i})=>{const c=Bt(i),p=[],v=[];for(const x of i){const h=Y(x);h?p.push({task:x,start:h.start}):v.push(x)}return p.sort((x,h)=>x.start-h.start||ze(x.task,h.task)),v.sort(ze),{projectId:u,span:c,geometry:c?Ye(c,a):null,tasks:[...p.map(x=>x.task),...v]}}),d=u=>u.geometry?0:u.span?1:2,g=u=>u.projectId===null?[1,""]:[0,u.projectId];return o.sort((u,i)=>{const[c,p]=g(u),[v,x]=g(i);return d(u)-d(i)||(u.span&&i.span?u.span.start-i.span.start:0)||n(u.projectId).localeCompare(n(i.projectId),"id")||c-v||p.localeCompare(x)}),o}const Ot={tinggi:"err",sedang:"neutral",rendah:"neutral"};function Rt({task:e,members:a,dragging:n,onDragStart:r,onDragEnd:l,onOpen:o,onMove:d,onAssign:g,onEscalate:u,onUnlink:i}){var v;const c=((v=a.find(x=>x.id===e.memberId))==null?void 0:v.name)??"belum ditugaskan",p=Q(e);return t.jsxs("div",{draggable:!0,"data-testid":`team-card-${e.id}`,onDragStart:x=>{x.dataTransfer.effectAllowed="move",x.dataTransfer.setData("text/plain",e.id),r()},onDragEnd:l,style:{flex:"0 0 auto",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",padding:10,boxShadow:"var(--shadow-xs)",cursor:"grab",opacity:n?.4:1},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6},children:[t.jsx(ae,{tone:Ot[e.priority]??"neutral",size:"sm",variant:e.priority==="tinggi"?"soft":"outline",children:e.priority}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:e.projectId??"tanpa project"})]}),t.jsx("button",{type:"button",onClick:()=>o(e),style:{display:"block",width:"100%",textAlign:"left",border:"none",background:"none",padding:0,cursor:"pointer",fontFamily:"var(--font-ui)",fontSize:13,fontWeight:"var(--weight-medium)",color:"var(--text-strong)",lineHeight:1.35},children:e.title}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[t.jsx(X,{name:"user",size:12,color:"var(--text-subtle)"}),t.jsx("span",{children:c}),p&&t.jsxs(t.Fragment,{children:[t.jsx("span",{"aria-hidden":"true",children:"·"}),t.jsx("span",{children:p})]})]}),t.jsx("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:6,flexWrap:"wrap"},children:e.specId?t.jsxs(t.Fragment,{children:[t.jsx(ae,{tone:e.spec?"ok":"warn",size:"sm",icon:e.spec?"link":"unlink",children:e.spec?`${e.spec.id} · ${e.spec.stage}`:"tautan putus"}),t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"unlink","aria-label":`Lepas tautan: ${e.title}`,onClick:()=>i(e),children:"Lepas tautan"})]}):t.jsx(B,{size:"sm",variant:"ghost",leftIcon:"git-branch","aria-label":`Eskalasi ke backlog: ${e.title}`,onClick:()=>u(e),children:"Eskalasi"})}),t.jsxs("div",{style:{display:"flex",gap:6,marginTop:8},children:[t.jsx(M,{size:"sm",value:e.status,"aria-label":`Pindah kolom: ${e.title}`,onChange:x=>d(e,x.target.value),options:K.map(x=>({value:x.key,label:x.label})),style:{flex:1,minWidth:0}}),t.jsx(M,{size:"sm",value:e.memberId??"","aria-label":`Tugaskan: ${e.title}`,onChange:x=>g(e,x.target.value||null),options:[{value:"",label:"Belum ditugaskan"},...a.map(x=>({value:x.id,label:x.name}))],style:{flex:1,minWidth:0}})]})]})}function Pt({board:e,totals:a,columns:n,members:r,onMove:l,onAssign:o,onOpen:d,onEscalate:g,onUnlink:u}){const[i,c]=m.useState(null),[p,v]=m.useState(null),x=h=>{i&&pe(i.from,h)&&l(i.task,h),c(null),v(null)};return t.jsx("div",{"data-testid":"team-board",className:"hn-board-local-overflow",style:{flex:"1 1 auto",minHeight:0,display:"flex",gap:10,overflowX:"auto",overflowY:"hidden",alignItems:"stretch",paddingBottom:4},children:n.map(h=>{const y=e[h.key],f=!!i&&pe(i.from,h.key),k=f&&p===h.key,L=Math.max(0,(a[h.key]??0)-y.length);return t.jsxs("div",{"data-testid":`team-col-${h.key}`,onDragOver:S=>{f&&(S.preventDefault(),S.dataTransfer.dropEffect="move",v(h.key))},onDragLeave:()=>v(S=>S===h.key?null:S),onDrop:S=>{S.preventDefault(),x(h.key)},style:{flex:"0 0 244px",display:"flex",flexDirection:"column",minHeight:0,padding:10,borderRadius:"var(--radius-lg)",background:k?"var(--brass-100)":"var(--bone-100)",border:`1px ${f?"dashed":"solid"} ${k?"var(--brass-500)":"var(--border-hair)"}`,opacity:i&&!f?.5:1,transition:"var(--transition-fast)"},children:[t.jsxs("div",{style:{...G,display:"flex",alignItems:"center",gap:6,marginBottom:8},children:[t.jsx("span",{className:"hn-eyebrow",children:h.label}),t.jsx("span",{style:{flex:1}}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)"},children:y.length})]}),t.jsx("div",{style:{...lt,display:"flex",flexDirection:"column",gap:8},children:y.map(S=>t.jsx(Rt,{task:S,members:r,dragging:(i==null?void 0:i.task.id)===S.id,onDragStart:()=>c({task:S,from:h.key}),onDragEnd:()=>{c(null),v(null)},onOpen:d,onMove:l,onAssign:o,onEscalate:g,onUnlink:u},S.id))}),L>0&&t.jsxs("div",{style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:["menampilkan ",y.length," dari ",a[h.key]," — persempit penyaring"]})]},h.key)})})}const U=232,he=34,me=6,_t={brass:{bg:"var(--brass-300)",border:"var(--brass-500)"},err:{bg:"var(--status-err-tint)",border:"var(--status-err)"},muted:{bg:"var(--bone-300)",border:"var(--border-strong)"},envelope:{bg:"var(--bone-200)",border:"var(--border-hair)"}},Oe={position:"sticky",left:0,zIndex:1,flex:`0 0 ${U}px`,width:U,boxSizing:"border-box",padding:"5px 10px",minWidth:0,background:"var(--surface-card)",borderRight:"1px solid var(--border-hair)"},V={overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"};function Nt({spec:e}){const a=e.geometry,n=_t[e.tone];return t.jsxs("button",{type:"button","data-testid":`timeline-bar-${e.key}`,"data-tone":e.tone,"data-invalid":a.invalid?"true":"false","data-clipped-start":a.clippedStart?"true":"false","data-clipped-end":a.clippedEnd?"true":"false",title:e.title,"aria-label":e.title,onClick:e.onClick,style:{position:"absolute",top:me,height:he-me*2,left:`${a.left}%`,width:`${a.width}%`,minWidth:3,minHeight:he-me*2,display:"flex",alignItems:"center",padding:0,overflow:"hidden",background:n.bg,border:`1px solid ${n.border}`,borderTopLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderBottomLeftRadius:a.clippedStart?0:"var(--radius-sm)",borderTopRightRadius:a.clippedEnd?0:"var(--radius-sm)",borderBottomRightRadius:a.clippedEnd?0:"var(--radius-sm)",cursor:e.onClick?"pointer":"default"},children:[a.clippedStart&&t.jsx(X,{name:"chevron-left",size:11,color:n.border}),t.jsx("span",{style:{flex:1}}),a.clippedEnd&&t.jsx(X,{name:"chevron-right",size:11,color:n.border})]})}function Ze({window:e,rows:a,today:n,emptyHint:r,testId:l,labelHead:o}){const d=kt(e.zoom),g=e.ticks.length*d,u=Lt(e,n),i={position:"relative",width:g,height:he,flex:`0 0 ${g}px`,backgroundImage:`repeating-linear-gradient(to right, var(--border-hair) 0 1px, transparent 1px ${d}px)`};return t.jsx("div",{"data-testid":l??"team-timeline",className:"hn-timeline-scroll",style:{flex:"1 1 auto",minHeight:0,minWidth:0,maxWidth:"100%",overflowX:"auto",overflowY:"auto"},children:t.jsxs("div",{"data-testid":"timeline-canvas",style:{position:"relative",minWidth:U+g,width:U+g},children:[t.jsxs("div",{style:{display:"flex",position:"sticky",top:0,zIndex:2,background:"var(--bone-100)",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{style:{...Oe,zIndex:3,background:"var(--bone-100)"},children:t.jsx("span",{className:"hn-eyebrow",children:o??"Tugas"})}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:`repeat(${e.ticks.length}, ${d}px)`,width:g,flex:`0 0 ${g}px`},children:e.ticks.map(c=>t.jsx("div",{"data-testid":"timeline-tick",style:{borderLeft:`1px solid ${c.major?"var(--border-strong)":"var(--border-hair)"}`,padding:"5px 4px",fontFamily:"var(--font-mono)",fontSize:10,...V,color:c.major?"var(--text-body)":"var(--text-subtle)"},children:c.label},c.start))})]}),a.length===0?t.jsx("div",{"data-testid":"timeline-empty",style:{position:"sticky",left:0,width:U,padding:"18px 10px",fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r??"Tak ada yang bisa dihamparkan di jendela ini."}):a.map(c=>t.jsxs("div",{"data-testid":`timeline-row-${c.key}`,style:{display:"flex",borderBottom:"1px solid var(--border-hair)"},children:[t.jsxs("div",{style:Oe,children:[t.jsx("div",{style:{...V,fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:c.label}),c.meta&&t.jsx("div",{style:{...V,fontSize:10,color:"var(--text-subtle)"},children:c.meta})]}),t.jsx("div",{style:i,children:c.bars.map(p=>t.jsx(Nt,{spec:p},p.key))})]},c.key)),u!==null&&t.jsx("div",{"data-testid":"timeline-today","aria-hidden":"true",style:{position:"absolute",top:0,bottom:0,width:2,pointerEvents:"none",left:U+u/100*g,background:"var(--brass-500)",opacity:.5}})]})})}function Re({testId:e,icon:a,title:n,hint:r,tasks:l,onOpen:o}){return l.length===0?null:t.jsxs("div",{"data-testid":e,style:{...G,marginTop:10,padding:10,background:"var(--bone-100)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-lg)"},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:6,flexWrap:"wrap"},children:[t.jsx(X,{name:a,size:13,color:"var(--text-subtle)"}),t.jsxs("span",{className:"hn-eyebrow",children:[n," · ",l.length]}),r&&t.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:r})]}),t.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:6},children:l.map(d=>t.jsx("button",{type:"button",onClick:()=>o(d),style:{padding:"3px 10px",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-pill)",fontFamily:"var(--font-ui)",fontSize:12,color:"var(--text-body)",cursor:"pointer"},children:d.title},d.id))})]})}function Ft({tasks:e,members:a,zoom:n,today:r,hidden:l,onOpen:o}){const d=m.useMemo(()=>{const p=e.map(Y).filter(v=>v!==null);return Ge(p,n,r)},[e,n,r]),{rows:g,unscheduled:u,outside:i}=m.useMemo(()=>$t(e,d),[e,d]),c=m.useMemo(()=>g.map(({task:p,geometry:v})=>{var f;const x=((f=a.find(k=>k.id===p.memberId))==null?void 0:f.name)??"belum ditugaskan",h=Q(p),y=[v.invalid?"tenggat mendahului mulai":null,v.clippedStart||v.clippedEnd?"melewati tepi jendela":null].filter(Boolean);return{key:p.id,label:p.title,meta:h?`${x} · ${h}`:x,bars:[{key:p.id,geometry:v,tone:v.invalid?"err":p.status==="done"?"muted":"brass",title:[p.title,h,...y].filter(Boolean).join(" · "),onClick:()=>o(p)}]}}),[g,a,o]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:d,rows:c,today:r,emptyHint:"Belum ada tugas bertanggal — isi mulai atau tenggat di kartunya."}),l>0&&t.jsxs("div",{"data-testid":"timeline-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[l," tugas tak termuat karena plafon 200 per kolom — persempit penyaring"]}),t.jsx(Re,{testId:"timeline-unscheduled",icon:"calendar-off",title:"Belum dijadwalkan",tasks:u,onOpen:o}),t.jsx(Re,{testId:"timeline-outside",icon:"chevrons-left-right",title:"Di luar jendela",hint:"pilih zoom yang lebih lebar",tasks:i,onOpen:o})]})}const Wt="__none__",At=16,Pe=(e,a)=>a.invalid?"err":e.status==="done"?"muted":"brass",_e=(e,a,n)=>[e.title,n,a.invalid?"tenggat mendahului mulai":null,a.clippedStart||a.clippedEnd?"melewati tepi jendela":null].filter(Boolean).join(" · ");function Ut({testId:e,open:a,name:n,count:r,onClick:l}){return t.jsxs("button",{type:"button",onClick:l,"data-testid":e,"aria-expanded":a,style:{display:"flex",alignItems:"center",gap:5,width:"100%",padding:0,background:"none",border:"none",cursor:"pointer",textAlign:"left",minHeight:0,fontFamily:"var(--font-ui)",fontSize:12,fontWeight:"var(--weight-medium)",color:"var(--text-strong)"},children:[t.jsx(X,{name:a?"chevron-down":"chevron-right",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{...V,flex:1},children:n}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:10,color:"var(--text-subtle)"},children:r})]})}function Ht({tasks:e,projects:a,members:n,zoom:r,today:l,hidden:o,expanded:d,onToggle:g,onOpen:u}){const i=m.useMemo(()=>{const h=e.map(Y).filter(y=>y!==null);return Ge(h,r,l)},[e,r,l]),c=m.useCallback(h=>{var y;return h===null?"Tanpa project":((y=a.find(f=>f.id===h))==null?void 0:y.name)??h},[a]),p=m.useMemo(()=>zt(e,i,c),[e,i,c]),v=m.useMemo(()=>new Set(d),[d]),x=m.useMemo(()=>{var y;const h=[];for(const f of p){const k=f.projectId??Wt,L=v.has(k),S=c(f.projectId),b=f.geometry?Q({startDate:new Date(f.span.start).toISOString(),dueDate:new Date(f.span.end-1).toISOString()}):f.span?"di luar jendela · pilih zoom yang lebih lebar":"belum dijadwalkan",D=[];if(f.geometry){D.push({key:`span:${k}`,geometry:f.geometry,tone:f.geometry.invalid?"err":"envelope",title:`${S} · ${b??""}`.trim(),onClick:()=>g(k)});for(const C of f.tasks){const E=ge(C,i);E&&D.push({key:`seg:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,Q(C)),onClick:()=>u(C)})}}if(h.push({key:`p:${k}`,meta:b,bars:D,label:t.jsx(Ut,{testId:`expand-${k}`,open:L,name:S,count:f.tasks.length,onClick:()=>g(k)})}),!!L)for(const C of f.tasks){const E=ge(C,i),j=((y=n.find(_=>_.id===C.memberId))==null?void 0:y.name)??"belum ditugaskan",P=Q(C);h.push({key:`t:${C.id}`,label:t.jsx("span",{style:{...V,display:"block",paddingLeft:At},children:C.title}),meta:P?`${j} · ${P}`:j,bars:E?[{key:`t:${C.id}`,geometry:E,tone:Pe(C,E),title:_e(C,E,P),onClick:()=>u(C)}]:[]})}}return h},[p,v,c,i,n,g,u]);return t.jsxs(t.Fragment,{children:[t.jsx(Ze,{window:i,rows:x,today:l,testId:"team-projects",labelHead:"Project",emptyHint:"Belum ada project bertanggal — isi mulai atau tenggat di kartunya."}),o>0&&t.jsxs("div",{"data-testid":"projects-truncated",style:{...G,marginTop:8,fontSize:"var(--text-xs)",color:"var(--amber-600)"},children:[o," tugas tak termuat karena plafon 200 per kolom — amplop project bisa lebih pendek dari rentang sebenarnya; persempit kolom, anggota, atau pencarian"]})]})}const fe={tinggi:"Tinggi",sedang:"Sedang",rendah:"Rendah"},Kt=Object.keys(fe).map(e=>({value:e,label:fe[e]})),Ne=(e,a)=>({title:(e==null?void 0:e.title)??"",detail:(e==null?void 0:e.detail)??"",projectId:e?e.projectId??"":a??"",status:(e==null?void 0:e.status)??"backlog",priority:e&&e.priority in fe?e.priority:"sedang",memberId:(e==null?void 0:e.memberId)??"",startDate:De((e==null?void 0:e.startDate)??null),dueDate:De((e==null?void 0:e.dueDate)??null)});function Gt({open:e,task:a,projects:n,members:r,defaultProjectId:l,orderFor:o,onClose:d,onSaved:g,onToast:u}){const[i,c]=m.useState(()=>Ne(a,l)),[p,v]=m.useState(!1),{confirm:x,dialog:h}=Ue(),y=`${e?"1":"0"}:${(a==null?void 0:a.id)??""}`,f=m.useRef(y);if(f.current!==y&&(f.current=y,e&&c(Ne(a,l))),!e)return null;const k=b=>c(D=>({...D,...b}));async function L(){if(!i.title.trim()){u("Judul tugas wajib diisi","err","x-circle");return}v(!0);const b=!a||a.status!==i.status,D={title:i.title.trim(),detail:i.detail.trim()||null,projectId:i.projectId||null,status:i.status,priority:i.priority,memberId:i.memberId||null,startDate:Ee(i.startDate),dueDate:Ee(i.dueDate),...b?{order:o(i.status)}:{}};try{a?await w.patchTask(a.id,D):await w.createTask(D),u(a?"Tugas diperbarui":"Tugas dibuat","ok","check"),g(),d()}catch{u("Gagal menyimpan tugas","err","x-circle")}finally{v(!1)}}async function S(){a&&await x({title:`Hapus "${a.title}"?`,message:"Kartu ini hilang dari papan di semua device yang tersinkron.",confirmLabel:"Hapus tugas",tone:"danger",icon:"trash-2",run:()=>w.deleteTask(a.id)})&&(u("Tugas dihapus","ok","trash-2"),g(),d())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:d,icon:"clipboard-list",eyebrow:"Papan tim",title:a?"Ubah tugas":"Tugas baru",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[a&&t.jsx(B,{variant:"ghost",leftIcon:"trash-2",onClick:S,disabled:p,children:"Hapus"}),t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:d,disabled:p,children:"Batal"}),t.jsx(B,{onClick:L,loading:p,children:a?"Simpan":"Buat tugas"})]}),children:[t.jsx($,{label:"Judul",children:t.jsx(O,{value:i.title,"aria-label":"Judul tugas",placeholder:"mis. Rapikan halaman harga",onChange:b=>k({title:b.target.value}),style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Project",children:t.jsx(M,{value:i.projectId,"aria-label":"Project tugas",onChange:b=>k({projectId:b.target.value}),options:[{value:"",label:"Tanpa project"},...n.map(b=>({value:b.id,label:b.name}))]})}),t.jsx($,{label:"Kolom",children:t.jsx(M,{value:i.status,"aria-label":"Kolom tugas",onChange:b=>k({status:b.target.value}),options:K.map(b=>({value:b.key,label:b.label}))})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{value:i.priority,"aria-label":"Prioritas tugas",onChange:b=>k({priority:b.target.value}),options:Kt})})]}),t.jsx($,{label:"Ditugaskan ke",children:t.jsx(M,{value:i.memberId,"aria-label":"Anggota tugas",onChange:b=>k({memberId:b.target.value}),options:[{value:"",label:"Belum ditugaskan"},...r.map(b=>({value:b.id,label:b.role?`${b.name} · ${b.role}`:b.name}))],style:{width:"100%"}})}),t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[t.jsx($,{label:"Mulai",children:t.jsx(O,{type:"date",value:i.startDate,"aria-label":"Tanggal mulai",onChange:b=>k({startDate:b.target.value})})}),t.jsx($,{label:"Tenggat",children:t.jsx(O,{type:"date",value:i.dueDate,"aria-label":"Tanggal tenggat",onChange:b=>k({dueDate:b.target.value})})})]}),t.jsx($,{label:"Detail",hint:"Opsional — konteks yang tak muat di judul.",children:t.jsx(ot,{value:i.detail,"aria-label":"Detail tugas",rows:4,placeholder:"mis. tunggu aset dari klien, deadline ikut jadwal kampanye",onChange:b=>k({detail:b.target.value})})})]}),h]})}const Yt=dt.map(e=>({value:e,label:ct(e).label}));function Zt({task:e,projects:a,onClose:n,onDone:r,onToast:l}){const[o,d]=m.useState("brief"),[g,u]=m.useState(()=>Te.some(f=>f.value===e.priority)?e.priority:"sedang"),[i,c]=m.useState(""),[p,v]=m.useState(!1),x=e.projectId===null,h=e.projectId??i;async function y(){if(!(!h||p)){v(!0);try{const f=await w.escalateTask(e.id,{source:o,priority:g,...e.projectId?{}:{projectId:i}});l(f.created?`Dieskalasi jadi ${f.spec.id}`:`Sudah tertaut ke ${f.spec.id}`,"ok","link"),r(f.task),n()}catch{l("Gagal mengeskalasi kartu","err","x-circle")}finally{v(!1)}}}return t.jsxs(xe,{open:!0,onClose:p?void 0:n,icon:"git-branch",eyebrow:"Papan tim",title:"Eskalasi ke backlog",footer:t.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[t.jsx("span",{style:{flex:1}}),t.jsx(B,{variant:"secondary",onClick:n,disabled:p,children:"Batal"}),t.jsx(B,{onClick:y,loading:p,disabled:!h,leftIcon:"git-branch",children:"Eskalasi"})]}),children:[t.jsxs("div",{style:{fontSize:13.5,color:"var(--text-strong)",lineHeight:1.55,marginBottom:14},children:["Kartu ",t.jsx("strong",{children:e.title})," tetap di papan. Yang lahir adalah backlog item baru yang bisa dikerjakan sesi agen, dan kartu ini menampilkan stage-nya."]}),x&&t.jsxs($,{label:"Project",children:[t.jsx(M,{"aria-label":"Project",value:i,style:{width:"100%"},onChange:f=>c(f.target.value),options:[{value:"",label:"Pilih project…"},...a.map(f=>({value:f.id,label:f.name}))]}),t.jsx("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Nomor SPEC diambil dari repo project, jadi kartu tanpa project belum bisa dieskalasi."})]}),t.jsx($,{label:"Source",children:t.jsx(M,{"aria-label":"Source",value:o,style:{width:"100%"},onChange:f=>d(f.target.value),options:Yt})}),t.jsx($,{label:"Prioritas",children:t.jsx(M,{"aria-label":"Prioritas",value:g,style:{width:"100%"},onChange:f=>u(f.target.value),options:Te})})]})}function qt({m:e,busy:a,onSave:n,onToggle:r,onDelete:l}){const[o,d]=m.useState(!1),[g,u]=m.useState(e.name),[i,c]=m.useState(e.role??"");return o?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8,padding:"12px 14px",marginBottom:8,border:"1px solid var(--border-strong)",borderRadius:"var(--radius-md)",background:"var(--surface-card)"},children:[t.jsx(O,{size:"sm",value:g,"aria-label":`Nama ${e.name}`,placeholder:"mis. Dena Meidina",onChange:p=>u(p.target.value)}),t.jsx(O,{size:"sm",value:i,"aria-label":`Peran ${e.name}`,placeholder:"mis. desainer",onChange:p=>c(p.target.value)}),t.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[e.email," — ganti email berarti hapus lalu buat baru."]}),t.jsxs("div",{style:{display:"flex",gap:8},children:[t.jsx(B,{size:"sm",disabled:a,onClick:()=>{n(e.id,{name:g.trim(),role:i.trim()||null}),d(!1)},children:"Simpan"}),t.jsx(B,{size:"sm",variant:"ghost",onClick:()=>d(!1),children:"Batal"})]})]}):t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 14px",marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",opacity:e.active?1:.6},children:[t.jsxs("span",{style:{flex:1,minWidth:0},children:[t.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{fontWeight:"var(--weight-semibold)",color:"var(--text-strong)"},children:e.name}),e.role&&t.jsx(ae,{tone:"neutral",size:"sm",children:e.role}),!e.active&&t.jsx(ae,{tone:"warn",size:"sm",children:"nonaktif"})]}),t.jsx("span",{style:{display:"block",fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2},children:e.email})]}),t.jsx(de,{icon:"pencil",label:`Ubah ${e.name}`,size:"sm",onClick:()=>d(!0)}),t.jsx(de,{icon:e.active?"user-minus":"user-check",size:"sm",label:`${e.active?"Nonaktifkan":"Aktifkan"} ${e.name}`,onClick:()=>r(e)}),t.jsx(de,{icon:"trash-2",label:`Hapus ${e.name}`,size:"sm",onClick:()=>l(e)})]})}function Jt({open:e,onClose:a,onChanged:n,onToast:r}){const[l,o]=m.useState([]),[d,g]=m.useState("loading"),[u,i]=m.useState(!1),[c,p]=m.useState(""),[v,x]=m.useState(""),[h,y]=m.useState(""),{confirm:f,dialog:k}=Ue(),L=m.useRef(n);L.current=n;const S=m.useCallback(()=>{g("loading"),w.listMembers().then(j=>{o(j.items),g("ready"),L.current(j.items)}).catch(()=>g("error"))},[]);if(m.useEffect(()=>{e&&S()},[e,S]),!e)return null;async function b(){if(!c.trim()||!v.trim()){r("Nama & email wajib diisi","err","x-circle");return}i(!0);try{await w.createMember({name:c.trim(),email:v.trim(),role:h.trim()||null}),p(""),x(""),y(""),r("Anggota ditambahkan","ok","user-plus"),S()}catch{r("Gagal menambah anggota — email mungkin sudah terdaftar","err","x-circle")}finally{i(!1)}}async function D(j,P){i(!0);try{await w.patchMember(j,P),S()}catch{r("Gagal menyimpan anggota","err","x-circle")}finally{i(!1)}}async function C(j){i(!0);try{await w.patchMember(j.id,{active:!j.active}),S()}catch{r("Gagal mengubah status anggota","err","x-circle")}finally{i(!1)}}async function E(j){await f({title:`Hapus ${j.name} dari direktori?`,message:"Tugasnya tidak ikut terhapus — kartu yang ditugaskan padanya jadi 'belum ditugaskan'.",confirmLabel:"Hapus anggota",tone:"danger",icon:"trash-2",run:()=>w.deleteMember(j.id)})&&(r("Anggota dihapus","ok","trash-2"),S())}return t.jsxs(t.Fragment,{children:[t.jsxs(xe,{open:e,onClose:a,icon:"users",eyebrow:"Papan tim",title:"Anggota",width:620,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap",alignItems:"flex-end",marginBottom:16,paddingBottom:16,borderBottom:"1px solid var(--border-hair)"},children:[t.jsx(O,{size:"sm",value:c,"aria-label":"Nama anggota baru",placeholder:"Nama",onChange:j=>p(j.target.value),style:{flex:"1 1 140px"}}),t.jsx(O,{size:"sm",value:v,"aria-label":"Email anggota baru",placeholder:"email@nafanesia.id",onChange:j=>x(j.target.value),style:{flex:"1 1 180px"}}),t.jsx(O,{size:"sm",value:h,"aria-label":"Peran anggota baru",placeholder:"Peran (opsional)",onChange:j=>y(j.target.value),style:{flex:"1 1 130px"}}),t.jsx(B,{size:"sm",leftIcon:"user-plus",onClick:b,loading:u,children:"Tambah anggota"})]}),d==="loading"?t.jsx(H,{kind:"loading",compact:!0}):d==="error"?t.jsx(H,{kind:"error",compact:!0,hint:"Gagal memuat anggota.",action:S,actionLabel:"Coba lagi"}):l.length===0?t.jsx(H,{kind:"empty",compact:!0,icon:"users",title:"Belum ada anggota",hint:"Tambahkan orang di atas agar kartu papan bisa ditugaskan."}):l.map(j=>t.jsx(qt,{m:j,busy:u,onSave:D,onToggle:C,onDelete:E},j.id))]}),k]})}const Qt=5e3,Fe=200,Vt=400,We=[{value:"board",label:"Papan",icon:"kanban"},{value:"timeline",label:"Linimasa",icon:"gantt-chart"},{value:"projects",label:"Lintas project",icon:"layers"}],Xt={day:"Hari",week:"Minggu",month:"Bulan"},ea=()=>Object.fromEntries(K.map(e=>[e.key,0]));function ta({status:e,params:a,onData:n,refetch:r}){return ft({topic:"tasks",params:{...a,status:e},apply:l=>n(e,l.data.items,l.data.total),refetch:r,pollMs:Qt}),null}function sa({projects:e,projectFilter:a,onProjectFilter:n,onToast:r}){const[l,o]=m.useState(vt),[d,g]=m.useState(ea),[u,i]=m.useState([]),[c,p]=m.useState("loading"),[v,x]=m.useState(!1),[h,y]=m.useState(null),[f,k]=m.useState(!1),[L,S]=m.useState(!1),[b,D]=m.useState(null),[C,E]=A("team","view","board",we(...We.map(s=>s.value))),[j,P]=A("team","q","",ce),[_,qe]=A("team","col","all",ce),[Z,Je]=A("team","member","all",ce),[ne,Qe]=A("team","zoom","week",we(...Le)),[Ve,be]=A("team","expanded",[],ht),Xe=m.useCallback(s=>{be(I=>I.includes(s)?I.filter(T=>T!==s):[...I,s])},[be]),ve=C==="timeline",N=C==="projects",ye=m.useRef(Date.now()).current,R=m.useMemo(()=>_==="all"?K:K.filter(s=>s.key===_),[_]),ie=R.map(s=>s.key).join(","),je=[a!=="all"&&!N,_!=="all",Z!=="all",j.trim()!==""].filter(Boolean).length,re=N||a==="all"?void 0:a,W=m.useMemo(()=>({projectId:re,memberId:Z==="all"?void 0:Z,q:j.trim()||void 0}),[re,Z,j]),te=m.useRef(!1),q=m.useCallback((s=!1)=>{!s&&!te.current&&p("loading");const I=ie?ie.split(","):[];Promise.all(I.map(T=>w.listTasks({...W,status:T,page:1,limit:Fe}))).then(T=>{o(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].items}),J}),g(z=>{const J={...z};return I.forEach((le,oe)=>{J[le]=T[oe].total}),J}),te.current=!0,x(!1),p("ready")}).catch(()=>{if(!te.current){p("error");return}x(!0)})},[W,ie]);m.useEffect(()=>{q()},[q]);const ke=m.useCallback(()=>{w.listMembers().then(s=>i(s.items)).catch(()=>{})},[]);m.useEffect(()=>{ke()},[ke]);const[Se,et]=m.useState(()=>j.trim());m.useEffect(()=>{const s=setTimeout(()=>et(j.trim()),Vt);return()=>clearTimeout(s)},[j]);const tt=m.useCallback((s,I,T)=>{o(z=>({...z,[s]:I})),g(z=>({...z,[s]:T})),te.current=!0,x(!1),p("ready")},[]),at=m.useMemo(()=>({projectId:W.projectId,memberId:W.memberId,q:Se||void 0,page:1,limit:Fe}),[W.projectId,W.memberId,Se]),se=m.useCallback(()=>q(!0),[q]);async function nt(s,I){const T=yt(l,s.id,s.status,I);if(!T)return;const z=l;o(T.board);try{await w.patchTask(s.id,T.patch)}catch{o(z),r("Gagal memindahkan tugas","err","x-circle")}}async function it(s,I){const T=l;o(ue(l,{...s,memberId:I}));try{await w.patchTask(s.id,{memberId:I})}catch{o(T),r("Gagal menugaskan","err","x-circle")}}async function rt(s){const I=l;o(ue(l,{...s,specId:null,spec:null}));try{await w.unlinkTaskSpec(s.id),r("Tautan backlog dilepas","ok","unlink")}catch{o(I),r("Gagal melepas tautan","err","x-circle")}}const st=R.every(s=>l[s.key].length===0),Ie=m.useMemo(()=>R.flatMap(s=>l[s.key]),[l,R]),Ce=R.reduce((s,I)=>s+Math.max(0,(d[I.key]??0)-l[I.key].length),0);return t.jsxs("div",{style:ut,children:[t.jsxs("div",{className:"hn-team-controls",role:"region","aria-label":"Kontrol papan tim",style:{...G,marginBottom:18},children:[t.jsxs("div",{className:"hn-team-topline",style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,flexWrap:"wrap",marginBottom:12},children:[t.jsx(mt,{variant:"pill",value:C,onChange:E,tabs:We,"aria-label":"Mode tampilan"}),t.jsxs("div",{className:"hn-team-view-actions",style:{display:"flex",alignItems:"center",gap:10},children:[t.jsx(B,{size:"sm",leftIcon:"plus",onClick:()=>{y(null),k(!0)},children:"Tugas baru"}),t.jsx(B,{size:"sm",variant:"secondary",leftIcon:"users",onClick:()=>S(!0),children:"Anggota"}),t.jsx(pt,{onDone:se,onToast:r}),t.jsx(gt,{screen:"team",active:je,onReset:N?void 0:()=>n("all")}),t.jsxs("span",{className:"hn-eyebrow",role:"status",style:v?{color:"var(--amber-600)"}:void 0,title:v?"Server tak menjawab saat menyegarkan — angka ini dari muatan terakhir yang berhasil":void 0,children:[R.reduce((s,I)=>s+(d[I.key]??0),0)," tugas",v?" · basi":""]}),t.jsx(xt,{})]})]}),t.jsxs("div",{className:"hn-team-filters",style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[t.jsx(O,{size:"sm",leftIcon:"search","aria-label":"Cari tugas",value:j,placeholder:"mis. halaman harga atau deploy",onChange:s=>P(s.target.value),style:{flex:"1 1 220px"}}),t.jsx(M,{size:"sm","aria-label":"Filter project",value:a,disabled:N,onChange:s=>n(s.target.value),options:[{value:"all",label:"Semua project"},...e.map(s=>({value:s.id,label:s.name}))]}),N&&t.jsx("span",{"data-testid":"project-filter-note",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:"Mode ini melintasi semua project"}),t.jsx(M,{size:"sm","aria-label":"Filter kolom",value:_,onChange:s=>qe(s.target.value),options:[{value:"all",label:"Semua kolom"},...K.map(s=>({value:s.key,label:s.label}))]}),t.jsx(M,{size:"sm","aria-label":"Filter anggota",value:Z,onChange:s=>Je(s.target.value),options:[{value:"all",label:"Semua anggota"},...u.map(s=>({value:s.id,label:s.name}))]}),(ve||N)&&t.jsx(M,{size:"sm","aria-label":"Zoom linimasa",value:ne,onChange:s=>Qe(s.target.value),options:Le.map(s=>({value:s,label:Xt[s]}))})]})]}),R.map(s=>t.jsx(ta,{status:s.key,params:at,onData:tt,refetch:se},s.key)),c==="loading"?t.jsx(H,{kind:"loading"}):c==="error"?t.jsx(H,{kind:"error",hint:"Gagal memuat papan tim.",action:()=>q(),actionLabel:"Coba lagi"}):st&&je===0?t.jsx(H,{kind:"empty",icon:"users",title:"Papan tim masih kosong",hint:"Catat pekerjaan manusia di sekitar sesi agen — desain, meeting klien, deploy, nego.",action:()=>{y(null),k(!0)},actionLabel:"Tugas baru",actionIcon:"plus"}):N?t.jsx(Ht,{tasks:Ie,projects:e,members:u,zoom:ne,today:ye,hidden:Ce,expanded:Ve,onToggle:Xe,onOpen:s=>{y(s),k(!0)}}):ve?t.jsx(Ft,{tasks:Ie,members:u,zoom:ne,today:ye,hidden:Ce,onOpen:s=>{y(s),k(!0)}}):t.jsx(Pt,{board:l,totals:d,columns:R,members:u,onMove:nt,onAssign:it,onEscalate:D,onUnlink:rt,onOpen:s=>{y(s),k(!0)}}),t.jsx(Gt,{open:f,task:h,projects:e,members:u,defaultProjectId:re??null,orderFor:s=>He(l[s]),onClose:()=>{k(!1),y(null)},onSaved:se,onToast:r}),b&&t.jsx(Zt,{task:b,projects:e,onClose:()=>D(null),onDone:s=>o(I=>ue(I,s)),onToast:r}),t.jsx(Jt,{open:L,onClose:()=>S(!1),onChanged:i,onToast:r})]})}export{We as TEAM_VIEWS,sa as TeamScreen};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
-
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
-
* https://github.com/chjj/term.js
|
|
5
|
-
* @license MIT
|
|
6
|
-
*
|
|
7
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
-
* in the Software without restriction, including without limitation the rights
|
|
10
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
-
* furnished to do so, subject to the following conditions:
|
|
13
|
-
*
|
|
14
|
-
* The above copyright notice and this permission notice shall be included in
|
|
15
|
-
* all copies or substantial portions of the Software.
|
|
16
|
-
*
|
|
17
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
-
* THE SOFTWARE.
|
|
24
|
-
*
|
|
25
|
-
* Originally forked from (with the author's permission):
|
|
26
|
-
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
-
* http://bellard.org/jslinux/
|
|
28
|
-
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
-
* The original design remains. The terminal itself
|
|
30
|
-
* has been extended to include xterm CSI codes, among
|
|
31
|
-
* other features.
|
|
32
|
-
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{j as t,d as ct,e as _,A as Qt,M as Oe,S as me,G as Zt,J as Dt,f as ut,B as at,I as Ce,w as en,D as tn,a as re,K as nn,N as rn,O as xt,Q as bt,c as Qe,U as an,V as sn,W as on,X as ln,Y as cn,Z as un,_ as We,$ as Bt,a0 as dt,a1 as dn,a2 as pn,a3 as it,h as Fe,a4 as $t,a5 as fn,a6 as mn,a7 as hn,g as Ze,a8 as Mt,l as gn,a9 as vt,x as xn,aa as et,p as bn,ab as vn,ac as Pe,ad as yn,ae as yt,af as kn,ag as jn}from"./index-Bd9gXx1g.js";import{R as o,r as Y}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as wn,o as Sn}from"./xterm-3VOAfa_q.js";function pt(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Cn=new RegExp(["\\x1b\\[[?>][0-9;]*c","\\x1b\\[\\??[0-9]+;[0-9]+R","\\x1b\\[\\??[0-9;]*n","\\x1b\\[\\??[0-9;]*\\$y","\\x1b\\][0-9][0-9;]*;[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)","\\x1bP[0-9]*[$+>][a-z|][^\\x1b]*\\x1b\\\\"].join("|"),"g"),In=e=>e.length>0&&e.replace(Cn,"")==="";function En(e,n){if(e.type!=="keydown")return null;const r=e.key.toLowerCase();return e.metaKey||e.ctrlKey&&e.shiftKey?r==="c"?n?"copy":null:r==="v"?"paste":null:null}const Tn=new Set(["image/png","image/jpeg","image/webp"]);function kt(e){return(e!=null&&e.files?Array.from(e.files):[]).filter(r=>Tn.has(r.type))}function Rn(e){return e!=null&&e.types?Array.from(e.types).includes("Files"):!1}const zn=96,An=50,Ln=2,Nn=2;function Dn(e,n,r){if(!Number.isFinite(e)||e<=0)return n;const i=r+Ln,s=Math.floor((e-zn-An-Nn*i)/i);return s>=n?n:Math.max(0,s-1)}const Bn=/enter to select/i,$n=/to navigate/i,Mn=/^\s*[❯>*]?\s*(\d)\.\s/;function Fn(e,n){var s;const r=e.join(`
|
|
2
|
-
`);if(!Bn.test(r)||!$n.test(r))return null;const i=e[n];return i?((s=Mn.exec(i))==null?void 0:s[1])??null:null}const Ft=10,Pt=24,ft=13,Pn=15;function st(e){return Number.isFinite(e)?Math.min(Pt,Math.max(Ft,Math.round(e))):ft}const On=[{id:"esc",label:"Esc",seq:"\x1B",aria:"Kirim Escape ke terminal"},{id:"tab",label:"Tab",seq:" ",aria:"Kirim Tab ke terminal"},{id:"up",label:"↑",seq:"\x1B[A",aria:"Kirim panah atas ke terminal"},{id:"down",label:"↓",seq:"\x1B[B",aria:"Kirim panah bawah ke terminal"},{id:"left",label:"←",seq:"\x1B[D",aria:"Kirim panah kiri ke terminal"},{id:"right",label:"→",seq:"\x1B[C",aria:"Kirim panah kanan ke terminal"},{id:"enter",label:"Enter",seq:"\r",aria:"Kirim Enter ke terminal"}],Wn=/[\x00-\x1f\x7f]/;function mt(e){return!e||Wn.test(e)?"control":[...e].length>1?"bulk":"text"}function Ot(e){return e?`\x1B[4m${e}\x1B[24m`:""}function Ve(e){return e>0?`\x1B[${e}D\x1B[K`:""}const _n=500,Kn=5e3,Hn=64,qn=2;function Wt(){return{pending:"",since:null,altScreen:!1,suspendedUntil:0,typed:"",unechoed:"",gen:0,parsed:0}}const Gn=e=>e.gen!==e.parsed;function Un(e,n){return{...e,altScreen:n}}const Yn=/(password|passphrase|pass|pin)\s*(?:for\s+\S+\s*)?:\s*$/i;function Xn(e){return Yn.test(e)}function _t(e,n,r,i,s){return!s||!r.deliverable||e.altScreen||i<e.suspendedUntil||mt(n)!=="text"||r.cursorX+qn+1>r.cols||r.line.slice(r.cursorX).trim().length>0?!1:!Xn(r.line.trimEnd())}function Vn(e,n){for(let r=n.length;r>0;r-=1)if(e.endsWith(n.slice(0,r)))return r;return 0}function Jn(e,n,r,i,s){const c=mt(n);if(c==="text"&&Gn(e)&&s&&r.deliverable&&!e.altScreen&&i>=e.suspendedUntil)return e.unechoed.length>=Hn?{state:e,write:""}:{state:{...e,unechoed:e.unechoed+n,typed:""},write:"",deferred:!0};if(!_t(e,n,r,i,s)){const h=i<e.suspendedUntil&&c==="text"?(e.typed+n).slice(-32):"";return h===e.typed&&!e.unechoed?{state:e,write:""}:{state:{...e,typed:h,unechoed:""},write:""}}return{state:{...e,pending:e.pending+n,unechoed:e.unechoed+n,since:null,typed:""},write:Ot(n)}}function Qn(e,n){if(!n)return!1;const r=n.slice(-Math.min(2,n.length));return e.endsWith(r)}function Zn(e,n,r){return r>=e.suspendedUntil?e.typed?{...e,typed:""}:e:Qn(n,e.typed)?{...e,suspendedUntil:0,typed:""}:e}function er(e,n,r){return{state:{...e,pending:"",since:null,gen:e.gen+1},write:Ve(e.pending.length)+n}}function tr(e,n,r,i,s){if(n!==e.gen)return{state:e,write:""};const c=r.line.slice(0,r.cursorX),y=Zn({...e,parsed:n},c,i);if(!y.unechoed)return{state:y,write:""};const h=y.unechoed.slice(Vn(c,y.unechoed));if(!h)return{state:{...y,unechoed:""},write:""};const b=rr({...y,pending:""},h,r,i,s);return b.write?{state:{...b.state,unechoed:h},write:b.write}:{state:{...y,pending:"",unechoed:""},write:""}}function nr(e,n){return!e.pending||e.since!==null?e:{...e,since:n}}function rr(e,n,r,i,s){if(!n)return{state:e,write:""};const c=[...n];for(let y=0;y<c.length;y+=1){const h={...r,cursorX:r.cursorX+y};if(!_t({...e},c[y],h,i,s))return{state:e,write:""}}return{state:{...e,pending:n,since:null},write:Ot(n)}}function ar(e,n){return!e.pending||e.since===null||n<e.since+_n?{state:e,write:"",missed:!1}:{state:{...e,pending:"",since:null,suspendedUntil:n+Kn,typed:"",unechoed:""},write:Ve(e.pending.length),missed:!0}}function jt(e){const n=((e==null?void 0:e.gen)??0)+1;return{...Wt(),gen:n,parsed:n}}const ir=16;function sr(e){let n="",r;const i=()=>{if(r&&(clearTimeout(r),r=void 0),!n)return;const s=n;n="",e(s)};return{push(s,c){if(!c||mt(s)!=="text"){i(),s&&e(s);return}n+=s,r||(r=setTimeout(i,ir))},flush:i,dispose(){i()}}}const or=250,lr=512,cr={"\x1B":"\\e","\r":"\\r","\n":"\\n"," ":"\\t","\b":"\\b","":"\\x7f"};function wt(e){let n="";for(const r of e){const i=cr[r];if(i){n+=i;continue}const s=r.codePointAt(0);n+=s<32||s===127?`\\x${s.toString(16).padStart(2,"0")}`:r}return n}function ur(e){const n=e.batchMs??or,r=e.max??lr;let i=null,s=[],c,y=!1;const h=()=>{if(c&&(clearTimeout(c),c=void 0),!s.length)return;const b=s;s=[],e.send(b)};return{record(b,I,v){if(y)return;const l=e.now();i===null&&(i=l);const j={t:l-i,k:b,v:I};v!==void 0&&(j.n=v),s.push(j),s.length>r&&(s=s.slice(s.length-r)),c||(c=setTimeout(h,n))},flush:h,dispose(){h(),y=!0}}}const dr="",pr=350,fr=1e3;function ht(){return{text:"",sentPrefix:""}}function mr(e,n){const r=[...e],i=[...n];let s=0;for(;s<r.length&&s<i.length&&r[s]===i[s];)s+=1;return s}function gt(e,n){const r=mr(e,n);return dr.repeat([...e].length-r)+[...n].slice(r).join("")}function hr(e,n){return{...e,text:n}}function gr(e){return{state:{...e,sentPrefix:e.text},send:gt(e.sentPrefix,e.text)}}function xr(e){return{state:ht(),send:gt(e.sentPrefix,e.text)+"\r"}}function br(e){return{state:ht(),send:gt(e.sentPrefix,e.text)}}function vr(e,n){return n.held?{kind:"held",text:"tertahan — Kirim di atas"}:n.n>0?{kind:"queued",text:`diantre ${n.n}`}:e==="open"?{kind:"sent",text:"terkirim"}:null}function yr({sessionId:e,send:n,external:r,linkState:i,queue:s}){const[c,y]=o.useState(""),h=o.useRef(ht()),b=o.useRef(n);b.current=n;const I=o.useRef(void 0),v=o.useRef(void 0),l=()=>{clearTimeout(I.current),I.current=void 0,clearTimeout(v.current),v.current=void 0},j=E=>{l(),h.current=E.state,E.send&&b.current(E.send)},w=()=>j(gr(h.current));r.current=()=>{j(br(h.current)),y("")},o.useEffect(()=>()=>{r.current=()=>{}},[r]),o.useEffect(()=>l,[]);const k=E=>{h.current=hr(h.current,E),y(E),clearTimeout(I.current),I.current=setTimeout(w,pr),v.current||(v.current=setTimeout(w,fr))},S=()=>{j(xr(h.current)),y("")},m=vr(i,s);return t.jsxs("div",{className:"hn-terminal-composer",children:[t.jsx(ct,{size:"lg",mono:!0,value:c,"data-testid":"terminal-composer","aria-label":`Ketik untuk sesi ${e}`,placeholder:"mis. pnpm vitest --run",autoCapitalize:"off",autoCorrect:"off",spellCheck:!1,autoComplete:"off",enterKeyHint:"send",style:{flex:"1 1 160px",minWidth:0},onChange:E=>k(E.target.value),onBlur:()=>w(),onKeyDown:E=>{E.key!=="Enter"||E.nativeEvent.isComposing||(E.preventDefault(),S())}}),m&&t.jsx("span",{"data-testid":"terminal-composer-status",className:`hn-terminal-composer-status hn-terminal-composer-status--${m.kind}`,children:m.text})]})}const Kt=[500,1e3,2e3,4e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3],St=Kt.length,kr=4096,jr=/[\r\n]/;function Ht({sessionId:e,onExit:n,onPhases:r,fontSize:i=ft,showKeys:s=!1,predict:c=!0,diag:y=!1}){const h=o.useRef(null),b=o.useRef(i);b.current=i;const I=o.useRef(c);I.current=c;const v=o.useRef(y);v.current=y;const l=o.useRef(null),j=o.useRef(n);j.current=n;const w=o.useRef(r);w.current=r;const[k,S]=o.useState({state:"connecting"}),[m,E]=o.useState({n:0,held:!1,full:!1}),L=o.useRef(()=>{}),F=o.useRef(()=>{}),K=o.useRef(()=>{}),g=o.useRef(()=>{}),C=o.useRef(()=>{}),d=o.useRef(()=>{});return o.useEffect(()=>{const u=h.current;if(!u)return;const N=getComputedStyle(document.documentElement),O=(p,R)=>N.getPropertyValue(p).trim()||R,x=new wn({fontFamily:O("--font-mono","monospace"),fontSize:st(b.current),cursorBlink:!0,macOptionClickForcesSelection:!0,theme:{background:O("--term-bg","#1c1810"),foreground:O("--term-fg","#e9e0cd")}}),q=new Sn;x.loadAddon(q),x.open(u);const ae=()=>{const p=u.getBoundingClientRect();return p.width>0&&p.height>0?p:null};ae()&&q.fit();let z,ie=!1,J=0,se,oe=!1;const ue=p=>{(z==null?void 0:z.readyState)===WebSocket.OPEN&&z.send(JSON.stringify(p))};l.current={term:x,fit:q,send:ue};const be=ur({now:()=>Date.now(),send:p=>ue({t:"diag",ev:p})}),G=(p,R,D)=>{v.current&&be.record(p,R,D)};let Z="",X=!1,ee=!1,he=0,te=0,ve=!1;const ne=new Map,Q=p=>{if(he+=1,te+=1,v.current){if(ne.size>256)for(const R of[...ne.keys()].slice(0,128))ne.delete(R);ne.set(he,Date.now())}ue({t:"in",d:p,seq:he})},H=()=>E({n:Z.length,held:X,full:ee}),De=p=>{if(!X&&!Z&&(z==null?void 0:z.readyState)===WebSocket.OPEN){Q(p);return}if(!(ve||In(p))){if(Z.length+p.length>kr){ee=!0,H();return}Z+=p,H()}};let $=Wt();const de=sr(De),Je=p=>de.push(p,!1);F.current=Je;const U=p=>{C.current(),Je(p)};d.current=U;const le=()=>{var R;const p=x.buffer.active;return{cursorX:p.cursorX,cols:x.cols,deliverable:!ve&&!ee,line:((R=p.getLine(p.viewportY+p.cursorY))==null?void 0:R.translateToString(!0))??""}},ye=()=>{te===0&&(z==null?void 0:z.readyState)===WebSocket.OPEN&&($=nr($,Date.now()))},ce=()=>{if(!Z||(z==null?void 0:z.readyState)!==WebSocket.OPEN){H();return}const p=Z;Z="",ee=!1,H(),Q(p)},pe=()=>{if(de.flush(),!Z){H();return}if(jr.test(Z)){X=!0,H();return}ce()};K.current=()=>{X=!1,ce()},g.current=()=>{Z="",X=!1,ee=!1,H()};const Be=p=>{C.current();const R=$.pending.length>0;G("data",wt(p));const D=le(),P=Jn($,p,D,Date.now(),I.current);$=P.state,P.write?x.write(P.write):P.deferred?G("pred","tangguh: frame server in flight"):G("pred",`tolak cx=${D.cursorX}/${D.cols} alt=${$.altScreen?1:0} deliverable=${D.deliverable?1:0} suspend=${Math.max(0,$.suspendedUntil-Date.now())}`),de.push(p,R||P.write.length>0||P.deferred===!0)},ke=setInterval(()=>{const p=ar($,Date.now());$=p.state,p.write&&x.write(p.write)},100),$e=()=>{_.issueWsTicket(`terminal:${e}`).then(({ticket:p})=>{if(ie)return;const R=location.protocol==="https:"?"wss:":"ws:",D=new WebSocket(`${R}//${location.host}${Qt.terminalWs(e)}`,[`hanoman-ticket.${p}`]);z=D,D.onopen=()=>{J=0,he=0,te=0;const P=Ve($.pending.length);P&&x.write(P),$=jt($),S({state:"open"}),ae()&&((typeof window.matchMedia!="function"||window.matchMedia("(hover: hover) and (pointer: fine)").matches)&&x.focus(),ue({t:"resize",cols:x.cols,rows:x.rows})),pe()},D.onmessage=P=>{var a;const B=JSON.parse(P.data);if(B.t==="data"){const f=er($,B.d??"");$=f.state;const T=$.gen;x.write(f.write,()=>{if(ie)return;const A=tr($,T,le(),Date.now(),I.current);$=A.state,A.write&&x.write(A.write),ye()}),ye()}else if(B.t==="ack"){if(te=Math.max(0,te-1),typeof B.seq=="number"){const f=ne.get(B.seq);f!==void 0&&(ne.delete(B.seq),G("ack",String(B.seq),Date.now()-f))}ye()}else B.t==="phase"?(a=w.current)==null||a.call(w,B.phases??[],B.complete===!0):B.t==="alt"?$=Un($,B.on===!0):B.t==="exit"&&(oe=!0,x.write(`\r
|
|
3
|
-
\x1B[33m— sesi berakhir (exit ${B.code}) —\x1B[0m\r
|
|
4
|
-
`),j.current(B.code??0))},D.onclose=P=>{if(!(ie||oe)){if(P.code===4004){ve=!0;const B=Ve($.pending.length);B&&x.write(B),$=jt($),Z="",X=!1,ee=!1,H(),S({state:"gone"});return}Te()}},D.onerror=()=>{}}).catch(()=>{ie||(x.write(`\r
|
|
5
|
-
\x1B[31mWebSocket admission gagal\x1B[0m\r
|
|
6
|
-
`),Te())})},Te=()=>{if(J>=St){S({state:"lost"});return}const p=Kt[J];J+=1,S({state:"retrying",attempt:J}),se=setTimeout($e,p)};L.current=()=>{ie||(clearTimeout(se),J=0,S({state:"retrying",attempt:1}),$e())},$e(),x.attachCustomKeyEventHandler(p=>{var D,P;const R=En(p,x.hasSelection());return R==="copy"?((D=navigator.clipboard)==null||D.writeText(x.getSelection()),!1):R==="paste"?((P=navigator.clipboard)==null||P.readText().then(B=>{B&&U(B)}),!1):!0}),x.attachCustomWheelEventHandler(p=>{if(!p.shiftKey)return!0;const R=ae();if(!R||x.rows<=0)return!0;const D=R.height/x.rows,P=Math.trunc(p.deltaY/D)||Math.sign(p.deltaY);return P&&x.scrollLines(P),!1});const Re=x.onData(Be),M=x.textarea,Ke=p=>G("key",p.key,p.keyCode),ge=p=>G("comp",`${p.type}:${wt(p.data??"")}`);M==null||M.addEventListener("keydown",Ke),M==null||M.addEventListener("compositionstart",ge),M==null||M.addEventListener("compositionupdate",ge),M==null||M.addEventListener("compositionend",ge);let fe=null,je=0,Ie=!1;const Ee=()=>{fe=null,je=0,Ie=!1},Me=p=>{if(p.touches.length!==1){Ee();return}fe=p.touches[0].clientY,je=0,Ie=!1},He=p=>{if(fe===null||p.touches.length!==1){Ee();return}const R=ae();if(!R||x.rows<=0)return;const D=p.touches[0].clientY;je+=fe-D,fe=D;const P=R.height/x.rows,B=Math.trunc(je/P);B!==0&&(x.scrollLines(B),je-=B*P,Ie=!0),p.preventDefault()},qe=p=>{var A,V;const R=fe!==null&&!Ie,D=((V=(A=p.changedTouches)==null?void 0:A[0])==null?void 0:V.clientY)??fe;if(Ee(),!R||D===null||D===void 0)return;const P=ae();if(!P||x.rows<=0)return;const B=Math.floor((D-P.top)/(P.height/x.rows)),a=x.buffer.active,f=Array.from({length:x.rows},(we,xe)=>{var Ae;return((Ae=a.getLine(a.viewportY+xe))==null?void 0:Ae.translateToString(!0))??""}),T=Fn(f,B);T&&U(T)},Ge=async p=>{for(const R of p)try{const{path:D}=await _.uploadTerminalAttachment(e,R);U(`${D} `)}catch(D){x.write(`\r
|
|
7
|
-
\x1B[31mlampiran gagal: ${D.message}\x1B[0m\r
|
|
8
|
-
`)}},Ue=p=>{const R=kt(p.clipboardData);R.length&&(p.preventDefault(),Ge(R))},Ye=p=>{Rn(p.dataTransfer)&&p.preventDefault()},ze=p=>{const R=kt(p.dataTransfer);R.length&&(p.preventDefault(),Ge(R))};u.addEventListener("paste",Ue),u.addEventListener("dragover",Ye),u.addEventListener("drop",ze),u.addEventListener("touchstart",Me,{passive:!0}),u.addEventListener("touchmove",He,{passive:!1}),u.addEventListener("touchend",qe,{passive:!0}),u.addEventListener("touchcancel",Ee,{passive:!0});const W=new ResizeObserver(p=>{var D;const R=((D=p[0])==null?void 0:D.contentRect)??u.getBoundingClientRect();R.width<=0||R.height<=0||(q.fit(),ue({t:"resize",cols:x.cols,rows:x.rows}))});return W.observe(u),()=>{ie=!0,clearTimeout(se),L.current=()=>{},F.current=()=>{},d.current=()=>{},K.current=()=>{},g.current=()=>{},l.current=null,u.removeEventListener("paste",Ue),u.removeEventListener("dragover",Ye),u.removeEventListener("drop",ze),u.removeEventListener("touchstart",Me),u.removeEventListener("touchmove",He),u.removeEventListener("touchend",qe),u.removeEventListener("touchcancel",Ee),W.disconnect(),clearInterval(ke),de.dispose(),be.dispose(),M==null||M.removeEventListener("keydown",Ke),M==null||M.removeEventListener("compositionstart",ge),M==null||M.removeEventListener("compositionupdate",ge),M==null||M.removeEventListener("compositionend",ge),Re.dispose(),z==null||z.close(),x.dispose()}},[e]),o.useEffect(()=>{const u=l.current,N=h.current;if(!u||!N)return;const O=st(i);if(u.term.options.fontSize===O)return;u.term.options.fontSize=O;const x=N.getBoundingClientRect();x.width<=0||x.height<=0||(u.fit.fit(),u.send({t:"resize",cols:u.term.cols,rows:u.term.rows}))},[i]),o.useEffect(()=>{const u=l.current,N=h.current;if(!u||!N)return;const O=N.getBoundingClientRect();O.width<=0||O.height<=0||(u.fit.fit(),u.send({t:"resize",cols:u.term.cols,rows:u.term.rows}))},[s]),t.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[(k.state!=="open"&&k.state!=="connecting"||m.held||m.full)&&t.jsxs("div",{"data-testid":"terminal-link",style:{display:"flex",alignItems:"center",gap:8,flex:"0 0 auto",flexWrap:"wrap",padding:"3px 8px",fontFamily:"var(--font-mono)",fontSize:11,background:k.state==="retrying"||m.held?"var(--status-warn-tint)":"var(--status-err-tint)",color:"var(--text-body)"},children:[k.state==="retrying"&&t.jsxs("span",{children:["menyambung ulang… (",k.attempt,"/",St,")"]}),k.state==="gone"&&t.jsx("span",{children:"sesi tidak ditemukan di tmux"}),k.state==="lost"&&t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"terputus"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>L.current(),children:"Sambungkan lagi"})]}),m.n>0&&!m.held&&t.jsxs("span",{"data-testid":"terminal-queue",children:[m.n," ketikan diantre"]}),m.held&&t.jsxs(t.Fragment,{children:[t.jsxs("span",{"data-testid":"terminal-held",children:[m.n," ketikan tertahan — belum dikirim"]}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>K.current(),children:"Kirim"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>g.current(),children:"Buang"})]}),m.full&&t.jsx("span",{"data-testid":"terminal-queue-full",children:"antrean penuh"})]}),t.jsx("div",{ref:h,"data-testid":"terminal-host",style:{flex:1,minHeight:0,width:"100%",background:"var(--term-bg)",padding:8,borderRadius:"var(--radius-sm)",touchAction:"pan-x pinch-zoom",overscrollBehavior:"contain"}}),s&&t.jsx(yr,{sessionId:e,send:u=>F.current(u),external:C,linkState:k.state,queue:m}),s&&t.jsx(wr,{onKey:u=>d.current(u)})]})}function wr({onKey:e}){return t.jsx("div",{className:"hn-terminal-keys",role:"group","aria-label":"Tombol terminal",children:On.map(n=>t.jsx("button",{type:"button",className:"hn-terminal-key","aria-label":n.aria,title:n.aria,onClick:()=>e(n.seq),children:n.label},n.id))})}const Ct=20;function Sr(e,n){if(!n)return"—";const r=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(r)||r<0)return"—";const i=Math.round(r/1e3);if(i<60)return`${i} dtk`;const s=Math.round(i/60);return s<60?`${s} mnt`:`${Math.floor(s/60)} jam ${s%60} mnt`}function Cr(e){switch(pt(e)){case"running":return{label:"berjalan",tone:"neutral"};case"interrupted":return{label:"terputus",tone:"warn"};case"failed":return{label:`exit ${e.exitCode}`,tone:"err"};default:return{label:"selesai",tone:"ok"}}}const qt=e=>pt(e)==="interrupted"?"—":Sr(e.startedAt,e.endedAt),Gt=e=>Dt[e]??e;function Ir({projects:e,onClose:n,onRestart:r}){const[i,s]=o.useState([]),[c,y]=o.useState(0),[h,b]=o.useState(1),[I,v]=o.useState(!1),[l,j]=o.useState(""),[w,k]=o.useState(""),[S,m]=o.useState(""),[E,L]=o.useState(""),[F,K]=o.useState(null);o.useEffect(()=>{const d=setTimeout(()=>L(S.trim()),250);return()=>clearTimeout(d)},[S]),o.useEffect(()=>{b(1)},[l,w,E]),o.useEffect(()=>{let d=!0;return v(!0),_.listSessionHistory({projectId:l||void 0,kind:w||void 0,q:E||void 0,page:h,limit:Ct}).then(u=>{d&&(y(u.total),s(u.items))}).catch(()=>{d&&(s([]),y(0))}).finally(()=>{d&&v(!1)}),()=>{d=!1}},[l,w,E,h]);const g=tn(c,h,Ct),C=d=>{var u;return((u=e.find(N=>N.id===d))==null?void 0:u.name)??d};return t.jsxs(Oe,{open:!0,title:"Riwayat sesi",icon:"history",onClose:n,width:900,children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ct,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:S,onChange:d=>m(d.target.value),style:{flex:"1 1 200px"}}),t.jsx(me,{size:"sm","aria-label":"Filter project",value:l,onChange:d=>j(d.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(d=>({value:d.id,label:d.name})))}),t.jsx(me,{size:"sm","aria-label":"Filter jenis",value:w,onChange:d=>k(d.target.value),options:[{value:"",label:"Semua jenis"}].concat(Zt.map(d=>({value:d,label:Dt[d]})))})]}),i.length===0&&!I?t.jsx(ut,{kind:"empty",icon:"history",title:"Belum ada riwayat sesi",hint:"Riwayat terisi sendiri saat sesi terminal dibuka lalu ditutup — termasuk sesi backlog, terminal biasa, dan sesi project-level."}):t.jsxs("div",{style:{display:"flex",flexDirection:"column",maxHeight:"60vh",overflowY:"auto"},children:[i.map(d=>{const u=Cr(d);return t.jsx("button",{onClick:()=>K(d),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",flex:"0 0 132px"},children:new Date(d.startedAt).toLocaleString("id-ID")}),t.jsx(at,{size:"sm",tone:"neutral",children:Gt(d.kind)}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.title??d.specId??C(d.projectId)}),d.transcriptBytes!==null&&t.jsx(Ce,{name:"file-text",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-muted)",flex:"0 0 72px"},children:qt(d)}),t.jsx(at,{size:"sm",tone:u.tone,children:u.label})]})},d.id)}),I&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(en,{page:g.page,pageCount:g.pageCount,total:c,from:g.from,to:g.to,onPage:b,unit:"sesi"}),F&&t.jsx(Er,{row:F,projectName:C(F.projectId),onBack:()=>K(null),onRestart:r})]})}function Er({row:e,projectName:n,onBack:r,onRestart:i}){const[s,c]=o.useState(null),[y,h]=o.useState("idle");o.useEffect(()=>{if(e.transcriptBytes===null){h("none"),c(null);return}let v=!0;return h("loading"),_.sessionTranscript(e.id).then(l=>{v&&(c(l.text),h("idle"))}).catch(()=>{v&&(c(null),h("error"))}),()=>{v=!1}},[e.id,e.transcriptBytes]);const b=pt(e)==="interrupted",I=[["Project",n],["Sesi",e.sessionId],["Jenis",Gt(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[b?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...b&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",qt(e)],["Direktori",e.cwd]];return e.specId&&I.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&I.push(["Branch",e.branch]),t.jsxs(Oe,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:r,width:1e3,children:[t.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",marginBottom:10},children:[t.jsx(re,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:r,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),s&&t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var v;return void((v=navigator.clipboard)==null?void 0:v.writeText(s))},children:"Salin transkrip"}),nn(e.kind)&&t.jsx(re,{size:"sm",leftIcon:"play",onClick:()=>i(e),children:"Mulai lagi"})]}),b&&t.jsxs(rn,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",style:{marginBottom:12},children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",t.jsx("code",{children:"tmux kill-server"}),", atau host mati), jadi sesi ini tak meninggalkan exit code dan transkripnya kemungkinan besar tak sempat diambil — capture berjalan tepat sebelum pane dibunuh, dan di jalur ini sudah tak ada pane untuk dibaca. Periksa worktree & branch sesi ini sebelum menganggapnya selesai, lalu mulai lagi bila pekerjaannya belum tuntas."]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"4px 12px",marginBottom:12,fontSize:12},children:I.map(([v,l])=>t.jsxs(o.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:v}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:l})]},v))}),y==="loading"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:"memuat transkrip…"}),y==="none"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:b?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),y==="error"&&t.jsx("div",{style:{fontSize:12,color:"var(--clay-600)"},children:"Transkrip tak terbaca lagi di server."}),s!==null&&t.jsx("pre",{style:{maxHeight:"52vh",overflow:"auto",margin:0,padding:10,background:"var(--bone-200)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",fontFamily:"var(--font-mono)",fontSize:11,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:s})]})}function Tr({open:e,projectId:n,projectName:r,onClose:i,onCreated:s}){var K;const[c,y]=o.useState("claude"),[h,b]=o.useState("claude-opus-5"),[I,v]=o.useState("xhigh"),[l,j]=o.useState({claude:{model:"claude-sonnet-5",effort:"medium"},codex:{...xt}}),[w,k]=o.useState(!1),[S,m]=o.useState(null);o.useEffect(()=>{e&&(_.getSettings().then(g=>{const C={claude:{model:g.model,effort:g.effort},codex:{...xt,...g.codex??{}}},d=g.agent==="codex"?"codex":"claude",u=bt(C,d);j(C),y(d),b(u.model),v(u.effort)}).catch(()=>{}),_.getCodexVersion().then(g=>m(g.version)).catch(()=>{}))},[e]);const E=g=>{y(g);const C=bt(l,g);b(C.model),v(C.effort)},L=g=>{b(g),v(C=>c==="codex"?cn(g,C):un(g,C))};async function F(){k(!0);try{const{id:g}=await _.createTerminal(n,{agent:c,model:h,effort:I});s(g),i()}catch{}finally{k(!1)}}return t.jsxs(Oe,{open:e,onClose:i,icon:"plus",eyebrow:r,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(re,{variant:"ghost",onClick:i,children:"Batal"}),t.jsx(re,{leftIcon:"play",disabled:w,onClick:()=>void F(),children:"Buka sesi"})]}),children:[t.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Runtime untuk sesi ini. Default dari setelan global; ubah bila perlu. Sesi lahir dengan pilihan ini untuk seluruh hidupnya — ",t.jsx("code",{children:"/model"})," di terminal tetap bisa mengubahnya."]}),t.jsx(Qe,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(me,{"aria-label":"Agen",value:c,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:g=>E(g.target.value)})}),t.jsx(Qe,{label:"Model",children:t.jsx(me,{"aria-label":"Model",value:h,style:{width:"100%"},options:an(c).map(g=>({value:g.id,label:g.label})),onChange:g=>L(g.target.value)})}),t.jsx(Qe,{label:"Effort",children:t.jsx(me,{"aria-label":"Effort",value:I,style:{width:"100%"},options:sn(c,h).map(g=>({value:g,label:g})),onChange:g=>v(g.target.value)})}),c==="codex"&&on(h,S)&&t.jsxs("div",{"data-testid":"codex-version-note",style:{fontSize:12,lineHeight:1.5,marginBottom:12,padding:"8px 10px",borderRadius:8,background:"var(--warn-bg, #fdf6e3)",color:"var(--text-muted)"},children:["Codex CLI terpasang ",t.jsx("b",{children:S}),", sedangkan ",t.jsx("b",{children:h})," butuh ",t.jsx("b",{children:(K=ln(h))==null?void 0:K.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const Rr=()=>({rows:1,cols:1,cells:[null]}),It=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function Et(e){const n=e.cols+1,r=[];for(let i=0;i<e.rows;i++)for(let s=0;s<n;s++)r.push(s<e.cols?e.cells[i*e.cols+s]??null:null);return{rows:e.rows,cols:n,cells:r}}function Tt(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const r=[...e.cells];return r.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:r}}function Rt(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const r=e.cols-1,i=[];for(let s=0;s<e.rows;s++)for(let c=0;c<e.cols;c++)c!==n&&i.push(e.cells[s*e.cols+c]??null);return{rows:e.rows,cols:r,cells:i}}function ot(e,n,r){if(n<0||n>=e.cells.length)return e;const i=e.cells.map(s=>r!==null&&s===r?null:s);return i[n]=r,{...e,cells:i}}const zr=(e,n)=>({...e,cells:e.cells.map(r=>r&&n.has(r)?r:null)}),Ut=e=>({id:crypto.randomUUID(),name:e,layout:Rr()});function zt(){const e=Ut("Utama");return{groups:[e],active:e.id}}const _e=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function Ar(e,n){const r=Ut(n);return{groups:[...e.groups,r],active:r.id}}const Lr=(e,n,r)=>({...e,groups:e.groups.map(i=>i.id===n?{...i,name:r}:i)});function Nr(e,n){if(e.groups.length===1)return e;const r=e.groups.filter(i=>i.id!==n);return r.length===e.groups.length?e:{groups:r,active:e.active===n?r[0].id:e.active}}const Dr=(e,n)=>e.groups.some(r=>r.id===n)?{...e,active:n}:e;function Se(e,n){const r=_e(e);return{...e,groups:e.groups.map(i=>i.id===r.id?{...i,layout:n(i.layout)}:i)}}function lt(e,n,r){const i=_e(e),s=r===null?e.groups:e.groups.map(c=>c.id===i.id?c:{...c,layout:ot(c.layout,c.layout.cells.indexOf(r),null)});return{...e,groups:s.map(c=>c.id===i.id?{...c,layout:ot(c.layout,n,r)}:c)}}function Le(e,n){const r=_e(e).layout.cells.indexOf(null);return r===-1?e:lt(e,r,n)}const Br=(e,n)=>({...e,groups:e.groups.map(r=>({...r,layout:ot(r.layout,r.layout.cells.indexOf(n),null)}))}),At=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(r=>r!==null))),Lt=(e,n)=>({...e,groups:e.groups.map(r=>({...r,layout:zr(r.layout,n)}))}),Yt="hanoman.terminal.workspace",Xt="hanoman.terminal.layout",Ne=e=>We.parse({version:1,groups:e.groups});function Xe(e,n){const r=e.groups,i=n&&r.some(s=>s.id===n)?n:r[0].id;return{groups:r,active:i}}function $r(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const r=n,i=We.parse({version:1,groups:r.groups});return{workspace:i,active:typeof r.active=="string"&&i.groups.some(s=>s.id===r.active)?r.active:i.groups[0].id}}catch{return null}}function Mr(){try{const e=localStorage.getItem(Yt);if(e)return $r(e);const n=localStorage.getItem(Xt);if(!n)return null;const r=JSON.parse(n),i={id:crypto.randomUUID(),name:"Utama",layout:r};return{workspace:We.parse({version:1,groups:[i]}),active:i.id}}catch{return null}}function tt(){try{localStorage.removeItem(Yt),localStorage.removeItem(Xt)}catch{}}const Vt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Fr(e){try{const n=localStorage.getItem(Vt(e));if(!n)return null;const r=JSON.parse(n),i=We.parse(r.workspace);if(!Number.isInteger(r.revision)||(r.revision??-1)<0)return null;const s=typeof r.active=="string"&&i.groups.some(c=>c.id===r.active)?r.active:i.groups[0].id;return{workspace:i,revision:r.revision,active:s}}catch{return null}}function nt(e,n){try{const r=We.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const i=r.groups.some(s=>s.id===n.active)?n.active:r.groups[0].id;localStorage.setItem(Vt(e),JSON.stringify({workspace:r,revision:n.revision,active:i}))}catch{}}function rt(e){if(!(e instanceof dt)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const r=dn.safeParse(n.current);return r.success?r.data:null}function Pr(e){const n=Y.useRef(null);n.current||(n.current=zt());const[r,i]=Y.useState(n.current),[s,c]=Y.useState("loading"),[y,h]=Y.useState(null),[b,I]=Y.useState(!1),v=Y.useRef(r),l=Y.useRef(0),j=Y.useRef(!1),w=Y.useRef(Promise.resolve()),k=Y.useRef(0),S=Y.useCallback(d=>{v.current=d,i(d)},[]),m=Y.useCallback(d=>{j.current=d,I(d)},[]),E=Y.useCallback(d=>{const u=w.current.then(d,d);return w.current=u.then(()=>{},()=>{}),u},[]),L=Y.useCallback((d,u="ready",N=null,O=v.current.active)=>{const x=d.workspace?Xe(d.workspace,O):zt();l.current=d.revision,S(x),c(u),h(N),m(!0),d.workspace&&nt(e,{workspace:d.workspace,revision:d.revision,active:x.active})},[S,m,e]),F=Y.useCallback(d=>{const u=Fr(e);u&&(l.current=u.revision,S(Xe(u.workspace,u.active))),m(!1),c("recovering"),h(d instanceof Error?d.message:"Layout server belum tersambung")},[S,m,e]),K=Y.useCallback(()=>E(async()=>{try{L(await _.getTerminalWorkspace())}catch(d){F(d)}}),[L,E,F]);Y.useEffect(()=>{const d=++k.current;return c("loading"),h(null),m(!1),E(async()=>{try{const u=await _.getTerminalWorkspace();if(d!==k.current)return;if(u.workspace){L(u),tt();return}const N=Mr();if(!N){L(u);return}try{const O=await _.putTerminalWorkspace({baseRevision:u.revision,workspace:N.workspace});if(d!==k.current)return;S(Xe(O.workspace,N.active)),l.current=O.revision,nt(e,{workspace:O.workspace,revision:O.revision,active:N.active}),tt(),c("ready"),h(null),m(!0)}catch(O){const x=rt(O);x!=null&&x.workspace?(L(x,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),tt()):F(O)}}catch(u){d===k.current&&F(u)}}),()=>{k.current+=1}},[L,E,F,S,m,e]),Y.useEffect(()=>{const d=()=>{K()},u=()=>{document.visibilityState==="visible"&&K()};return window.addEventListener("focus",d),document.addEventListener("visibilitychange",u),()=>{window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",u)}},[K]);const g=Y.useCallback(d=>E(async()=>{if(!j.current)return!1;const u=d(v.current);let N,O;try{N=Ne(u),O=Ne(v.current)}catch{return c("conflict"),h("Layout tidak valid dan tidak disimpan"),!1}if(Bt(N,O))return!0;try{return L(await _.putTerminalWorkspace({baseRevision:l.current,workspace:N}),"ready",null,u.active),!0}catch(x){const q=rt(x);if(!(q!=null&&q.workspace))return F(x),!1;const ae=d(Xe(q.workspace,v.current.active));try{const z=await _.putTerminalWorkspace({baseRevision:q.revision,workspace:Ne(ae)});return L(z,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",ae.active),!0}catch(z){if(!rt(z)&&!(z instanceof dt&&z.status===409))return F(z),!1;try{L(await _.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(ie){F(ie)}return!1}}}),[L,E,F]),C=Y.useCallback(d=>{const u=Dr(v.current,d);S(u);const N=Ne(u);nt(e,{workspace:N,revision:l.current,active:u.active})},[S,e]);return{workspace:r,status:s,message:y,writable:b,mutate:g,setActive:C,refresh:K}}function Zr({userId:e="test-user",projects:n,backlog:r=[],focusSession:i,startedSession:s,onStartedSessionHandled:c,onStartBacklog:y,onOpenReview:h,onOpenSessionReview:b,titleOf:I,onIntegrate:v,onIntegrateSession:l,specOf:j}){var B;const[w,k]=o.useState([]),[S,m]=o.useState([]),E=Pr(e),{workspace:L,status:F,message:K,writable:g,mutate:C,setActive:d,refresh:u}=E,[N,O]=Fe("terminal","project",((B=n[0])==null?void 0:B.id)??"",bn),x=$t(),[q,ae]=Fe("terminal","fontSize",x?Pn:ft,xn),[z,ie]=Fe("terminal","keys",x,et),[J,se]=Fe("terminal","predict",!0,et),[oe,ue]=Fe("terminal","diag",!1,et),be=a=>ae(f=>st(f+a)),[G,Z]=o.useState(!1),[X,ee]=o.useState(null),[he,te]=o.useState(!1),[ve,ne]=o.useState(null),[Q,H]=o.useState(!1),[De,$]=o.useState(!1),de=fn(),U=mn()==="mobile",[le,ye]=o.useState(0),[ce,pe]=o.useState(null),Be=o.useRef(null),[ke,$e]=o.useState(!1);o.useEffect(()=>{_.listTerminals().then(a=>{k(a),$e(!0)}).catch(()=>{})},[]),o.useEffect(()=>hn(a=>{a.t==="sessions"?k(a.sessions):a.t==="cleanups"&&m(a.cleanups)}),[]),o.useEffect(()=>{if(!ke||!g)return;const a=new Set(w.map(T=>T.id)),f=Lt(L,a);Bt(Ne(f),Ne(L))||C(T=>Lt(T,a))},[C,w,ke,g,L]),o.useEffect(()=>{!s||s.specId==null||!ke||(k(a=>a.some(f=>f.id===s.id)?a:[...a,{...s,cwd:"",exited:!1}]),pe(s.id),c==null||c())},[c,ke,s]),o.useEffect(()=>{if(!i){Be.current=null;return}!ke||Be.current===i||w.some(a=>a.id===i&&!a.exited)&&(Be.current=i,pe(i))},[i,w,ke]),o.useEffect(()=>{if(!ce)return;const a=L.groups.find(f=>f.layout.cells.includes(ce));if(a){a.id!==L.active&&d(a.id);return}g&&C(f=>{if(At(f).has(ce))return f;const T=Le(f,ce);return T!==f||!U?T:lt(f,le,ce)})},[le,U,C,ce,d,g,L]),o.useEffect(()=>{X&&!w.some(a=>a.id===X)&&ee(null)},[X,w]);const Te=S.filter(a=>a.error),Re=a=>w.find(f=>f.id===a)??null,M=a=>{var f;return((f=n.find(T=>T.id===a))==null?void 0:f.name)??a};function Ke(a){k(f=>f.some(T=>T.id===a)?f:[...f,{id:a,projectId:N,cwd:"",exited:!1}]),C(f=>Le(f,a)),pe(a)}async function ge(){if(!N)return;const{id:a}=await _.createShell(N);k(f=>[...f,{id:a,projectId:N,cwd:"",exited:!1}]),C(f=>Le(f,a)),pe(a)}async function fe(a,f){if(y&&!f){te(!1),ne(null),y(a);return}const T=jn(a.source);try{const{id:A}=await _.startSession({spec:a.id,flow:T,...f?{force:f}:{}});k(V=>V.some(we=>we.id===A)?V:[...V,{id:A,projectId:a.projectId,specId:a.id,flow:T,cwd:"",exited:!1}]),C(V=>Le(V,A)),pe(A),te(!1),ne(null)}catch(A){if(de.offerRetry(A,a.id,we=>fe(a,we)))return;const V=A instanceof dt&&(A.status===400||A.status===422);ne(`${a.id} · gagal mulai${V?" · project belum punya repoDir":""}`)}}async function je(a,f){try{const T=a.specId?await _.startSession({spec:a.specId,flow:a.flow??"feature",...f?{force:f}:{}}):a.kind==="shell"?await _.createShell(a.projectId):a.kind==="terminal"?await _.createTerminal(a.projectId,{agent:a.agent==="codex"?"codex":"claude",...a.model?{model:a.model}:{},...a.effort?{effort:a.effort}:{}}):await(f?_.createTerminalFlow(a.projectId,a.kind,{force:f}):_.createTerminalFlow(a.projectId,a.kind));k(A=>A.some(V=>V.id===T.id)?A:[...A,{id:T.id,projectId:a.projectId,specId:a.specId??void 0,cwd:"",exited:!1}]),C(A=>Le(A,T.id)),pe(T.id),$(!1)}catch(T){if((a.specId||a.kind!=="shell"&&a.kind!=="terminal")&&de.offerRetry(T,`${a.projectId} · ${a.title??a.specId??a.kind}`,A=>je(a,A)))return}}const Ie=new Set(w.filter(a=>a.specId&&!a.exited).map(a=>a.specId)),Ee=r.filter(a=>a.stage!=="done"&&!Ie.has(a.id));function Me(a){k(f=>f.filter(T=>T.id!==a)),_.deleteTerminal(a).catch(()=>{})}const He=o.useCallback((a,f)=>{k(T=>T.map(A=>A.id===a?{...A,exited:!0,exitCode:f}:A))},[]),qe=(a,f)=>{ye(a),C(T=>lt(T,a,f))},Ge=a=>{pe(a),C(f=>Le(f,a))},Ue=a=>{C(f=>Br(f,a))},Ye=At(L),ze=w.filter(a=>!Ye.has(a.id)),W=_e(L).layout;o.useEffect(()=>{if(!ce)return;const a=W.cells.indexOf(ce);a<0||(ye(a),pe(null))},[W.cells,ce]),o.useEffect(()=>{le>=W.cells.length&&ye(Math.max(0,W.cells.length-1))},[le,W.cells.length]);const p=W.rows===1&&W.cols===1&&!W.cells[0]&&w.length===0,R=t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:10,marginBottom:10},children:[t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ukuran teks terminal"}),t.jsx(Ze,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:q<=Ft,onClick:()=>be(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[q,"px"]}),t.jsx(Ze,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:q>=Pt,onClick:()=>be(1)})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Papan tombol layar (Esc · panah · Enter)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":z,onClick:()=>ie(a=>!a),children:z?"Sembunyikan":"Tampilkan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ketik responsif (huruf tampil sebelum echo server)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":J,"aria-label":`${J?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>se(a=>!a),children:J?"Matikan":"Nyalakan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Rekam jalur ketik (diagnostik — merekam setiap tombol)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":oe,"aria-label":`${oe?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>ue(a=>!a),children:oe?"Matikan":"Nyalakan"})]}),U&&t.jsx(me,{size:"sm","aria-label":"Project sesi baru",value:N,onChange:a=>O(a.target.value),options:n.map(a=>({value:a.id,label:a.name}))})]}),D=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{ne(null),te(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>$(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void ge()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!g,onSelect:()=>void C(a=>Se(a,Et))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!g,onSelect:()=>void C(a=>Se(a,It))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!g||W.cols===1,onSelect:()=>void C(a=>Se(a,f=>Rt(f,le%f.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!g||W.rows===1,onSelect:()=>void C(a=>Se(a,f=>Tt(f,Math.floor(le/f.cols))))}],P={display:"flex",flexDirection:"column",gap:G?8:12,...G?{position:"fixed",inset:0,zIndex:100,background:"var(--surface-page)",paddingTop:"max(12px, var(--safe-top))",paddingRight:"max(12px, var(--safe-right))",paddingBottom:"max(12px, var(--safe-bottom))",paddingLeft:"max(12px, var(--safe-left))"}:{flex:"1 1 0",minHeight:640}};return t.jsxs("div",{"data-testid":"terminal-root",style:P,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:G?"row":"column",alignItems:G?"center":"stretch"},children:[t.jsx(Wr,{compact:G,ws:L,writable:g,onSelect:d,onAdd:()=>void C(a=>Ar(a,`Grup ${a.groups.length+1}`)),onRename:(a,f)=>void C(T=>Lr(T,a,f)),onRemove:a=>void C(f=>Nr(f,a))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...G?{flex:1,minWidth:0}:{}},children:[!U&&t.jsxs(t.Fragment,{children:[t.jsx(re,{size:"sm",variant:"ghost",disabled:!g,onClick:()=>void C(a=>Se(a,Et)),children:"+ Kolom"}),t.jsx(re,{size:"sm",variant:"ghost",disabled:!g,onClick:()=>void C(a=>Se(a,It)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),F!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:K??void 0,style:{fontSize:12,color:F==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:F==="loading"?"Memuat layout server…":F==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void u(),children:"Retry"})]}):K??"Layout berubah di perangkat lain"}),S.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:S.map(a=>`${a.sessionId}${a.error?` — ${a.error}`:""}`).join(`
|
|
9
|
-
`),style:{fontSize:12,color:Te.length?"var(--status-err)":"var(--text-muted)"},children:Te.length?`${Te.length} worktree gagal dibersihkan`:`membersihkan ${S.length} worktree…`}),!U&&t.jsxs(t.Fragment,{children:[t.jsx(me,{size:"sm",value:N,onChange:a=>O(a.target.value),options:n.map(a=>({value:a.id,label:a.name}))}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{ne(null),te(!0)},children:"Ambil backlog"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"history",title:"Riwayat sesi yang sudah berlalu — buka kembali atau baca transkripnya",onClick:()=>$(!0),children:"Riwayat"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"terminal",title:"Buka shell tmux tanpa Claude di project terpilih — jalankan command di project",onClick:()=>void ge(),children:"Terminal biasa"})]}),t.jsx(re,{size:"sm",leftIcon:"plus",onClick:()=>H(!0),children:"Sesi baru"}),t.jsx(Mt,{label:U?"Aksi terminal lain":"Tampilan terminal",items:U?D:[],children:R}),t.jsx(Ze,{size:"sm",icon:G?"minimize-2":"maximize-2",label:G?"Keluar layar penuh":"Layar penuh","aria-pressed":G,onClick:()=>Z(a=>!a)})]})]}),ze.length>0&&t.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",alignItems:"center"},children:[t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Belum di grid:"}),ze.map(a=>t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",borderRadius:"var(--radius-sm)",background:"var(--bone-200)",border:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("button",{className:"hn-terminal-unplaced-action",disabled:!g,onClick:()=>Ge(a.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[a.specId??M(a.projectId)," · ",a.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${a.id}`,onClick:()=>void Me(a.id),children:"×"})]},a.id))]}),U&&!p&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(gn,{"aria-label":"Panel terminal",variant:"pill",value:String(le),onChange:a=>ye(Number(a)),tabs:W.cells.map((a,f)=>({value:String(f),label:`Panel ${f+1}${a?` · ${a.slice(0,6)}`:" · kosong"}`}))})}),p?t.jsx(ut,{kind:"empty",icon:"terminal",title:"Belum ada sesi terminal",hint:"Pilih project lalu buka sesi — 'Sesi baru' menjalankan claude --dangerously-skip-permissions di direktori project; 'Terminal biasa' membuka shell tmux polos untuk menjalankan command."}):t.jsxs("div",{style:{flex:1,minHeight:0,display:"grid",gap:8,gridTemplateColumns:U?"minmax(0, 1fr)":`18px repeat(${W.cols}, minmax(0, 1fr))`,gridTemplateRows:U?"minmax(0, 1fr)":`16px repeat(${W.rows}, minmax(0, 1fr))`},children:[!U&&t.jsx("div",{}),!U&&Array.from({length:W.cols},(a,f)=>t.jsx(Nt,{label:`Tutup kolom ${f+1}`,disabled:!g||W.cols===1,onClick:()=>void C(T=>Se(T,A=>Rt(A,f)))},`col-${f}`)),Array.from({length:W.rows},(a,f)=>t.jsxs(o.Fragment,{children:[!U&&t.jsx(Nt,{label:`Tutup baris ${f+1}`,disabled:!g||W.rows===1,onClick:()=>void C(T=>Se(T,A=>Tt(A,f)))}),Array.from({length:W.cols},(T,A)=>{const V=f*W.cols+A,we=W.cells[V]??null,xe=we?Re(we):null;return t.jsx("div",{"data-terminal-cell-index":V,"aria-hidden":U&&le!==V?"true":"false",style:{minHeight:0,minWidth:0,display:U&&le!==V?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:xe?t.jsx(Gr,{session:xe,nameOf:M,onClose:()=>void Me(xe.id),canArrange:g,onDetach:()=>Ue(xe.id),onExit:Ae=>He(xe.id,Ae),onReview:h,onSessionReview:b,titleOf:I,onIntegrate:v,onIntegrateSession:l,specOf:j,fontSize:q,showKeys:z,predict:J,diag:oe,fullscreen:X===xe.id,onFullscreen:()=>ee(xe.id)}):t.jsx(Yr,{disabled:!g,unplaced:ze,nameOf:M,onPick:Ae=>qe(V,Ae)})},we??`empty-${V}`)})]},`row-${f}`))]}),he&&t.jsx(Or,{seed:Ee,activeIds:Ie,error:ve,onPick:a=>void fe(a),onClose:()=>te(!1)}),Q&&t.jsx(Tr,{open:!0,projectId:N,projectName:M(N),onClose:()=>H(!1),onCreated:Ke}),De&&t.jsx(Ir,{projects:n,onClose:()=>$(!1),onRestart:a=>void je(a)}),de.dialog,X&&Re(X)&&t.jsx(Ur,{session:Re(X),label:Jt(Re(X),M,I),fontSize:q,showKeys:z,predict:J,diag:oe,onClose:()=>ee(null)})]})}function Jt(e,n,r){const i=n(e.projectId),s=e.specId?r==null?void 0:r(e.specId):void 0;return e.specId?`${i} · ${e.specId}${s?` · ${s}`:""}`:e.id.startsWith("xaudit-")?`${i} · audit lintas`:i}function Or({seed:e,activeIds:n,error:r,onPick:i,onClose:s}){const[c,y]=o.useState(""),[h,b]=o.useState("all"),[I,v]=o.useState("all"),[l,j]=o.useState(e),[w,k]=o.useState("");o.useEffect(()=>{const m=setTimeout(()=>k(c.trim()),250);return()=>clearTimeout(m)},[c]),o.useEffect(()=>{var L,F;let m=!0;const E=(F=(L=_).listSpecs)==null?void 0:F.call(L,{startable:!0,q:w||void 0,stage:h==="all"?void 0:h,priority:I==="all"?void 0:I});return E==null||E.then(K=>{m&&j(K.items)}).catch(()=>{}),()=>{m=!1}},[w,h,I]);const S=l.filter(m=>!n.has(m.id));return t.jsxs(Oe,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:s,width:760,children:[r&&t.jsx("div",{style:{marginBottom:10,padding:"8px 10px",borderRadius:"var(--radius-sm)",background:"var(--clay-100)",color:"var(--clay-600)",fontSize:12},children:r}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ct,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:c,onChange:m=>y(m.target.value),style:{flex:"1 1 220px"}}),t.jsx(me,{size:"sm","aria-label":"Filter stage",value:h,onChange:m=>b(m.target.value),options:[{value:"all",label:"Semua stage"}].concat(kn.filter(m=>m.key!=="done").map(m=>({value:m.key,label:m.label})))}),t.jsx(me,{size:"sm","aria-label":"Filter prioritas",value:I,onChange:m=>v(m.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),S.length===0?t.jsx(ut,{kind:"empty",icon:"inbox",title:"Tak ada backlog untuk diambil",hint:"Semua item sudah selesai/aktif atau tak cocok filter — buat brief baru di halaman Backlog."}):t.jsx("div",{style:{display:"flex",flexDirection:"column",maxHeight:"62vh",overflowY:"auto"},children:S.map(m=>t.jsx("button",{onClick:()=>i(m),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx(Ce,{name:m.source==="qa"?"bug":m.source==="audit"?"search":"lightbulb",size:14,color:m.source==="qa"?"var(--clay-500)":m.source==="audit"?"var(--wind-600)":"var(--brass-500)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-subtle)",flex:"0 0 78px"},children:m.id}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:m.title}),t.jsx(at,{tone:m.priority==="tinggi"?"err":"neutral",size:"sm",children:m.priority}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,flex:"0 1 auto",minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--text-muted)"},children:m.projectId})]})},m.id))})]})}function Wr({ws:e,compact:n=!1,writable:r,onSelect:i,onAdd:s,onRename:c,onRemove:y}){const[h,b]=o.useState(null),I=_e(e),v=e.groups.length===1;return t.jsxs("div",{role:"tablist","aria-label":"Grup terminal",style:{display:"flex",alignItems:"center",gap:4,flexWrap:"wrap",...n?{}:{borderBottom:"1px solid var(--border-hair)",paddingBottom:4}},children:[e.groups.map((l,j)=>{const w=l.id===I.id;return h===l.id?t.jsx(_r,{initial:l.name,onCommit:k=>{k.trim()&&c(l.id,k.trim()),b(null)},onCancel:()=>b(null)},l.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:w?"var(--bone-200)":"transparent",border:`1px solid ${w?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":w,tabIndex:w?0:-1,onClick:()=>i(l.id),onKeyDown:k=>{var m,E;let S=null;k.key==="ArrowRight"?S=(j+1)%e.groups.length:k.key==="ArrowLeft"?S=(j-1+e.groups.length)%e.groups.length:k.key==="Home"?S=0:k.key==="End"&&(S=e.groups.length-1),S!==null&&(k.preventDefault(),i(e.groups[S].id),(E=(m=k.currentTarget.closest('[role="tablist"]'))==null?void 0:m.querySelectorAll('[role="tab"]')[S])==null||E.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:w?"var(--text-strong)":"var(--text-muted)"},children:l.name}),w&&r&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${l.name}`,title:"Ganti nama",onClick:()=>b(l.id),style:{border:0,padding:0,background:"transparent",cursor:"pointer",color:"var(--text-subtle)",fontSize:10},children:"✎"}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Hapus grup ${l.name}`,title:v?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:v,onClick:()=>y(l.id),style:{border:0,padding:0,background:"transparent",cursor:v?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:v?.35:1},children:"×"})]})]},l.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!r,onClick:s,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function Nt({label:e,disabled:n,onClick:r}){return t.jsx("button",{type:"button","aria-label":e,title:n?"Grid tak boleh menyusut ke nol":e,disabled:n,onClick:r,style:{all:"unset",display:"grid",placeItems:"center",fontSize:11,lineHeight:1,color:"var(--text-subtle)",opacity:n?.3:1,cursor:n?"not-allowed":"pointer"},children:"×"})}function _r({initial:e,onCommit:n,onCancel:r}){const[i,s]=o.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:i,placeholder:"mis. Rilis",onChange:c=>s(c.target.value),onBlur:()=>n(i),onKeyDown:c=>{c.key==="Enter"?n(i):c.key==="Escape"&&r()},style:{width:100,padding:"3px 6px",fontSize:12,fontFamily:"var(--font-ui)",border:"1px solid var(--border-strong)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",color:"var(--text-strong)"}})}const Kr={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"},Hr={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function qr({phases:e,compact:n=!1,now:r}){const[i,s]=o.useState(null),[,c]=o.useState(0),y=!!(e!=null&&e.some(l=>{var j;return((j=l.agent)==null?void 0:j.status)==="running"}));if(o.useEffect(()=>{if(!y||r!==void 0)return;const l=setInterval(()=>c(j=>j+1),1e3);return()=>clearInterval(l)},[y,r]),!(e!=null&&e.length))return null;const h=r??Date.now(),b=e.find(l=>l.name===i&&l.agent),I=l=>({color:Kr[l.state],fontWeight:l.state==="active"?600:400,textDecoration:l.state==="skipped"?"line-through":"none",opacity:l.state==="pending"?.5:1}),v=l=>{const j=l.agent;return j?typeof j.durationMs=="number"?vt(j.durationMs):j.status==="running"&&j.startedAt?vt(h-Date.parse(j.startedAt)):"":""};return t.jsxs("div",{"data-testid":"phase-strip",style:{flex:"0 0 auto",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{"data-testid":"phase-strip-scroller",style:{display:"flex",alignItems:"center",gap:8,padding:"3px 8px",fontSize:10,fontFamily:"var(--font-mono)",overflowX:"auto",whiteSpace:"nowrap"},children:e.map(l=>{if(!l.agent)return t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name},l.name);const j=l.agent,w=pn(l),k=!n||l.state==="active",S=v(l);return t.jsxs("button",{type:"button","data-tone":w,"aria-expanded":i===l.name,"aria-label":`Detail fase ${l.name}`,onClick:()=>s(i===l.name?null:l.name),style:{display:"inline-flex",alignItems:"center",gap:4,flex:"0 0 auto",padding:"1px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"transparent",font:"inherit",color:"var(--text-body)",cursor:"pointer"},children:[t.jsx("span",{"aria-hidden":!0,children:Hr[w]}),t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name}),l.state==="skipped"&&t.jsx("span",{children:"dilewati"}),k&&j.model&&t.jsxs("span",{children:["· ",it(j.model)]}),k&&j.effort&&t.jsxs("span",{children:["· ",j.effort]}),k&&S&&t.jsxs("span",{children:["· ",S]}),j.attempts>1&&t.jsxs("span",{children:["↻",j.attempts]}),j.evidence==="missing"&&t.jsx("span",{role:"img","aria-label":"bukti subagent tak diterima",title:"bukti subagent tak diterima",style:{color:"var(--status-warn)"},children:"⚠"})]},l.name)})}),(b==null?void 0:b.agent)&&t.jsxs("div",{role:"dialog","aria-label":`Detail fase ${b.name}`,style:{position:"absolute",marginLeft:8,zIndex:5,minWidth:220,maxWidth:"min(420px, calc(100% - 16px))",maxHeight:"calc(100% - 48px)",overflowY:"auto",boxSizing:"border-box",padding:"8px 10px",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",whiteSpace:"normal",lineHeight:1.5,fontSize:10,fontFamily:"var(--font-mono)"},children:[t.jsx("div",{children:t.jsx("b",{children:b.agent.name})}),t.jsx("div",{children:[it(b.agent.model),b.agent.effort,b.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),t.jsxs("div",{children:["durasi ",v(b)||"—"," · percobaan ",b.agent.attempts]}),t.jsxs("div",{children:["token in ",b.agent.inputTokens??"—"," · out ",b.agent.outputTokens??"—"," · cache ",b.agent.cachedTokens??"—"]}),b.agent.resultExcerpt&&t.jsx("pre",{style:{margin:"6px 0 0",whiteSpace:"pre-wrap",maxHeight:160,overflow:"auto"},children:b.agent.resultExcerpt})]})]})}function Gr({session:e,nameOf:n,onClose:r,canArrange:i,onDetach:s,onExit:c,onReview:y,onSessionReview:h,titleOf:b,onIntegrate:I,onIntegrateSession:v,specOf:l,fontSize:j,showKeys:w,predict:k,diag:S,fullscreen:m,onFullscreen:E}){const[L,F]=o.useState(null),K=o.useRef(null),[g,C]=o.useState(Number.POSITIVE_INFINITY),d=$t();o.useEffect(()=>{const Q=K.current;if(!Q||typeof ResizeObserver!="function")return;const H=new ResizeObserver(De=>{var de;const $=((de=De[0])==null?void 0:de.contentRect.width)??Q.getBoundingClientRect().width;$>0&&C($)});return H.observe(Q),()=>H.disconnect()},[]);const[u,N]=o.useState(!1),O=o.useCallback((Q,H)=>{F(Q),N(H)},[]),[x,q]=o.useState(!1),[ae,z]=o.useState(!1),[ie,J]=o.useState(!1),se=e.specId?l==null?void 0:l(e.specId):void 0,oe=!e.specId&&!!e.branch,ue=Jt(e,n,b),be=!e.exited&&!!e.decision,G=!e.exited&&!!e.deciding,Z=be||G,X=e.exited&&!!e.exitCode,ee=!e.exited&&u,he=X?null:e.exited||ee?"PST-005":Z?"PST-004":"PST-003",te=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>q(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>q(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(Ce,{name:"file-text",size:12})},"docs")}]:[],...e.specId&&y?[{key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>y(e.specId),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>y(e.specId),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree)",children:t.jsx(Ce,{name:"git-compare",size:12})},"review")}]:[],...oe&&h?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>h(e.id,ue),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>h(e.id,ue),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(Ce,{name:"git-compare",size:12})},"review-session")}]:[],...se&&I?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>z(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>z(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch spec",children:t.jsx(Ce,{name:"git-merge",size:12})},"integrate")}]:[],...oe&&v?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>J(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>J(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(Ce,{name:"git-merge",size:12})},"integrate-session")}]:[],{key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",onSelect:s,render:t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:s,disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",children:"lepas"},"detach")}],ve=Dn(g,te.length,d?44:28),ne=te.slice(ve);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:K,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:X?"var(--status-err-tint)":e.exited||ee?"var(--status-ok-tint)":Z?"var(--status-warn-tint)":"var(--bone-200)",borderBottom:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11,color:e.exited?"var(--text-muted)":"var(--text-body)"},children:[he&&t.jsx(vn,{id:he,decorative:!0,style:{width:34,flex:"0 0 auto",borderRadius:"var(--radius-sm)"}}),t.jsxs("span",{style:{flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[ue," · ",e.id.slice(0,6)]}),e.orchestrated&&e.model&&t.jsxs("span",{"data-testid":"orchestrator-chip",title:"Model & effort orchestrator",style:{flex:"0 0 auto",fontSize:10,color:"var(--text-muted)"},children:["orch ",it(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(X?t.jsx(Pe,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(Pe,{status:"done",size:"sm",children:"Selesai"})),ee&&t.jsx(Pe,{status:"done",size:"sm",children:"Selesai"}),G&&!ee&&t.jsx(Pe,{status:"running",size:"sm",children:"Lead memutuskan"}),be&&!G&&!ee&&t.jsx(Pe,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[te.slice(0,ve).map(Q=>Q.render),ne.length>0&&t.jsx(Mt,{label:`Aksi lain sesi ${e.id}`,items:ne.map(({render:Q,...H})=>H)}),t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:E,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(Ce,{name:"fullscreen",size:12})}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:r,children:"×"})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,position:"relative",opacity:e.exited?.6:1},children:[t.jsx(qr,{phases:L,compact:g<480}),t.jsx("div",{style:{flex:1,minHeight:0},children:m?t.jsx("div",{style:{height:"100%",display:"grid",placeItems:"center",padding:12,color:"var(--text-subtle)",fontSize:12,textAlign:"center"},children:"Terbuka di layar penuh"}):t.jsx(Ht,{sessionId:e.id,onExit:c,onPhases:O,fontSize:j,showKeys:w,predict:k,diag:S},e.id)})]}),x&&e.specId&&t.jsx(yn,{specId:e.specId,onClose:()=>q(!1)}),ae&&se&&I&&t.jsx(yt,{projectId:se.projectId,ownBranch:`hanoman/${se.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:se.id,onClose:()=>z(!1),onIntegrate:(Q,H)=>{z(!1),I(se,Q,H)}}),ie&&oe&&v&&t.jsx(yt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>J(!1),onIntegrate:(Q,H)=>{J(!1),v(e,Q,H)}})]})}function Ur({session:e,label:n,fontSize:r,showKeys:i,predict:s,diag:c,onClose:y}){return t.jsx(Oe,{open:!0,icon:"terminal",title:n,onClose:y,closeOnEscape:!1,width:1600,children:t.jsx("div",{style:{height:"min(72vh, calc(100dvh - 180px))",minHeight:0,display:"flex",flexDirection:"column",opacity:e.exited?.6:1},children:t.jsx(Ht,{sessionId:e.id,onExit:()=>{},fontSize:r,showKeys:i,predict:s,diag:c},e.id)})})}function Yr({unplaced:e,nameOf:n,onPick:r,disabled:i}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(me,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:i||!e.length,onChange:s=>s.target.value&&r(s.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(s=>({value:s.id,label:`${s.specId??n(s.projectId)} · ${s.id.slice(0,6)}`})))})})}export{qr as PhaseStrip,Zr as TerminalScreen};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{e as y,j as e,a as d,f as T,B as C,h as H,o as V,r as Y,t as X,q as Z,S as F,d as U,m as ee,R as te,v as ae,w as ie,p as A,x as se,I as le,y as ne,u as re,c as W,H as oe,z as O,A as q,C as ce,D as de}from"./index-Bd9gXx1g.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-BlNZnTbo.js";import"./markdown-CWEY34jk.js";function pe(s,c){return s==="rejected"?"Ditutup":s!=="accepted"?"Sedang ditinjau":c==="done"?"Selesai":c==="executing"?"Sedang dikerjakan":"Diterima"}const he=5e3,$=20,me=400;function M({total:s,page:c,onPage:j,unit:p="tiket"}){const n=de(s,c,$);return e.jsx(ie,{page:n.page,pageCount:n.pageCount,total:s,from:n.from,to:n.to,onPage:j,unit:p})}function Q(s,c=Date.now()){const j=Math.max(0,c-new Date(s).getTime()),p=Math.floor(j/6e4);if(p<1)return"baru saja";if(p<60)return`${p}m`;const n=Math.floor(p/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const K={new:"warn",accepted:"ok",rejected:"neutral"},J={new:"belum ditinjau",accepted:"diterima",rejected:"ditutup"};function ge({t:s,onOpen:c}){return e.jsxs("button",{onClick:()=>c(s.id),className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:12,width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",cursor:"pointer",marginBottom:8},children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",s.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:s.category}),e.jsx(C,{tone:K[s.status]??"neutral",size:"sm",children:J[s.status]??s.status})]}),e.jsx("span",{style:{display:"block",color:"var(--text-body)",fontSize:"var(--text-sm)",marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2,display:"block"},children:[s.projectId," · ",s.reporterEmail," · ",Q(s.createdAt)," lalu",s.attachmentCount>0?` · ${s.attachmentCount} lampiran`:""]})]}),s.specId&&e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",s.specId]}),e.jsx(le,{name:"chevron-right",size:16,color:"var(--text-subtle)"})]})}function xe({id:s,onBack:c,onAccepted:j,onDeleted:p,onToast:n}){var R;const[i,k]=l.useState(null),[h,z]=l.useState("loading"),[m,u]=l.useState(!1),[g,x]=l.useState("sedang"),[P,b]=l.useState(!1),[f,B]=l.useState(!1),{confirm:v,dialog:S}=re(),[r,I]=l.useState({title:"",detail:"",category:"bug",status:"new"}),w=l.useCallback(()=>{y.getTicket(s).then(t=>{k(t),z("ready")}).catch(()=>z("error"))},[s]);if(l.useEffect(()=>{w()},[w]),h==="loading")return e.jsx(T,{kind:"loading"});if(h==="error"||!i)return e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:w,actionLabel:"Coba lagi"});async function L(){u(!0);try{const t=await y.acceptTicket(s,g);j(t.spec,!!t.alreadyPromoted)}catch{n("Gagal menerima tiket","err","x-circle")}finally{u(!1)}}async function E(){if(await v({title:`Tolak & tutup tiket #${i.number}?`,message:`"${i.title}" ditutup tanpa membuat backlog item.`,confirmLabel:"Tolak tiket",icon:"x-circle"})){u(!0);try{await y.rejectTicket(s),k({...i,status:"rejected"}),n("Tiket ditutup","ok","check")}catch{n("Gagal menolak tiket","err","x-circle")}finally{u(!1)}}}async function a(){u(!0);try{const t=await y.unlinkTicket(s);k({...i,specId:t.specId,spec:null,status:t.status}),n("Tautan backlog dilepas","ok","unlink")}catch{n("Gagal melepas tautan","err","x-circle")}finally{u(!1)}}function o(){I({title:i.title,detail:i.detail,category:i.category,status:i.status}),b(!0)}async function D(){u(!0);try{const t=await y.editTicket(s,{title:r.title,detail:r.detail,category:r.category,status:r.status});k(t),b(!1),n("Tiket diperbarui","ok")}catch{n("Gagal menyimpan","err","x-circle")}finally{u(!1)}}async function N(){u(!0);try{await y.deleteTicket(s),n("Tiket dihapus","ok","trash-2"),p()}catch{n("Gagal menghapus","err","x-circle"),u(!1)}}if(P)return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>b(!1),disabled:m,children:"Batal"}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"primary",leftIcon:"check",onClick:D,disabled:m,children:"Simpan"})]}),e.jsx(W,{label:"Judul",children:e.jsx(U,{value:r.title,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:t=>I({...r,title:t.target.value})})}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[e.jsx(W,{label:"Kategori",children:e.jsx(F,{value:r.category,onChange:t=>I({...r,category:t.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(W,{label:"Status",children:e.jsx(F,{value:r.status,onChange:t=>I({...r,status:t.target.value}),options:[{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]})})]}),e.jsx(W,{label:"Detail keluhan",children:e.jsx(oe,{value:r.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:t=>I({...r,detail:t.target.value})})})]});const _=i.status!=="new";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:c,children:"Kembali"}),e.jsx(C,{tone:K[i.status]??"neutral",children:J[i.status]??i.status}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:o,disabled:m,children:"Ubah"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:()=>B(!0),disabled:m,children:"Hapus"}),i.publicStatusUrl&&e.jsxs(e.Fragment,{children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"share-2",onClick:()=>window.open(i.publicStatusUrl,"_blank","noreferrer"),children:"Buka status publik"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"link-2",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(i.publicStatusUrl),n("Link publik disalin","ok","copy")},children:"Salin link publik"})]}),i.specId?e.jsxs(e.Fragment,{children:[e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",i.specId]}),e.jsx(C,{tone:"neutral",size:"sm",children:pe(i.status,(R=i.spec)==null?void 0:R.stage)}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(O(i.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(O(i.specId)),n("Link backlog disalin","ok","copy")},children:"Salin link"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"unlink",onClick:a,disabled:m,children:"Lepas tautan"})]}):!_&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:g,onChange:t=>x(t.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]}),e.jsx(d,{size:"sm",leftIcon:"arrow-up-right",onClick:L,disabled:m,children:"Terima → backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"ban",onClick:E,disabled:m,children:"Tolak"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",i.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:i.category})]}),e.jsx("div",{style:{fontWeight:600,fontSize:"var(--text-lg)",color:"var(--text-strong)",marginTop:4},children:i.title})]}),e.jsxs("div",{style:{display:"flex",gap:18,flexWrap:"wrap",fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[e.jsxs("span",{children:["pelapor: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.reporterEmail})]}),e.jsxs("span",{children:["project: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.projectId})]}),e.jsxs("span",{children:["masuk: ",Q(i.createdAt)," lalu"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Detail keluhan"}),e.jsx("div",{style:{whiteSpace:"pre-wrap",color:"var(--text-body)",fontSize:"var(--text-sm)",lineHeight:1.55},children:i.detail})]}),i.attachments.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Lampiran"}),e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:i.attachments.map(t=>e.jsx("a",{href:q.ticketAttachment(i.id,t.id),target:"_blank",rel:"noreferrer",style:{display:"block",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:e.jsx("img",{src:q.ticketAttachment(i.id,t.id),alt:t.filename,style:{display:"block",maxWidth:180,maxHeight:140,objectFit:"cover"}})},t.id))})]}),e.jsx(ce,{open:f,title:"Hapus tiket?",eyebrow:`#${i.number}`,message:`Tiket "${i.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:m,onCancel:()=>B(!1),onConfirm:N}),S]})}function fe({projectId:s,onAccepted:c}){const[j,p]=l.useState([]),[n,i]=l.useState("loading"),[k,h]=l.useState(!1),[z,m]=l.useState(null),[u,g]=l.useState(null),[x,P]=l.useState([]),[b,f]=l.useState(0),[B,v]=l.useState(1),S=l.useCallback(async()=>{try{const a=await y.listGithubIssues(s,{page:B,limit:$});p(a.items),f(a.total),i("ready")}catch{i("error")}},[s,B]);l.useEffect(()=>{S()},[S]);const r=a=>{var D;const o=(D=a.detail)==null?void 0:D.error;return typeof o=="string"?o:a.message};async function I(){h(!0),g(null),m(null);try{const a=await y.pullGithubIssues(s);m(`${a.repo}: ${a.created} baru, ${a.updated} diperbarui`+(a.skippedPullRequests?` · ${a.skippedPullRequests} pull request dilewati`:"")),await S()}catch(a){g(r(a))}finally{h(!1)}}async function w(){h(!0),g(null);try{const a=await y.acceptGithubIssues(x,void 0);P([]),c==null||c(a.created),await S()}catch(a){g(r(a))}finally{h(!1)}}async function L(a){h(!0),g(null);try{await y.rejectGithubIssue(a),await S()}catch(o){g(r(o))}finally{h(!1)}}const E=a=>P(o=>o.includes(a)?o.filter(D=>D!==a):[...o,a]);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",onClick:I,disabled:k,children:"Tarik issue"}),e.jsxs(d,{size:"sm",variant:"primary",onClick:w,disabled:k||x.length===0,children:["Terima terpilih",x.length?` (${x.length})`:""]}),z&&e.jsx("span",{style:{fontSize:12,color:"var(--text-muted)"},children:z})]}),u&&e.jsx("div",{role:"alert",style:{fontSize:12,color:"var(--danger, #b00)"},children:u}),n==="loading"?e.jsx(T,{kind:"loading"}):n==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat daftar issue.",action:()=>void S(),actionLabel:"Coba lagi"}):j.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada issue tertarik",hint:"Tekan “Tarik issue” untuk menariknya dari repo GitHub project ini."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{overflowY:"auto",minHeight:0},children:j.map(a=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",gap:8,alignItems:"baseline",padding:"8px 0",borderBottom:"1px solid var(--border-hair)"},children:[a.status==="new"&&e.jsx("input",{type:"checkbox","aria-label":`Pilih issue ${a.number}`,checked:x.includes(a.id),onChange:()=>E(a.id)}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:["#",a.number]}),e.jsx("a",{href:a.url,target:"_blank",rel:"noreferrer",style:{flex:1,minWidth:0},children:a.title}),e.jsxs("span",{style:{fontSize:12,color:"var(--text-muted)"},children:["@",a.authorLogin]}),a.labels.map(o=>e.jsx(C,{children:o},o)),a.status==="rejected"&&e.jsx(C,{tone:"neutral",children:"ditutup"}),a.specId&&e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12},children:a.specId}),a.status==="new"&&e.jsx(d,{size:"sm",variant:"ghost",onClick:()=>L(a.id),disabled:k,children:"Tolak"})]},a.id))}),e.jsx(M,{total:b,page:B,onPage:v,unit:"issue"})]})]})}function ve({projects:s,onAccepted:c,onToast:j}){const[p,n]=l.useState([]),[i,k]=l.useState(0),[h,z]=H("triage","page",1,se),[m,u]=l.useState(0),[g,x]=l.useState("loading"),[P,b]=H("triage","openId",null,ne),[f,B]=H("triage","project","",A),[v,S]=H("triage","status","",A),[r,I]=H("triage","q","",A),[w,L]=H("triage","tab","tiket",V("tiket","issue")),E=[f!=="",v!=="",r.trim()!==""].filter(Boolean).length,a=Y("triage","scroll",p.length>0),o=l.useCallback((t=!1)=>{t||x("loading"),y.listTickets({project:f||void 0,status:v||void 0,q:r||void 0,page:String(h),limit:String($)}).then(G=>{n(G.items),k(G.total),u(G.unreviewed),x("ready")}).catch(()=>{t||x("error")})},[f,v,r,h]);l.useEffect(()=>{o()},[o]),X(JSON.stringify([f,v,r]),()=>z(1));const[D,N]=l.useState(r);l.useEffect(()=>{const t=setTimeout(()=>N(r),me);return()=>clearTimeout(t)},[r]),Z({topic:"tickets",params:{project:f||void 0,status:v||void 0,q:D||void 0,page:h,limit:$},apply:t=>{n(t.data.items),k(t.data.total),u(t.data.unreviewed),x("ready")},refetch:()=>o(!0),pollMs:he});const _=e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:f?e.jsx(fe,{projectId:f,onAccepted:t=>t.forEach(G=>c(G,!1))}):e.jsx(T,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring di atas."})}),R=e.jsx("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0},children:g==="loading"?e.jsx(T,{kind:"loading"}):g==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:()=>o(),actionLabel:"Coba lagi"}):p.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{ref:a,"data-testid":"triage-scroll",style:{overflowY:"auto",minHeight:0,flex:"1 1 auto"},children:p.map(t=>e.jsx(ge,{t,onOpen:b},t.id))}),e.jsx(M,{total:i,page:h,onPage:z})]})});return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14,minHeight:0,flex:1},children:[e.jsxs("div",{className:"hn-wrap-mobile",style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(d,{size:"sm",variant:w==="tiket"?"primary":"ghost",onClick:()=>L("tiket"),children:"Tiket Help Center"}),e.jsx(d,{size:"sm",variant:w==="issue"?"primary":"ghost",onClick:()=>L("issue"),children:"Issue GitHub"})]}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap",alignItems:"center"},children:[e.jsx(F,{size:"sm",value:f,"aria-label":"Project triase",onChange:t=>B(t.target.value),options:[{value:"",label:"Semua project"},...s.map(t=>({value:t.id,label:t.name}))]}),w==="tiket"&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:v,"aria-label":"Status tiket",onChange:t=>S(t.target.value),options:[{value:"",label:"Semua status"},{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]}),e.jsx(U,{size:"sm",value:r,"aria-label":"Cari tiket",onChange:t=>I(t.target.value),placeholder:"mis. gagal login atau budi@contoh.id",style:{flex:1,minWidth:160}}),m>0&&e.jsxs(C,{tone:"warn",children:[m," belum ditinjau"]}),e.jsx(ee,{onDone:()=>o(!0),onToast:j}),e.jsx(te,{screen:"triage",active:E}),e.jsx(ue,{})]})]}),w==="issue"?_:e.jsx(ae,{ariaLabel:"Panel triase",active:P?"detail":"list",onActiveChange:t=>{t==="list"&&b(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:R,className:"hn-panel-flex"},...P?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:e.jsx(xe,{id:P,onBack:()=>{b(null),o(!0)},onAccepted:c,onDeleted:()=>{b(null),o(!0)},onToast:j})}]:[]]})]})}export{fe as GithubIssuesPanel,ve as TriageScreen};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{e as v,u as te,j as e,M as oe,f as U,I as W,a as f,h as de,o as fe,ap as be,ai as ke,c as O,d as T,a7 as ye,ac as se,y as ve}from"./index-Bd9gXx1g.js";import{R as p}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";const je={pass:"check",fail:"x",warn:"alert-triangle",na:"minus",unknown:"circle"},we={pass:"var(--leaf-600)",fail:"var(--clay-600)",warn:"var(--amber-600)",na:"var(--text-subtle)",unknown:"var(--text-subtle)"},Se={AUTO:"var(--brass-700)",AUDIT:"var(--amber-600)",INFO:"var(--text-subtle)"},Ce={critical:"var(--clay-600)",high:"var(--amber-600)",medium:"var(--text-subtle)",low:"var(--text-subtle)"};function K({text:a,color:s}){return e.jsx("span",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:"0.04em",color:s,border:`1px solid ${s}`,borderRadius:3,padding:"0 4px",whiteSpace:"nowrap"},children:a})}function ce({score:a}){const s=a>=90?"var(--leaf-600)":a>=50?"var(--amber-600)":"var(--clay-600)";return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,minWidth:90},children:[e.jsx("div",{style:{flex:1,height:6,background:"var(--bone-200)",borderRadius:3,overflow:"hidden"},children:e.jsx("div",{style:{width:`${a}%`,height:"100%",background:s}})}),e.jsxs("span",{style:{fontSize:11,fontFamily:"var(--font-mono)",color:"var(--text-subtle)",minWidth:28,textAlign:"right"},children:[a,"%"]})]})}function Pe({item:a,busy:s,selected:l,onToggle:o,onNa:u,onAttest:c}){const n=a.mode==="AUTO"&&!a.na;return e.jsxs("div",{"data-testid":`item-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,padding:"5px 0",borderBottom:"1px solid var(--border-hair)",fontSize:13,opacity:a.na?.55:1},children:[n?e.jsx("input",{type:"checkbox","aria-label":`pilih ${a.id}`,checked:l,onChange:()=>o(a)}):e.jsx("span",{style:{display:"inline-block",width:13}}),e.jsx(W,{name:je[a.status],size:14,color:we[a.status]}),e.jsx("span",{style:{flex:1,minWidth:0},children:a.title}),a.drifted&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),e.jsx(K,{text:a.mode,color:Se[a.mode]}),e.jsx(K,{text:a.severity,color:Ce[a.severity]}),a.mode==="INFO"&&!a.attested&&e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"check-circle",loading:s,onClick:()=>c(a),children:"Attest"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:a.na?"rotate-ccw":"minus-circle",loading:s,onClick:()=>u(a,!a.na),children:a.na?"Batal N/A":"N/A"})]})}const ee={section:"",mode:"",status:"",severity:""};function J({value:a,onChange:s,options:l,label:o}){return e.jsxs("select",{"aria-label":o,value:a,onChange:u=>s(u.target.value),style:{fontSize:12,padding:"3px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--bone-50)",color:"var(--text)"},children:[e.jsxs("option",{value:"",children:[o,": semua"]}),l.map(([u,c])=>e.jsx("option",{value:u,children:c},u))]})}function ze(a){let s=0,l=0,o=0,u=0;for(const n of a)n.status==="fail"?s++:n.status==="warn"?l++:n.status==="unknown"&&o++,n.drifted&&u++;const c=[s&&`${s} fail`,l&&`${l} warn`,o&&`${o} unknown`].filter(Boolean);return{text:c.length?c.join(" "):"semua pass",drift:u}}function $e({section:a,items:s,expanded:l,onToggle:o,busy:u,selected:c,onToggleItem:n,onNa:b,onAttest:g,onSectionNa:k}){const S=ze(a.items),h=!!a.suggestion&&!a.suggestion.applicable;return e.jsxs("div",{style:{marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:[e.jsxs("button",{"data-testid":`section-${a.id}`,"aria-expanded":l,onClick:()=>o(a.id),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"8px 10px",textAlign:"left",background:l?"var(--bone-100)":"transparent",border:"none",cursor:"pointer"},children:[e.jsx(W,{name:l?"chevron-down":"chevron-right",size:15,color:"var(--text-subtle)"}),e.jsx("span",{style:{fontSize:14},children:a.icon}),e.jsx("span",{style:{fontSize:13,fontWeight:600,flex:1,minWidth:0},children:a.title}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:S.text}),S.drift>0&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),h&&e.jsx(K,{text:"saran N/A",color:"var(--brass-700)"}),e.jsx(ce,{score:a.score})]}),l&&e.jsxs("div",{style:{padding:"2px 10px 8px"},children:[h&&e.jsxs("div",{"data-testid":`suggestion-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,margin:"6px 0",padding:"6px 10px",fontSize:12,color:"var(--text-subtle)",background:"var(--bone-50)",border:"1px dashed var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"info",size:13,color:"var(--brass-700)"}),e.jsxs("span",{style:{flex:1},children:["Stack tak terdeteksi (",a.suggestion.detail,") — kemungkinan N/A. Cek Docker manual bila ragu."]}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"minus-circle",loading:u===`section:${a.id}`,onClick:()=>k(a),children:"Tandai seksi N/A"})]}),s.map(y=>e.jsx(Pe,{item:y,busy:u===y.id,selected:c.has(y.id),onToggle:n,onNa:b,onAttest:g},y.id))]})]})}function Ae({vpsId:a,vpsName:s,lastAuditAt:l,health:o,provisioning:u,onClose:c,onToast:n}){const[b,g]=p.useState(null),[k,S]=p.useState("loading"),[h,y]=p.useState(ee),[P,w]=p.useState(""),[B,E]=p.useState(new Set),[$,C]=p.useState(null),[R,V]=p.useState(new Set),[F,D]=p.useState(null),[A,L]=p.useState(""),I=p.useCallback(()=>{S("loading"),v.vpsChecklist(a).then(r=>{g(r),S("ready")}).catch(()=>S("error"))},[a]);p.useEffect(()=>{I(),V(new Set),D(null),E(new Set),w(""),y(ee)},[I]);const t=r=>V(j=>{const d=new Set(j);return d.has(r.id)?d.delete(r.id):d.add(r.id),d}),x=()=>{V(new Set),D(null)},m=r=>E(j=>{const d=new Set(j);return d.has(r)?d.delete(r):d.add(r),d}),{confirm:H,dialog:X}=te();async function M(){L("preview");try{D((await v.remediatePreview(a,[...R])).steps)}catch{n("Preview remediasi gagal","err","x-circle")}finally{L("")}}async function Y(){if(await H({title:`Terapkan ${R.size} item AUTO ke VPS ini?`,message:"Remediasi dijalankan langsung di server yang terdaftar.",impact:["Langkahnya idempoten dan anti-lockout.","Checklist diaudit ulang setelah selesai."],confirmLabel:"Terapkan",icon:"shield"})){L("apply");try{await v.remediate(a,[...R]),x(),I(),n("Remediasi diterapkan · audit ulang","ok","shield")}catch{n("Remediasi gagal","err","x-circle")}finally{L("")}}}async function _(r,j,d){C(r.id);try{await j(),I(),n(d,"ok","shield")}catch{n(`Gagal memperbarui ${r.id}`,"err","x-circle")}finally{C(null)}}const i=(r,j)=>_(r,()=>v.markNa(a,r.id,j,j?"ditandai dari checklist":void 0),j?`${r.id} ditandai N/A`:`${r.id} kembali applicable`),z=r=>_(r,()=>v.attestItem(a,r.id),`${r.id} di-attest`);async function N(r){const j=r.items.map(d=>d.id);if(await H({title:`Tandai ${j.length} item seksi "${r.title}" sebagai N/A?`,message:"Stack-nya tak terdeteksi — cek Docker manual bila ragu.",confirmLabel:"Tandai N/A",icon:"shield"})){C(`section:${r.id}`);try{await v.markNaBulk(a,j,!0,"app-layer: stack tak terdeteksi"),I(),n(`Seksi ${r.title} ditandai N/A`,"ok","shield")}catch{n("Gagal tandai seksi N/A","err","x-circle")}finally{C(null)}}}const G=P.trim().toLowerCase(),q=!!(h.section||h.mode||h.status||h.severity)||G!=="",me=r=>(!h.section||r.section===h.section)&&(!h.mode||r.mode===h.mode)&&(!h.status||r.status===h.status)&&(!h.severity||r.severity===h.severity)&&(!G||r.title.toLowerCase().includes(G)||r.id.toLowerCase().includes(G)||(r.code??"").toLowerCase().includes(G)),Q=r=>j=>y(d=>({...d,[r]:j}));function ge(){if(k==="loading")return e.jsx(U,{kind:"loading",compact:!0,title:"Memuat checklist…"});if(k==="error"||!b)return e.jsx(U,{kind:"error",compact:!0,title:"Gagal memuat checklist",action:I});const r=b.sections.reduce((d,Z)=>d+Z.items.filter(xe=>xe.drifted).length,0),j=b.sections.map(d=>({section:d,matched:d.items.filter(me)})).filter(d=>!q||d.matched.length>0);return e.jsxs("div",{children:[e.jsxs("div",{style:{position:"sticky",top:0,zIndex:1,background:"var(--surface-card)",paddingBottom:10},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:10},children:[e.jsxs("div",{"data-testid":"score-total",style:{fontSize:22,fontWeight:700,fontFamily:"var(--font-mono)"},children:[b.scoreTotal,"%"]}),e.jsx("div",{style:{flex:1},children:e.jsx(ce,{score:b.scoreTotal})}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"skor kepatuhan"})]}),r>0&&e.jsxs("div",{"data-testid":"drift-summary",style:{display:"flex",alignItems:"center",gap:6,marginBottom:10,padding:"6px 10px",fontSize:12,color:"var(--clay-700)",background:"var(--clay-50, var(--bone-100))",border:"1px solid var(--clay-600)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"alert-triangle",size:14,color:"var(--clay-600)"}),r," item drift (regresi) sejak audit sebelumnya"]}),e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,flex:"1 1 180px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"2px 8px",background:"var(--bone-50)"},children:[e.jsx(W,{name:"search",size:13,color:"var(--text-subtle)"}),e.jsx("input",{"aria-label":"cari item",value:P,onChange:d=>w(d.target.value),placeholder:"mis. ssh atau 5.2.1",style:{flex:1,border:"none",background:"transparent",fontSize:12,color:"var(--text)",outline:"none"}})]}),e.jsx(J,{label:"seksi",value:h.section,onChange:Q("section"),options:b.sections.map(d=>[d.id,d.title])}),e.jsx(J,{label:"mode",value:h.mode,onChange:Q("mode"),options:[["AUTO","AUTO"],["AUDIT","AUDIT"],["INFO","INFO"]]}),e.jsx(J,{label:"status",value:h.status,onChange:Q("status"),options:[["pass","pass"],["fail","fail"],["warn","warn"],["na","na"],["unknown","unknown"]]}),e.jsx(J,{label:"severity",value:h.severity,onChange:Q("severity"),options:[["critical","critical"],["high","high"],["medium","medium"],["low","low"]]}),q&&e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>{y(ee),w("")},children:"Reset"})]}),R.size>0&&e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginTop:10,padding:"8px 10px",background:"var(--bone-100)",border:"1px solid var(--brass-300)",borderRadius:"var(--radius-sm)"},children:[e.jsxs("span",{style:{fontSize:12,flex:1},children:[R.size," item AUTO dipilih"]}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"eye",loading:A==="preview",onClick:M,children:"Preview"}),e.jsx(f,{size:"sm",leftIcon:"shield",loading:A==="apply",onClick:Y,children:"Apply"}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,children:"Batal"})]}),F&&e.jsxs("div",{"data-testid":"remediate-preview",style:{marginTop:10,padding:"8px 10px",fontSize:12,fontFamily:"var(--font-mono)",background:"var(--bone-50)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx("div",{style:{fontWeight:600,marginBottom:4},children:"Pratinjau (dry-run) — belum diterapkan:"}),F.map(d=>e.jsxs("div",{style:{color:"var(--text-subtle)"},children:[d.item," · ",d.status," ",d.detail]},d.item))]})]}),j.length===0?e.jsx(U,{kind:"empty",compact:!0,title:"Tak ada item cocok",hint:"Ubah kata kunci atau reset filter."}):j.map(({section:d,matched:Z})=>e.jsx($e,{section:d,items:q?Z:d.items,expanded:q?!0:B.has(d.id),onToggle:m,busy:$,selected:R,onToggleItem:t,onNa:i,onAttest:z,onSectionNa:N},d.id))]})}return e.jsxs(oe,{open:!0,width:960,icon:"clipboard-list",eyebrow:s??"VPS",title:"Checklist kepatuhan",onClose:c,children:[e.jsxs("div",{"data-testid":"vps-detail",style:{fontSize:12,color:"var(--text-subtle)",marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:[l?`Audit terakhir ${new Date(l).toLocaleString()}`:"Belum pernah diaudit",o&&` · disk ${o.disk} · mem ${o.mem} · load ${o.load}`]}),u&&e.jsx("div",{"data-testid":"vps-provisioning",style:{marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:u}),ge(),X]})}const ne={ok:"terpasang",partial:"belum siap",absent:"belum ada"},ue={ok:"var(--leaf-600)",partial:"var(--amber-600)",absent:"var(--text-subtle)"};function pe(a,s){if(s.status==="partial"&&s.detail.startsWith("not-logged-in"))return`${a} · belum login`;if(s.status==="partial")return`${a} · ${s.detail||ne.partial}`;const l=s.status==="ok"&&s.detail?` ${s.detail}`:"";return`${a} · ${ne[s.status]??s.status}${l}`}const Ie={ok:"terpasang",partial:"belum siap",absent:"belum ada"};function he({status:a,children:s,title:l}){const o=ue[a]??"var(--text-subtle)";return e.jsxs("span",{title:l,style:{display:"inline-flex",alignItems:"center",gap:5,fontSize:11,lineHeight:"18px",color:"var(--text-primary)",background:"var(--surface-sunken)",border:"1px solid var(--border-hair)",borderRadius:999,padding:"0 8px",whiteSpace:"nowrap"},children:[e.jsx("span",{"aria-hidden":!0,style:{width:6,height:6,borderRadius:"50%",background:o,flex:"0 0 auto"}}),s]})}function Be({components:a,checkedAt:s}){return!a||!s?e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa"}):e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[Object.entries(a).map(([l,o])=>e.jsx(he,{status:o.status,children:pe(l,o)},l)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:["diperiksa ",new Date(s).toLocaleString("id-ID")]})]})}const Re=a=>new Date(a).toLocaleString("id-ID",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"});function Le({components:a,checkedAt:s}){if(!a||!s)return e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa — buka detail untuk memeriksa"});const l=Object.entries(a),o=l.filter(([,c])=>c.status!=="ok"),u=l.length-o.length;return e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:8,alignItems:"center",minWidth:0},children:[e.jsx("span",{"aria-hidden":!0,style:{display:"flex",gap:2,alignItems:"center"},children:l.map(([c,n])=>e.jsx("span",{style:{width:12,height:4,borderRadius:2,background:n.status==="absent"?"var(--border-strong)":ue[n.status]}},c))}),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:[e.jsxs("strong",{style:{color:"var(--text-primary)",fontWeight:600},children:[u,"/",l.length]})," terpasang"]}),o.map(([c,n])=>e.jsxs(he,{status:n.status,title:pe(c,n),children:[c," · ",n.status==="partial"&&n.detail.startsWith("not-logged-in")?"belum login":Ie[n.status]??n.status]},c)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:["diperiksa ",Re(s)]})]})}function Ne(a,s,l){const o=new Map(s.map(n=>[n.id,n])),u=new Set,c=n=>{var b;if(!u.has(n)){u.add(n);for(const g of((b=o.get(n))==null?void 0:b.requires[l])??[])c(g)}};for(const n of a)c(n);return u}function De({vps:a,onToast:s,onGotoTerminal:l}){const[o,u]=p.useState([]),[c,n]=de("vps",`provisionProfile@${a.id}`,"lab",fe("lab","production")),[b,g]=p.useState(new Set),[k,S]=p.useState(""),[h,y]=p.useState(null),[P,w]=p.useState(null),[B,E]=p.useState(null),[$,C]=p.useState(null),{confirm:R,dialog:V}=te();p.useEffect(()=>{v.listVpsComponents().then(i=>u(i.components)).catch(()=>u([]))},[]);const F=o.filter(i=>i.profiles.includes(c)),D=Ne(b,o,c),A=[...D],L=A.some(i=>{var z;return(z=o.find(N=>N.id===i))==null?void 0:z.needsDomain}),I=A.length>0&&(!L||k.trim().length>0);function t(i){g(z=>{const N=new Set(z);return N.has(i)?N.delete(i):N.add(i),N})}async function x(){C("probe");try{w(await v.probeVps(a.id)),s("Komponen diperiksa","ok","server")}catch{s("Probe gagal","err","x-circle")}finally{C(null)}}async function m(){C("preview");try{y((await v.provisionPreview(a.id,{items:A,profile:c,domain:k||void 0})).steps)}catch{s("Pratinjau gagal","err","x-circle")}finally{C(null)}}async function H(){if(await R({title:`Pasang ${A.length} komponen di "${a.name}"?`,message:`Profil ${c}. Langkah dijalankan lewat SSH dan bisa memakan beberapa menit.`,impact:A.map(i=>{var z;return((z=o.find(N=>N.id===i))==null?void 0:z.label)??i}),confirmLabel:"Pasang",icon:"server"})){C("apply");try{const i=await v.provisionVps(a.id,{items:A,profile:c,domain:k||void 0,confirm:!0});y(i.steps),w({components:i.components,checkedAt:i.checkedAt}),E(i.setup),s("Provisioning selesai","ok","server")}catch{s("Provisioning gagal","err","x-circle")}finally{C(null)}}}const X=async()=>{try{const{id:i}=await v.vpsConsole(a.id);l(i)}catch{s("Gagal membuka console","err","x-circle")}},M=P?Object.fromEntries(P.components.map(i=>[i.id,{status:i.status,detail:i.detail}])):a.components??null,Y=(P==null?void 0:P.checkedAt)??a.componentsCheckedAt??null,_=M?Object.entries(M).filter(([,i])=>i.status==="partial"&&i.detail.startsWith("not-logged-in")):[];return e.jsxs("div",{style:{display:"grid",gap:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(Be,{components:M,checkedAt:Y}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,disabled:$!==null,children:"Periksa"})]}),e.jsx("div",{style:{display:"flex",gap:16},children:["lab","production"].map(i=>e.jsx(be,{"aria-label":i,label:i,checked:c===i,onChange:()=>n(i)},i))}),e.jsx("div",{style:{display:"grid",gap:6},children:F.map(i=>{const z=D.has(i.id)&&!b.has(i.id);return e.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[e.jsx(ke,{"aria-label":i.label,label:i.label,checked:D.has(i.id),disabled:z,onChange:()=>t(i.id)}),z&&e.jsx("span",{style:{fontSize:10,color:"var(--text-subtle)"},children:"prasyarat"})]},i.id)})}),L&&e.jsx(O,{label:"Domain",hint:"A record harus sudah menunjuk ke IP VPS ini",children:e.jsx(T,{"aria-label":"Domain",value:k,onChange:i=>S(i.currentTarget.value),placeholder:"hanoman.contoh.id"})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(f,{variant:"ghost",onClick:m,disabled:!I||$!==null,children:"Pratinjau"}),e.jsx(f,{onClick:H,disabled:!I||$!==null,children:"Pasang"})]}),h&&e.jsx("pre",{style:{fontSize:11,fontFamily:"var(--font-mono)",maxHeight:220,overflow:"auto",background:"var(--surface-sunken)",padding:8,borderRadius:4},children:h.map(i=>`${i.item.padEnd(14)} ${i.status.padEnd(6)} ${i.detail}`).join(`
|
|
2
|
-
`)}),B&&e.jsxs("div",{style:{display:"grid",gap:4,border:"1px solid var(--border-strong)",borderRadius:4,padding:8},children:[e.jsx("strong",{style:{fontSize:12},children:"Buat admin pertama"}),e.jsx("a",{href:B.url,target:"_blank",rel:"noreferrer",style:{fontSize:12,wordBreak:"break-all"},children:B.url}),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:["berlaku sampai ",new Date(B.expiresAt).toLocaleTimeString("id-ID")]}),e.jsx("div",{children:e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>{var i;return void((i=navigator.clipboard)==null?void 0:i.writeText(B.url))},children:"Salin"})})]}),_.length>0&&e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",fontSize:12},children:[e.jsx(W,{name:"alert-triangle"}),e.jsxs("span",{children:[_.map(([i])=>i).join(", ")," terpasang tapi belum login."]}),e.jsx(f,{size:"sm",variant:"ghost",onClick:X,children:"Login lewat Console"})]}),V]})}const ie=(a,s=Date.now())=>!!a.lastSeenAt&&s-new Date(a.lastSeenAt).getTime()<10*6e4,Ve=a=>a.lastAuditAt?a.hardened?"hardened":"belum":"unknown",Oe={hardened:{status:"ok",label:"hardened"},belum:{status:"broken",label:"belum hardened"},unknown:{status:"idle",label:"belum diaudit"}};function re(a){const s={name:a.name.trim(),host:a.host.trim(),user:a.user.trim(),port:Number(a.port)||22};return a.keyPath.trim()&&(s.keyPath=a.keyPath.trim()),a.password&&(s.password=a.password),s}const Te="opsional — dipakai sekali untuk memasang key hanoman, tidak disimpan";function ae({open:a,title:s,submitLabel:l,initial:o,onClose:u,onSubmit:c}){const[n,b]=p.useState(o);p.useEffect(()=>{a&&b(o)},[a,o]);const g=S=>h=>b(y=>({...y,[S]:h.target.value})),k=!!(n.name.trim()&&n.host.trim()&&n.user.trim());return e.jsxs(oe,{open:a,onClose:u,icon:"server",eyebrow:"infra",title:s,footer:e.jsxs(e.Fragment,{children:[e.jsx(f,{variant:"ghost",size:"sm",onClick:u,children:"Batal"}),e.jsx(f,{size:"sm",leftIcon:"check",onClick:()=>k&&c(n),children:l})]}),children:[e.jsx(O,{label:"Nama",children:e.jsx(T,{value:n.name,onChange:g("name"),placeholder:"mis. web-1",style:{width:"100%"}})}),e.jsx(O,{label:"Host",hint:"hostname atau IP — tanpa user@",children:e.jsx(T,{value:n.host,onChange:g("host"),mono:!0,placeholder:"203.0.113.10",style:{width:"100%"}})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1.4fr 1fr",gap:12},children:[e.jsx(O,{label:"User SSH",hint:"root atau user ber-passwordless-sudo",children:e.jsx(T,{value:n.user,onChange:g("user"),mono:!0,placeholder:"deploy",style:{width:"100%"}})}),e.jsx(O,{label:"Port",children:e.jsx(T,{value:n.port,onChange:g("port"),mono:!0,placeholder:"22",style:{width:"100%"}})})]}),e.jsx(O,{label:"Password SSH",hint:Te,children:e.jsx(T,{type:"password",value:n.password,onChange:g("password"),placeholder:"••••••••",style:{width:"100%"}})}),e.jsx(O,{label:"Key path",hint:"kosongkan bila memakai password di atas, atau key default mesin server",children:e.jsx(T,{value:n.keyPath,onChange:g("keyPath"),mono:!0,placeholder:"~/.ssh/id_ed25519",style:{width:"100%"}})})]})}const le={name:"",host:"",user:"",port:"22",keyPath:"",password:""},We=a=>({name:a.name,host:a.host,user:a.user,port:String(a.port),keyPath:a.keyPath??"",password:""});function Me({onToast:a,onGotoTerminal:s}){const[l,o]=p.useState([]),[u,c]=p.useState("loading"),[n,b]=p.useState(null),[g,k]=p.useState(null),[S,h]=de("vps","detailId",null,ve),y=p.useMemo(()=>l.find(t=>t.id===S)??null,[l,S]),P=p.useCallback(t=>h(t?t.id:null),[h]),w=p.useCallback(()=>{v.listVps().then(t=>{o(t),c("ready")}).catch(()=>c("error"))},[]);p.useEffect(()=>(w(),ye(t=>{t.t==="vps"&&(o(t.vps),c("ready"))})),[w]);const{confirm:B,dialog:E}=te();async function $(t,x,m,H){b(`${t}:${x}`);try{await m(),w(),a(H,"ok","server")}catch{a(`Gagal ${t}`,"err","x-circle")}finally{b(null)}}const C=t=>$("audit",t.id,()=>v.auditVps(t.id),`${t.name} · audit selesai`);async function R(t){await B({title:`Harden "${t.name}"?`,message:"Pastikan akses key SSH non-password kamu sudah bekerja sebelum melanjutkan.",impact:[`Firewall: izinkan ${t.port}/80/443.`,"fail2ban & auto security update dipasang.","PermitRootLogin & PasswordAuthentication dimatikan.","NTP disinkronkan."],confirmLabel:"Harden",icon:"shield"})&&$("harden",t.id,()=>v.hardenVps(t.id),`${t.name} · harden selesai`)}const V=t=>$("sesi",t.id,async()=>{const{id:x}=await v.vpsSession(t.id);s(x)},`${t.name} · sesi Claude dibuka`),F=t=>$("test",t.id,async()=>{const x=await v.testVps(t.id);if(!x.ok)throw new Error(x.out)},`${t.name} · koneksi ok`),D=t=>$("console",t.id,async()=>{const{id:x}=await v.vpsConsole(t.id);s(x)},`${t.name} · console dibuka`);async function A(t){try{if(!await B({title:`Hapus registrasi VPS "${t.name}"?`,message:"Server-nya sendiri tak disentuh — hanya pendaftarannya di dashboard ini yang dihapus.",confirmLabel:"Hapus registrasi",run:()=>v.deleteVps(t.id)}))return;w()}catch{a("Gagal hapus","err","x-circle")}}async function L(t){try{const x=await v.createVps(re(t));k(null),w(),a(t.password?`${x.name} terdaftar · key hanoman terpasang · password dibuang`:`${x.name} terdaftar · jalankan audit`,"ok","server")}catch{a("Gagal mendaftarkan VPS — cek host/user, atau password SSH-nya","err","x-circle")}}async function I(t,x){try{const m=await v.updateVps(t.id,re(x));k(null),w(),a(x.password?`${m.name} diperbarui · key hanoman terpasang · password dibuang`:`${m.name} diperbarui`,"ok","server")}catch{a("Gagal memperbarui VPS","err","x-circle")}}return u==="loading"?e.jsx(U,{kind:"loading",title:"Memuat daftar VPS…"}):u==="error"?e.jsx(U,{kind:"error",title:"Gagal memuat daftar VPS",hint:"Pastikan server hanoman berjalan.",action:w}):l.length===0?e.jsxs(e.Fragment,{children:[e.jsx(U,{kind:"empty",icon:"server",title:"Belum ada VPS",hint:"Daftarkan VPS untuk mulai audit & hardening.",action:()=>k("new"),actionLabel:"Daftarkan VPS"}),e.jsx(ae,{open:g==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:le,onClose:()=>k(null),onSubmit:L})]}):e.jsxs("div",{children:[e.jsxs("div",{children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:10},children:e.jsx(f,{size:"sm",leftIcon:"plus",onClick:()=>k("new"),children:"Daftarkan VPS"})}),l.map(t=>{const x=Oe[Ve(t)];return e.jsxs("div",{className:"hn-vps-row",onClick:()=>P(t),style:{padding:"10px 12px",cursor:"pointer",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",marginBottom:8},children:[e.jsxs("div",{className:"hn-vps-main",children:[e.jsxs("button",{type:"button","aria-label":`Buka detail ${t.name}`,onClick:m=>{m.stopPropagation(),P(t)},style:{display:"flex",alignItems:"center",gap:10,flex:"1 1 220px",minWidth:0,cursor:"pointer",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:0,border:"none"},children:[e.jsx(W,{name:"server",size:16,color:"var(--brass-700)"}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{style:{display:"block",fontSize:13,fontWeight:600,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.name}),e.jsxs("span",{style:{display:"block",fontSize:12,fontFamily:"var(--font-mono)",color:"var(--text-subtle)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[t.user,"@",t.host,t.port!==22?`:${t.port}`:""]})]})]}),e.jsxs("div",{className:"hn-vps-pills",style:{display:"flex",gap:6,alignItems:"center",flexShrink:0},children:[e.jsx(se,{size:"sm",status:ie(t)?"ok":"broken",children:ie(t)?"reachable":"unreachable"}),e.jsx(se,{size:"sm",status:x.status,children:x.label})]}),e.jsxs("div",{className:"hn-vps-actions",children:[e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"plug-zap",loading:n===`test:${t.id}`,onClick:m=>{m.stopPropagation(),F(t)},children:"Test"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"terminal-square",loading:n===`console:${t.id}`,onClick:m=>{m.stopPropagation(),D(t)},children:"Console"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"terminal",loading:n===`sesi:${t.id}`,onClick:m=>{m.stopPropagation(),V(t)},children:"Sesi Claude"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"radar",loading:n===`audit:${t.id}`,onClick:m=>{m.stopPropagation(),C(t)},children:"Audit"}),e.jsx(f,{size:"sm",leftIcon:"shield",loading:n===`harden:${t.id}`,onClick:m=>{m.stopPropagation(),R(t)},children:"Harden"}),e.jsx("span",{"aria-hidden":!0,className:"hn-vps-sep"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"pencil",title:`Edit ${t.name}`,onClick:m=>{m.stopPropagation(),k(t)}}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"trash-2",title:`Hapus ${t.name}`,onClick:m=>{m.stopPropagation(),A(t)}})]})]}),e.jsx("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:e.jsx(Le,{components:t.components??null,checkedAt:t.componentsCheckedAt??null})})]},t.id)})]}),y&&e.jsx(Ae,{vpsId:y.id,vpsName:y.name,lastAuditAt:y.lastAuditAt,health:y.health,provisioning:e.jsx(De,{vps:y,onToast:a,onGotoTerminal:s}),onClose:()=>{P(null),w()},onToast:a}),e.jsx(ae,{open:g==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:le,onClose:()=>k(null),onSubmit:L}),g&&g!=="new"&&e.jsx(ae,{open:!0,title:`Edit ${g.name}`,submitLabel:"Simpan",initial:We(g),onClose:()=>k(null),onSubmit:t=>I(g,t)}),E]})}export{Me as VpsScreen,Ve as hardenedLabel,ie as isReachable,re as vpsFormToBody};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as t,I as v,f as W}from"./index-Bd9gXx1g.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";function F(s,n=[]){const i={path:"",kids:[]},r=(o,p)=>{let e=i;const c=o.split("/").filter(Boolean);c.forEach((a,x)=>{const y=p&&x===c.length-1,m=e.path?e.path+"/"+a:a;let d=e.kids.find(u=>u.name===a&&u.leaf===y);d||(d={name:a,path:m,kids:[],leaf:y},e.kids.push(d)),e=d})};for(const o of s)r(o,!0);for(const o of n)r(o,!1);const l=o=>{o.kids.sort((p,e)=>p.leaf===e.leaf?p.name.localeCompare(e.name):p.leaf?1:-1),o.kids.forEach(l)};return l(i),i.kids}const j={A:"var(--leaf-600)",M:"var(--brass-600)",D:"var(--clay-500)"};function k({node:s,selected:n,onSelect:i,depth:r=0,meta:l,defaultOpen:o=!1,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a}){const[x,y]=g.useState(o),[m,d]=g.useState(!1),u=c!=null&&c.has(s.path)?.62:1;if(s.leaf){const f=s.path===n,h=l==null?void 0:l[s.path];return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 8px",paddingLeft:22+r*12,border:"none",cursor:"pointer",textAlign:"left",background:f?"var(--brass-100)":"transparent",opacity:u},children:[h?t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[h.status]},children:h.status}):t.jsx(v,{name:"file-text",size:13,color:f?"var(--brass-700)":"var(--text-subtle)"}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:f?"var(--brass-700)":"var(--text-body)",fontWeight:f?600:400},children:s.name}),h&&!h.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",h.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",h.del]})]})]})}const b=!!e&&s.path===p,w=!!a&&s.kids.length===0;async function z(){e==null||e(s.path);const f=!x;if(y(f),f&&w&&!m){d(!0);try{await(a==null?void 0:a(s.path))}finally{d(!1)}}}return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>void z(),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 6px",paddingLeft:6+r*12,border:"none",background:b?"var(--brass-100)":"transparent",cursor:"pointer",textAlign:"left",opacity:u},children:[t.jsx(v,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),t.jsx(v,{name:"folder",size:15,color:b?"var(--brass-700)":"var(--brass-500)"}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:b?"var(--brass-700)":"var(--text-strong)",fontWeight:b?700:500},children:[s.name,"/"]}),m&&t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),x&&s.kids.map(f=>t.jsx(k,{node:f,selected:n,onSelect:i,depth:r+1,meta:l,defaultOpen:o,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a},f.path)),x&&!m&&s.kids.length===0&&t.jsx("div",{style:{padding:"4px 8px",paddingLeft:28+r*12,fontSize:11.5,color:"var(--text-subtle)"},children:"kosong"})]})}function S({cf:s,selected:n,onSelect:i}){const r=s.path===n;return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 10px",border:"none",cursor:"pointer",textAlign:"left",background:r?"var(--brass-100)":"transparent"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[s.status]},children:s.status}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:r?"var(--brass-700)":"var(--text-body)"},children:s.path}),!s.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",s.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",s.del]})]})]})}function T({label:s,changed:n,selected:i,onSelect:r,view:l,onView:o,emptyText:p="Tak ada file berubah."}){const e=g.useMemo(()=>F(n.map(a=>a.path)),[n]),c=g.useMemo(()=>Object.fromEntries(n.map(a=>[a.path,a])),[n]);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"hn-eyebrow",style:{display:"flex",alignItems:"center",gap:6,padding:"6px 8px"},children:[t.jsxs("span",{style:{flex:1},children:[s," · ",n.length]}),n.length>0&&["list","tree"].map(a=>t.jsx("button",{"aria-label":`${a==="list"?"List":"Tree"} ${s}`,onClick:()=>o(a),style:{display:"flex",padding:3,border:"none",cursor:"pointer",borderRadius:4,background:l===a?"var(--brass-100)":"transparent"},children:t.jsx(v,{name:a==="list"?"list":"folder-tree",size:14,color:l===a?"var(--brass-700)":"var(--text-subtle)"})},a))]}),n.length===0?t.jsx("div",{style:{padding:"4px 10px",fontSize:12,color:"var(--text-subtle)"},children:p}):l==="tree"?e.map(a=>t.jsx(k,{node:a,selected:i,onSelect:r,meta:c,defaultOpen:!0},a.path)):n.map(a=>t.jsx(S,{cf:a,selected:i,onSelect:r},a.path))]})}function I({diff:s,emptyTitle:n="Tidak ada perubahan pada file ini",emptyHint:i}){return s?t.jsx("pre",{style:{margin:0,fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6},children:s.split(`
|
|
2
|
-
`).map((r,l)=>{const o=r.startsWith("+")&&!r.startsWith("+++"),p=r.startsWith("-")&&!r.startsWith("---"),e=r.startsWith("@@"),c=o?"var(--leaf-600)":p?"var(--clay-600)":e?"var(--brass-700)":"var(--text-body)",a=o?"color-mix(in srgb, var(--leaf-500) 10%, transparent)":p?"color-mix(in srgb, var(--clay-500) 10%, transparent)":"transparent";return t.jsx("div",{style:{color:c,background:a,padding:"0 12px",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:r||" "},l)})}):t.jsx(W,{kind:"empty",icon:"check",title:n,hint:i})}export{T as C,I as D,k as T,F as b};
|