@burdenoff/microfe-vibecontrols 2026.528.2 → 2026.528.3

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/README.md CHANGED
@@ -5,6 +5,7 @@ VibeControls microfrontend for Burdenoff products - a modern development environ
5
5
  ## Overview
6
6
 
7
7
  This microfrontend provides:
8
+
8
9
  - **Agents Management**: Control and monitor development agents
9
10
  - **Sessions**: Terminal and SSH session management
10
11
  - **Vibes**: Project workflow management
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogDetail.js","names":[],"sources":["../../../src/components/audit/AuditLogDetail.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useEffect, useState } from 'react';\nimport { X, ChevronDown, ChevronRight, Copy, Check, Terminal } from 'lucide-react';\nimport type { VibeAuditLogDetailFragment } from '@/generated/wspace-operations';\nimport { StatusBadge } from '@/components/shared';\n\ninterface AuditLogDetailProps {\n log: VibeAuditLogDetailFragment;\n onClose: () => void;\n}\n\nfunction JsonViewer({ data, label }: { data: unknown; label: string }) {\n const [expanded, setExpanded] = useState(false);\n if (!data) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n {label}\n </button>\n {expanded && (\n <pre className=\"px-3 py-2 text-xs overflow-auto max-h-64 bg-bg-sunken\">\n {JSON.stringify(data, null, 2)}\n </pre>\n )}\n </div>\n );\n}\n\nfunction CommandBlock({\n command,\n output,\n exitCode,\n}: {\n command?: string | null;\n output?: string | null;\n exitCode?: number | null;\n}) {\n const [copied, setCopied] = useState(false);\n if (!command && !output) return null;\n\n const handleCopy = () => {\n if (command) {\n navigator.clipboard.writeText(command);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-2 bg-bg-secondary/50\">\n <span className=\"flex items-center gap-2 text-sm font-medium\">\n <Terminal size={14} />\n Command Execution\n {exitCode !== null && exitCode !== undefined && (\n <span\n className={`px-1.5 py-0.5 rounded text-xs ${exitCode === 0 ? 'bg-status-success-bg text-status-success-text' : 'bg-status-error-bg text-status-error-text'}`}\n >\n exit {exitCode}\n </span>\n )}\n </span>\n {command && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"p-1 rounded hover:bg-bg-secondary text-text-secondary\"\n title=\"Copy command\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n )}\n </div>\n {command && (\n <div className=\"px-3 py-2 bg-bg-sunken text-text-secondary font-mono text-xs\">\n <span className=\"text-status-success-text\">$</span> {command}\n </div>\n )}\n {output && (\n <pre className=\"px-3 py-2 text-xs bg-bg-sunken text-text-tertiary font-mono overflow-auto max-h-48\">\n {output}\n </pre>\n )}\n </div>\n );\n}\n\nfunction ChangesetViewer({ changeset }: { changeset: Record<string, unknown> | null | undefined }) {\n const [expanded, setExpanded] = useState(false);\n if (!changeset || typeof changeset !== 'object') return null;\n\n const changes = Object.entries(changeset as Record<string, { from: unknown; to: unknown }>);\n if (changes.length === 0) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n Changes ({changes.length} field{changes.length !== 1 ? 's' : ''})\n </button>\n {expanded && (\n <div className=\"px-3 py-2 space-y-2\">\n {changes.map(([field, change]) => (\n <div key={field} className=\"text-xs\">\n <span className=\"font-medium text-text-primary\">{field}</span>\n <div className=\"ml-4 mt-1 space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-error-text font-mono\">-</span>\n <span className=\"text-status-error-text\">\n {JSON.stringify((change as { from: unknown }).from)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-success-text font-mono\">+</span>\n <span className=\"text-status-success-text\">\n {JSON.stringify((change as { to: unknown }).to)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function AuditLogDetail({ log, onClose }: AuditLogDetailProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-[1000] flex justify-end bg-bg-overlay/40\">\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetailOverlay', 'Close audit log detail')}\n className=\"absolute inset-0 cursor-default\"\n onClick={onClose}\n />\n <aside className=\"relative flex h-full w-full max-w-[480px] flex-col border-l border-border-default bg-bg-surface shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <div>\n <h3 className=\"text-sm font-semibold\">\n {log.action.replace(/_/g, ' ')}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {log.resourceType.replace(/_/g, ' ')}\n {log.resourceName ? ` · ${log.resourceName}` : ''}\n </p>\n <details className=\"mt-1\">\n <summary className=\"cursor-pointer text-[10px] uppercase tracking-wider text-text-secondary hover:text-text-primary\">\n Event ID\n </summary>\n <span className=\"mt-1 block break-all font-mono text-[11px] text-text-secondary\">\n {log.id}\n </span>\n </details>\n </div>\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetail', 'Close audit log detail')}\n onClick={onClose}\n className=\"flex size-10 items-center justify-center rounded hover:bg-bg-secondary\"\n >\n <X size={16} />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Summary */}\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <span className=\"text-text-secondary text-xs\">Action</span>\n <div className=\"font-medium\">{log.action}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Status</span>\n <div>\n <StatusBadge status={log.status} size=\"sm\" />\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource Type</span>\n <div className=\"font-medium\">{log.resourceType.replace(/_/g, ' ')}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource ID</span>\n <div className=\"font-mono text-xs truncate\">{log.resourceId || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Resource Name</span>\n <div>{log.resourceName || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Description</span>\n <div className=\"text-text-secondary\">{log.description || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Actor</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"capitalize\">\n {(log.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </span>\n <details className=\"text-xs text-text-secondary\">\n <summary className=\"cursor-pointer hover:text-text-primary\">\n ID\n </summary>\n <span className=\"ml-2 break-all font-mono text-[11px]\">\n {log.actorId}\n </span>\n </details>\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Timestamp</span>\n <div className=\"text-xs\">{new Date(log.createdAt).toLocaleString()}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">IP Address</span>\n <div className=\"font-mono text-xs\">{log.ipAddress || '-'}</div>\n </div>\n {log.expiresAt && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Expires At</span>\n <div className=\"text-xs text-status-warning-text\">\n {new Date(log.expiresAt).toLocaleString()}\n </div>\n </div>\n )}\n {log.errorMessage && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Error</span>\n <div className=\"text-status-error-text text-xs\">{log.errorMessage}</div>\n </div>\n )}\n {log.deleteReason && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Delete Reason</span>\n <div className=\"text-xs\">{log.deleteReason}</div>\n </div>\n )}\n </div>\n\n {/* Command execution */}\n <CommandBlock command={log.command} output={log.output} exitCode={log.exitCode} />\n\n {/* Changeset */}\n <ChangesetViewer changeset={log.changeset as Record<string, unknown> | null} />\n\n {/* State snapshots */}\n <JsonViewer data={log.previousState} label=\"Previous State\" />\n <JsonViewer data={log.newState} label=\"New State\" />\n <JsonViewer data={log.metadata} label=\"Metadata\" />\n </div>\n </aside>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAWA,SAAS,EAAW,EAAE,SAAM,YAA2C;CACrE,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAG/C,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ,CAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B,EACjE,EACM;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,KAAK,UAAU,GAAM,MAAM,EAAE;GAC1B,CAAA,CAEJ;MAjBU;;AAqBpB,SAAS,EAAa,EACpB,YACA,WACA,eAKC;CACD,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM;AAW3C,QAVI,CAAC,KAAW,CAAC,IAAe,OAW9B,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAhB;MACE,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;;MAErB,KAAa,QACZ,kBAAC,QAAD;OACE,WAAW,iCAAiC,MAAa,IAAI,kDAAkD;iBADjH,CAEC,SACO,EACD;;MAEJ;QACN,KACC,kBAAC,UAAD;KACE,MAAK;KACL,eAzBe;AACvB,MAAI,MACF,UAAU,UAAU,UAAU,EAAQ,EACtC,EAAU,GAAK,EACf,iBAAiB,EAAU,GAAM,EAAE,IAAK;;KAsBlC,WAAU;KACV,OAAM;eAEI,EAAT,IAAU,IAAsB,GAAvB,EAAO,MAAM,IAAM,CAAqB;KAC3C,CAAA,CAEP;;GACL,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAA2B;MAAQ,CAAA;;KAAE;KACjD;;GAEP,KACC,kBAAC,OAAD;IAAK,WAAU;cACZ;IACG,CAAA;GAEJ;;;AAIV,SAAS,EAAgB,EAAE,gBAAwE;CACjG,IAAM,CAAC,GAAU,KAAe,EAAS,GAAM;AAC/C,KAAI,CAAC,KAAa,OAAO,KAAc,SAAU,QAAO;CAExD,IAAM,IAAU,OAAO,QAAQ,EAA4D;AAG3F,QAFI,EAAQ,WAAW,IAAU,OAG/B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAY,CAAC,EAAS;GACrC,WAAU;aAHZ;IAKc,EAAX,IAAY,IAA4B,GAA7B,EAAa,MAAM,IAAM,CAA6B;IAAC;IACzD,EAAQ;IAAO;IAAO,EAAQ,WAAW,IAAU,KAAN;IAAS;IACzD;MACR,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,KAAK,CAAC,GAAO,OACpB,kBAAC,OAAD;IAAiB,WAAU;cAA3B,CACE,kBAAC,QAAD;KAAM,WAAU;eAAiC;KAAa,CAAA,EAC9D,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAmC;OAAQ,CAAA,EAC3D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA6B,KAAK;OAC9C,CAAA,CACH;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAqC;OAAQ,CAAA,EAC7D,kBAAC,QAAD;OAAM,WAAU;iBACb,KAAK,UAAW,EAA2B,GAAG;OAC1C,CAAA,CACH;QACF;OACF;MAhBI,EAgBJ,CACN;GACE,CAAA,CAEJ;;;AAIV,SAAgB,EAAe,EAAE,QAAK,cAAgC;CACpE,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;;AAchC,QAXA,QAAgB;EACd,IAAM,KAAiB,MAAyB;AAC9C,GAAI,EAAM,QAAQ,YAChB,GAAS;;AAKb,SADA,OAAO,iBAAiB,WAAW,EAAc,QACpC,OAAO,oBAAoB,WAAW,EAAc;IAChE,CAAC,EAAQ,CAAC,EAGX,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GACE,MAAK;GACL,cAAY,EAAG,4BAA4B,yBAAyB;GACpE,WAAU;GACV,SAAS;GACT,CAAA,EACF,kBAAC,SAAD;GAAO,WAAU;aAAjB,CAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAI,OAAO,QAAQ,MAAM,IAAI;MAC3B,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,EAAI,aAAa,QAAQ,MAAM,IAAI,EACnC,EAAI,eAAe,MAAM,EAAI,iBAAiB,GAC7C;;KACJ,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,WAAD;OAAS,WAAU;iBAAkG;OAE3G,CAAA,EACV,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAI;OACA,CAAA,CACC;;KACN,EAAA,CAAA,EACN,kBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAG,qBAAqB,yBAAyB;KAC7D,SAAS;KACT,WAAU;eAEV,kBAAC,GAAD,EAAG,MAAM,IAAM,CAAA;KACR,CAAA,CACL;OAGN,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI;QAAa,CAAA,CAC3C,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAa,CAAA,EAC3D,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;QAAa,QAAQ,EAAI;QAAQ,MAAK;QAAO,CAAA,EACzC,CAAA,CACF,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAoB,CAAA,EAClE,kBAAC,OAAD;QAAK,WAAU;kBAAe,EAAI,aAAa,QAAQ,MAAM,IAAI;QAAO,CAAA,CACpE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAkB,CAAA,EAChE,kBAAC,OAAD;QAAK,WAAU;kBAA8B,EAAI,cAAc;QAAU,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD,EAAA,UAAM,EAAI,gBAAgB,KAAU,CAAA,CAChC;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAkB,CAAA,EAChE,kBAAC,OAAD;SAAK,WAAU;mBAAuB,EAAI,eAAe;SAAU,CAAA,CAC/D;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,QAAD;UAAM,WAAU;qBACZ,EAAI,aAAa,WAAW,aAAa,CAAC,QAAQ,MAAM,IAAI;UACzD,CAAA,EACP,kBAAC,WAAD;UAAS,WAAU;oBAAnB,CACE,kBAAC,WAAD;WAAS,WAAU;qBAAyC;WAElD,CAAA,EACV,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAI;WACA,CAAA,CACC;YACN;WACF;;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAgB,CAAA,EAC9D,kBAAC,OAAD;QAAK,WAAU;kBAAW,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;QAAO,CAAA,CACrE,EAAA,CAAA;OACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAiB,CAAA,EAC/D,kBAAC,OAAD;QAAK,WAAU;kBAAqB,EAAI,aAAa;QAAU,CAAA,CAC3D,EAAA,CAAA;OACL,EAAI,aACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAiB,CAAA,EAC/D,kBAAC,OAAD;SAAK,WAAU;mBACZ,IAAI,KAAK,EAAI,UAAU,CAAC,gBAAgB;SACrC,CAAA,CACF;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAY,CAAA,EAC1D,kBAAC,OAAD;SAAK,WAAU;mBAAkC,EAAI;SAAmB,CAAA,CACpE;;OAEP,EAAI,gBACH,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAA8B;SAAoB,CAAA,EAClE,kBAAC,OAAD;SAAK,WAAU;mBAAW,EAAI;SAAmB,CAAA,CAC7C;;OAEJ;;KAGN,kBAAC,GAAD;MAAc,SAAS,EAAI;MAAS,QAAQ,EAAI;MAAQ,UAAU,EAAI;MAAY,CAAA;KAGlF,kBAAC,GAAD,EAAiB,WAAW,EAAI,WAA+C,CAAA;KAG/E,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAe,OAAM;MAAmB,CAAA;KAC9D,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAc,CAAA;KACpD,kBAAC,GAAD;MAAY,MAAM,EAAI;MAAU,OAAM;MAAa,CAAA;KAC/C;MACA;KACJ"}
1
+ {"version":3,"file":"AuditLogDetail.js","names":[],"sources":["../../../src/components/audit/AuditLogDetail.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useEffect, useState } from 'react';\nimport { X, ChevronDown, ChevronRight, Copy, Check, Terminal } from 'lucide-react';\nimport type { VibeAuditLogDetailFragment } from '@/generated/wspace-operations';\nimport { StatusBadge } from '@/components/shared';\n\ninterface AuditLogDetailProps {\n log: VibeAuditLogDetailFragment;\n onClose: () => void;\n}\n\nfunction JsonViewer({ data, label }: { data: unknown; label: string }) {\n const [expanded, setExpanded] = useState(false);\n if (!data) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n {label}\n </button>\n {expanded && (\n <pre className=\"px-3 py-2 text-xs overflow-auto max-h-64 bg-bg-sunken\">\n {JSON.stringify(data, null, 2)}\n </pre>\n )}\n </div>\n );\n}\n\nfunction CommandBlock({\n command,\n output,\n exitCode,\n}: {\n command?: string | null;\n output?: string | null;\n exitCode?: number | null;\n}) {\n const [copied, setCopied] = useState(false);\n if (!command && !output) return null;\n\n const handleCopy = () => {\n if (command) {\n navigator.clipboard.writeText(command);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n };\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-2 bg-bg-secondary/50\">\n <span className=\"flex items-center gap-2 text-sm font-medium\">\n <Terminal size={14} />\n Command Execution\n {exitCode !== null && exitCode !== undefined && (\n <span\n className={`px-1.5 py-0.5 rounded text-xs ${exitCode === 0 ? 'bg-status-success-bg text-status-success-text' : 'bg-status-error-bg text-status-error-text'}`}\n >\n exit {exitCode}\n </span>\n )}\n </span>\n {command && (\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"p-1 rounded hover:bg-bg-secondary text-text-secondary\"\n title=\"Copy command\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n )}\n </div>\n {command && (\n <div className=\"px-3 py-2 bg-bg-sunken text-text-secondary font-mono text-xs\">\n <span className=\"text-status-success-text\">$</span> {command}\n </div>\n )}\n {output && (\n <pre className=\"px-3 py-2 text-xs bg-bg-sunken text-text-tertiary font-mono overflow-auto max-h-48\">\n {output}\n </pre>\n )}\n </div>\n );\n}\n\nfunction ChangesetViewer({ changeset }: { changeset: Record<string, unknown> | null | undefined }) {\n const [expanded, setExpanded] = useState(false);\n if (!changeset || typeof changeset !== 'object') return null;\n\n const changes = Object.entries(changeset as Record<string, { from: unknown; to: unknown }>);\n if (changes.length === 0) return null;\n\n return (\n <div className=\"border border-border-primary rounded-lg overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm font-medium bg-bg-secondary/50 hover:bg-bg-secondary\"\n >\n {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n Changes ({changes.length} field{changes.length !== 1 ? 's' : ''})\n </button>\n {expanded && (\n <div className=\"px-3 py-2 space-y-2\">\n {changes.map(([field, change]) => (\n <div key={field} className=\"text-xs\">\n <span className=\"font-medium text-text-primary\">{field}</span>\n <div className=\"ml-4 mt-1 space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-error-text font-mono\">-</span>\n <span className=\"text-status-error-text\">\n {JSON.stringify((change as { from: unknown }).from)}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-status-success-text font-mono\">+</span>\n <span className=\"text-status-success-text\">\n {JSON.stringify((change as { to: unknown }).to)}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nexport function AuditLogDetail({ log, onClose }: AuditLogDetailProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n onClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onClose]);\n\n return (\n <div className=\"fixed inset-0 z-[1000] flex justify-end bg-bg-overlay/40\">\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetailOverlay', 'Close audit log detail')}\n className=\"absolute inset-0 cursor-default\"\n onClick={onClose}\n />\n <aside className=\"relative flex h-full w-full max-w-[480px] flex-col border-l border-border-default bg-bg-surface shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <div>\n <h3 className=\"text-sm font-semibold\">{log.action.replace(/_/g, ' ')}</h3>\n <p className=\"text-xs text-text-secondary\">\n {log.resourceType.replace(/_/g, ' ')}\n {log.resourceName ? ` · ${log.resourceName}` : ''}\n </p>\n <details className=\"mt-1\">\n <summary className=\"cursor-pointer text-[10px] uppercase tracking-wider text-text-secondary hover:text-text-primary\">\n Event ID\n </summary>\n <span className=\"mt-1 block break-all font-mono text-[11px] text-text-secondary\">\n {log.id}\n </span>\n </details>\n </div>\n <button\n type=\"button\"\n aria-label={tr('audit.closeDetail', 'Close audit log detail')}\n onClick={onClose}\n className=\"flex size-10 items-center justify-center rounded hover:bg-bg-secondary\"\n >\n <X size={16} />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-4 space-y-4\">\n {/* Summary */}\n <div className=\"grid grid-cols-2 gap-3 text-sm\">\n <div>\n <span className=\"text-text-secondary text-xs\">Action</span>\n <div className=\"font-medium\">{log.action}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Status</span>\n <div>\n <StatusBadge status={log.status} size=\"sm\" />\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource Type</span>\n <div className=\"font-medium\">{log.resourceType.replace(/_/g, ' ')}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Resource ID</span>\n <div className=\"font-mono text-xs truncate\">{log.resourceId || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Resource Name</span>\n <div>{log.resourceName || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Description</span>\n <div className=\"text-text-secondary\">{log.description || '-'}</div>\n </div>\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Actor</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"capitalize\">\n {(log.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </span>\n <details className=\"text-xs text-text-secondary\">\n <summary className=\"cursor-pointer hover:text-text-primary\">ID</summary>\n <span className=\"ml-2 break-all font-mono text-[11px]\">{log.actorId}</span>\n </details>\n </div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">Timestamp</span>\n <div className=\"text-xs\">{new Date(log.createdAt).toLocaleString()}</div>\n </div>\n <div>\n <span className=\"text-text-secondary text-xs\">IP Address</span>\n <div className=\"font-mono text-xs\">{log.ipAddress || '-'}</div>\n </div>\n {log.expiresAt && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Expires At</span>\n <div className=\"text-xs text-status-warning-text\">\n {new Date(log.expiresAt).toLocaleString()}\n </div>\n </div>\n )}\n {log.errorMessage && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Error</span>\n <div className=\"text-status-error-text text-xs\">{log.errorMessage}</div>\n </div>\n )}\n {log.deleteReason && (\n <div className=\"col-span-2\">\n <span className=\"text-text-secondary text-xs\">Delete Reason</span>\n <div className=\"text-xs\">{log.deleteReason}</div>\n </div>\n )}\n </div>\n\n {/* Command execution */}\n <CommandBlock command={log.command} output={log.output} exitCode={log.exitCode} />\n\n {/* Changeset */}\n <ChangesetViewer changeset={log.changeset as Record<string, unknown> | null} />\n\n {/* State snapshots */}\n <JsonViewer data={log.previousState} label=\"Previous State\" />\n <JsonViewer data={log.newState} label=\"New State\" />\n <JsonViewer data={log.metadata} label=\"Metadata\" />\n </div>\n </aside>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuditLogTable.js","names":[],"sources":["../../../src/components/audit/AuditLogTable.tsx"],"sourcesContent":["import { ChevronRight, Terminal, Trash2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StatusBadge } from '@/components/shared';\nimport { SelectionCheckbox } from '@/components/shared/SelectionCheckbox';\nimport type { VibeAuditLogFieldsFragment } from '@/generated/wspace-operations';\n\ninterface AuditLogTableProps {\n items: VibeAuditLogFieldsFragment[];\n total: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n onPageChange: (page: number) => void;\n onSelectLog: (id: string) => void;\n onDeleteLog: (id: string) => void;\n selectedLogId: string | null;\n selectedLogIds: Set<string>;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n onToggleLogSelection: (id: string, checked: boolean) => void;\n onToggleAllVisible: (checked: boolean) => void;\n}\n\nconst statusVariantMap: Record<string, 'success' | 'error' | 'warning' | 'info'> = {\n SUCCESS: 'success',\n FAILURE: 'error',\n DENIED: 'warning',\n ERROR: 'error',\n};\n\nconst actionColors: Record<string, string> = {\n CREATE: 'bg-status-success-bg text-status-success-text',\n UPDATE: 'bg-status-info-bg text-status-info-text',\n DELETE: 'bg-status-error-bg text-status-error-text',\n EXECUTE: 'bg-action-primary-bg/15 text-action-primary-text',\n EXPORT: 'bg-status-warning-bg text-status-warning-text',\n SHARE: 'bg-status-success-bg text-status-success-text',\n REVOKE: 'bg-status-warning-bg text-status-warning-text',\n ARCHIVE: 'bg-bg-muted text-text-secondary',\n RESTORE: 'bg-status-info-bg text-status-info-text',\n};\n\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction formatResourceType(type: string): string {\n return type\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n}\n\nexport function AuditLogTable({\n items,\n total,\n hasMore,\n page,\n pageSize,\n onPageChange,\n onSelectLog,\n onDeleteLog,\n selectedLogId,\n selectedLogIds,\n allVisibleSelected,\n partiallySelected,\n onToggleLogSelection,\n onToggleAllVisible,\n}: AuditLogTableProps) {\n const { t } = useI18n();\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div>\n <div className=\"space-y-3 md:hidden\">\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <article\n key={item.id}\n className={`rounded-lg border border-border-primary p-4 transition-colors ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : 'bg-bg-surface'\n }`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n className=\"mt-1\"\n />\n <div className=\"min-w-0\">\n <p className=\"text-xs text-text-secondary\">{formatDate(item.createdAt)}</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">\n {item.resourceName || item.description || '-'}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </p>\n </div>\n </div>\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </div>\n <div className=\"mt-3 flex items-center justify-between gap-3\">\n <p className=\"min-w-0 truncate text-xs capitalize text-text-secondary\">\n {(item.actorType || 'unknown')\n .toLowerCase()\n .replace(/_/g, ' ')}\n {item.resourceName ? ` · ${item.resourceName}` : ''}\n </p>\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </div>\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-primary px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-secondary\"\n >\n View details\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </article>\n );\n })}\n </div>\n\n <div className=\"hidden overflow-x-auto rounded-lg border border-border-primary md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-primary bg-bg-secondary/50\">\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllVisible}\n ariaLabel=\"Select all visible audit logs\"\n />\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.time', 'Time')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.action', 'Action')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.resource', 'Resource')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.name', 'Name')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.actor', 'Actor')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.status', 'Status')}\n </th>\n <th className=\"px-4 py-3 text-right font-medium text-text-secondary\">\n {tr('audit.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <tr\n key={item.id}\n className={`border-b border-border-primary/50 transition-colors hover:bg-bg-secondary/30 ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : ''\n }`}\n >\n <td className=\"px-4 py-3 align-top\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n />\n </td>\n <td className=\"whitespace-nowrap px-4 py-3 text-xs text-text-secondary\">\n {formatDate(item.createdAt)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </td>\n <td className=\"px-4 py-3 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </td>\n <td\n className=\"max-w-[220px] truncate px-4 py-3\"\n title={item.resourceName || item.description || ''}\n >\n {item.resourceName || item.description || '-'}\n </td>\n <td\n className=\"max-w-[140px] truncate px-4 py-3 text-xs capitalize text-text-secondary\"\n title={item.actorId}\n >\n {(item.actorType || 'unknown')\n .toLowerCase()\n .replace(/_/g, ' ')}\n </td>\n <td className=\"px-4 py-3\">\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </td>\n <td className=\"px-4 py-3 text-right\">\n <div className=\"flex items-center justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-bg-secondary hover:text-text-primary\"\n title={tr('audit.viewAuditLog', 'View details')}\n >\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-3 text-sm text-text-secondary sm:flex-row sm:items-center sm:justify-between\">\n <span>\n {tr('audit.showing', 'Showing')} {page * pageSize + 1}-\n {Math.min((page + 1) * pageSize, total)} {tr('audit.of', 'of')} {total}\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => onPageChange(page - 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.previous', 'Previous')}\n </button>\n <span>\n {tr('audit.page', 'Page')} {page + 1} {tr('audit.of', 'of')} {totalPages}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => onPageChange(page + 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.next', 'Next')}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AuditLogTable.js","names":[],"sources":["../../../src/components/audit/AuditLogTable.tsx"],"sourcesContent":["import { ChevronRight, Terminal, Trash2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StatusBadge } from '@/components/shared';\nimport { SelectionCheckbox } from '@/components/shared/SelectionCheckbox';\nimport type { VibeAuditLogFieldsFragment } from '@/generated/wspace-operations';\n\ninterface AuditLogTableProps {\n items: VibeAuditLogFieldsFragment[];\n total: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n onPageChange: (page: number) => void;\n onSelectLog: (id: string) => void;\n onDeleteLog: (id: string) => void;\n selectedLogId: string | null;\n selectedLogIds: Set<string>;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n onToggleLogSelection: (id: string, checked: boolean) => void;\n onToggleAllVisible: (checked: boolean) => void;\n}\n\nconst statusVariantMap: Record<string, 'success' | 'error' | 'warning' | 'info'> = {\n SUCCESS: 'success',\n FAILURE: 'error',\n DENIED: 'warning',\n ERROR: 'error',\n};\n\nconst actionColors: Record<string, string> = {\n CREATE: 'bg-status-success-bg text-status-success-text',\n UPDATE: 'bg-status-info-bg text-status-info-text',\n DELETE: 'bg-status-error-bg text-status-error-text',\n EXECUTE: 'bg-action-primary-bg/15 text-action-primary-text',\n EXPORT: 'bg-status-warning-bg text-status-warning-text',\n SHARE: 'bg-status-success-bg text-status-success-text',\n REVOKE: 'bg-status-warning-bg text-status-warning-text',\n ARCHIVE: 'bg-bg-muted text-text-secondary',\n RESTORE: 'bg-status-info-bg text-status-info-text',\n};\n\nfunction formatDate(dateString: string): string {\n const date = new Date(dateString);\n return date.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n}\n\nfunction formatResourceType(type: string): string {\n return type\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (character) => character.toUpperCase());\n}\n\nexport function AuditLogTable({\n items,\n total,\n hasMore,\n page,\n pageSize,\n onPageChange,\n onSelectLog,\n onDeleteLog,\n selectedLogId,\n selectedLogIds,\n allVisibleSelected,\n partiallySelected,\n onToggleLogSelection,\n onToggleAllVisible,\n}: AuditLogTableProps) {\n const { t } = useI18n();\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n const tr = (key: string, fallback: string) => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div>\n <div className=\"space-y-3 md:hidden\">\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <article\n key={item.id}\n className={`rounded-lg border border-border-primary p-4 transition-colors ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : 'bg-bg-surface'\n }`}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-start gap-3\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n className=\"mt-1\"\n />\n <div className=\"min-w-0\">\n <p className=\"text-xs text-text-secondary\">{formatDate(item.createdAt)}</p>\n <p className=\"mt-1 truncate font-medium text-text-primary\">\n {item.resourceName || item.description || '-'}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </p>\n </div>\n </div>\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </div>\n <div className=\"mt-3 flex items-center justify-between gap-3\">\n <p className=\"min-w-0 truncate text-xs capitalize text-text-secondary\">\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n {item.resourceName ? ` · ${item.resourceName}` : ''}\n </p>\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </div>\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-primary px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-secondary\"\n >\n View details\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </article>\n );\n })}\n </div>\n\n <div className=\"hidden overflow-x-auto rounded-lg border border-border-primary md:block\">\n <table className=\"w-full min-w-[860px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-primary bg-bg-secondary/50\">\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllVisible}\n ariaLabel=\"Select all visible audit logs\"\n />\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.time', 'Time')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.action', 'Action')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.resource', 'Resource')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.name', 'Name')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.actor', 'Actor')}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr('audit.status', 'Status')}\n </th>\n <th className=\"px-4 py-3 text-right font-medium text-text-secondary\">\n {tr('audit.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {items.map((item) => {\n const isSelected = selectedLogIds.has(item.id);\n return (\n <tr\n key={item.id}\n className={`border-b border-border-primary/50 transition-colors hover:bg-bg-secondary/30 ${\n selectedLogId === item.id ? 'bg-bg-secondary/50' : ''\n }`}\n >\n <td className=\"px-4 py-3 align-top\">\n <SelectionCheckbox\n checked={isSelected}\n onChange={(checked) => onToggleLogSelection(item.id, checked)}\n ariaLabel={`Select audit log ${item.id}`}\n />\n </td>\n <td className=\"whitespace-nowrap px-4 py-3 text-xs text-text-secondary\">\n {formatDate(item.createdAt)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium ${\n actionColors[item.action] || 'bg-bg-secondary text-text-secondary'\n }`}\n >\n {item.command ? <Terminal size={12} /> : null}\n {item.action}\n </span>\n </td>\n <td className=\"px-4 py-3 text-xs text-text-secondary\">\n {formatResourceType(item.resourceType)}\n </td>\n <td\n className=\"max-w-[220px] truncate px-4 py-3\"\n title={item.resourceName || item.description || ''}\n >\n {item.resourceName || item.description || '-'}\n </td>\n <td\n className=\"max-w-[140px] truncate px-4 py-3 text-xs capitalize text-text-secondary\"\n title={item.actorId}\n >\n {(item.actorType || 'unknown').toLowerCase().replace(/_/g, ' ')}\n </td>\n <td className=\"px-4 py-3\">\n <StatusBadge\n status={item.status}\n variant={statusVariantMap[item.status]}\n size=\"sm\"\n />\n </td>\n <td className=\"px-4 py-3 text-right\">\n <div className=\"flex items-center justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => onSelectLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-bg-secondary hover:text-text-primary\"\n title={tr('audit.viewAuditLog', 'View details')}\n >\n <ChevronRight size={14} />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteLog(item.id)}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-status-error-bg hover:text-status-error-text\"\n title={tr('audit.deleteAuditLog', 'Delete audit log')}\n >\n <Trash2 size={14} />\n </button>\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n <div className=\"mt-4 flex flex-col gap-3 text-sm text-text-secondary sm:flex-row sm:items-center sm:justify-between\">\n <span>\n {tr('audit.showing', 'Showing')} {page * pageSize + 1}-\n {Math.min((page + 1) * pageSize, total)} {tr('audit.of', 'of')} {total}\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n disabled={page === 0}\n onClick={() => onPageChange(page - 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.previous', 'Previous')}\n </button>\n <span>\n {tr('audit.page', 'Page')} {page + 1} {tr('audit.of', 'of')} {totalPages}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => onPageChange(page + 1)}\n className=\"rounded border border-border-primary px-3 py-1 transition-colors hover:bg-bg-secondary disabled:opacity-50\"\n >\n {tr('audit.next', 'Next')}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceDefaultsSection.js","names":[],"sources":["../../../src/components/settings/WorkspaceDefaultsSection.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { OptionalFields } from '@burdenoff/fe-libs/ui';\nimport { SectionCard, SelectField, ToggleField, NumberField, TextAreaField } from './SettingsForm';\n\ninterface AgentOption {\n id: string;\n name: string;\n isActive: boolean;\n}\n\ninterface WorkspaceDefaultsData {\n defaultAgent: string | null;\n defaultSessionType: string;\n autoStartSessions: boolean;\n defaultVibeType: string;\n autoGitSync: boolean;\n agentHeartbeatInterval: number;\n agentAutoReconnect: boolean;\n agentMaxSessions: number;\n logLevel: string;\n telemetryEnabled: boolean;\n autoUpdate: boolean;\n defaultEnvironmentVariables: string | null;\n}\n\ninterface WorkspaceDefaultsSectionProps {\n data: WorkspaceDefaultsData;\n onChange: (data: WorkspaceDefaultsData) => void;\n agents: AgentOption[];\n}\n\nexport function WorkspaceDefaultsSection({\n data,\n onChange,\n agents,\n}: WorkspaceDefaultsSectionProps) {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n },\n [t]\n );\n const defaultAgentOptions = useMemo(\n () => [\n { value: '', label: tr('settings.defaultAgentPlaceholder', 'Select default agent...') },\n ...agents.map((agent) => ({\n value: agent.id,\n label: `${agent.name} ${\n agent.isActive\n ? `(${tr('settings.agentStateActive', 'Active')})`\n : `(${tr('settings.agentStateOffline', 'Offline')})`\n }`,\n })),\n ],\n [agents, tr]\n );\n const sessionTypeOptions = useMemo(\n () => [\n { value: 'TMUX', label: tr('settings.sessionTypeTmux', 'Tmux') },\n { value: 'WEZTERM', label: tr('settings.sessionTypeWezTerm', 'WezTerm') },\n { value: 'ZELLIJ', label: tr('settings.sessionTypeZellij', 'Zellij') },\n { value: 'SSH', label: tr('settings.sessionTypeSsh', 'SSH') },\n { value: 'TERMINAL', label: tr('settings.sessionTypeTerminal', 'Terminal') },\n { value: 'SCRIPT', label: tr('settings.sessionTypeScript', 'Script') },\n ],\n [tr]\n );\n const vibeTypeOptions = useMemo(\n () => [\n { value: 'PROJECT', label: tr('settings.vibeTypeProject', 'Project') },\n { value: 'REPOSITORY', label: tr('settings.vibeTypeRepository', 'Repository') },\n { value: 'WORKSPACE', label: tr('settings.vibeTypeWorkspace', 'Workspace') },\n { value: 'MONOREPO', label: tr('settings.vibeTypeMonorepo', 'Monorepo') },\n { value: 'PACKAGE', label: tr('settings.vibeTypePackage', 'Package') },\n { value: 'CUSTOM', label: tr('settings.vibeTypeCustom', 'Custom') },\n ],\n [tr]\n );\n return (\n <div className=\"space-y-6\">\n <SectionCard\n title={tr('settings.generalDefaults', 'General Defaults')}\n description={tr(\n 'settings.generalDefaultsDescription',\n 'Defaults applied when you create a new session or vibe'\n )}\n >\n <SelectField\n label={tr('settings.defaultAgent', 'Default Agent')}\n value={data.defaultAgent || ''}\n onChange={(v) => onChange({ ...data, defaultAgent: v || null })}\n options={defaultAgentOptions}\n description={tr(\n 'settings.defaultAgentDescription',\n 'Agent used by default when creating new sessions'\n )}\n />\n <SelectField\n label={tr('settings.defaultSessionType', 'Default Session Type')}\n value={data.defaultSessionType}\n onChange={(v) => onChange({ ...data, defaultSessionType: v })}\n options={sessionTypeOptions}\n />\n <ToggleField\n label={tr('settings.autoStartSessions', 'Auto-start Sessions')}\n description={tr(\n 'settings.autoStartSessionsDescription',\n 'Automatically start sessions when a vibe is activated'\n )}\n value={data.autoStartSessions}\n onChange={(v) => onChange({ ...data, autoStartSessions: v })}\n />\n <SelectField\n label={tr('settings.defaultVibeType', 'Default Vibe Type')}\n value={data.defaultVibeType}\n onChange={(v) => onChange({ ...data, defaultVibeType: v })}\n options={vibeTypeOptions}\n />\n <ToggleField\n label={tr('settings.autoGitSync', 'Auto Git Sync')}\n description={tr(\n 'settings.autoGitSyncDescription',\n 'Automatically sync git status when a vibe is activated'\n )}\n value={data.autoGitSync}\n onChange={(v) => onChange({ ...data, autoGitSync: v })}\n />\n </SectionCard>\n\n <OptionalFields\n title={tr('settings.agentTuning', 'Agent tuning')}\n description={tr(\n 'settings.agentTuningDescription',\n 'Heartbeat, capacity, reconnect — most users keep the defaults'\n )}\n >\n <NumberField\n label={tr('settings.heartbeatInterval', 'Heartbeat Interval (seconds)')}\n value={data.agentHeartbeatInterval}\n onChange={(v) => onChange({ ...data, agentHeartbeatInterval: v })}\n min={10}\n max={300}\n description={tr(\n 'settings.heartbeatIntervalDescription',\n 'How often agents send heartbeat signals (10-300 seconds)'\n )}\n />\n <NumberField\n label={tr('settings.maxSessionsPerAgent', 'Max Sessions Per Agent')}\n value={data.agentMaxSessions}\n onChange={(v) => onChange({ ...data, agentMaxSessions: v })}\n min={1}\n max={100}\n />\n <ToggleField\n label={tr('settings.autoReconnect', 'Auto-reconnect')}\n description={tr(\n 'settings.autoReconnectDescription',\n 'Automatically reconnect agents after network interruptions'\n )}\n value={data.agentAutoReconnect}\n onChange={(v) => onChange({ ...data, agentAutoReconnect: v })}\n />\n <TextAreaField\n label={tr('settings.defaultEnvVars', 'Default Environment Variables')}\n value={data.defaultEnvironmentVariables || ''}\n onChange={(v) => onChange({ ...data, defaultEnvironmentVariables: v || null })}\n placeholder={tr(\n 'settings.defaultEnvVarsPlaceholder',\n 'KEY=value\\nANOTHER_KEY=value'\n )}\n description={tr(\n 'settings.defaultEnvVarsDescription',\n 'Environment variables applied to all new vibes (one per line, KEY=value format)'\n )}\n />\n </OptionalFields>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkspaceDefaultsSection.js","names":[],"sources":["../../../src/components/settings/WorkspaceDefaultsSection.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { OptionalFields } from '@burdenoff/fe-libs/ui';\nimport { SectionCard, SelectField, ToggleField, NumberField, TextAreaField } from './SettingsForm';\n\ninterface AgentOption {\n id: string;\n name: string;\n isActive: boolean;\n}\n\ninterface WorkspaceDefaultsData {\n defaultAgent: string | null;\n defaultSessionType: string;\n autoStartSessions: boolean;\n defaultVibeType: string;\n autoGitSync: boolean;\n agentHeartbeatInterval: number;\n agentAutoReconnect: boolean;\n agentMaxSessions: number;\n logLevel: string;\n telemetryEnabled: boolean;\n autoUpdate: boolean;\n defaultEnvironmentVariables: string | null;\n}\n\ninterface WorkspaceDefaultsSectionProps {\n data: WorkspaceDefaultsData;\n onChange: (data: WorkspaceDefaultsData) => void;\n agents: AgentOption[];\n}\n\nexport function WorkspaceDefaultsSection({\n data,\n onChange,\n agents,\n}: WorkspaceDefaultsSectionProps) {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n },\n [t]\n );\n const defaultAgentOptions = useMemo(\n () => [\n { value: '', label: tr('settings.defaultAgentPlaceholder', 'Select default agent...') },\n ...agents.map((agent) => ({\n value: agent.id,\n label: `${agent.name} ${\n agent.isActive\n ? `(${tr('settings.agentStateActive', 'Active')})`\n : `(${tr('settings.agentStateOffline', 'Offline')})`\n }`,\n })),\n ],\n [agents, tr]\n );\n const sessionTypeOptions = useMemo(\n () => [\n { value: 'TMUX', label: tr('settings.sessionTypeTmux', 'Tmux') },\n { value: 'WEZTERM', label: tr('settings.sessionTypeWezTerm', 'WezTerm') },\n { value: 'ZELLIJ', label: tr('settings.sessionTypeZellij', 'Zellij') },\n { value: 'SSH', label: tr('settings.sessionTypeSsh', 'SSH') },\n { value: 'TERMINAL', label: tr('settings.sessionTypeTerminal', 'Terminal') },\n { value: 'SCRIPT', label: tr('settings.sessionTypeScript', 'Script') },\n ],\n [tr]\n );\n const vibeTypeOptions = useMemo(\n () => [\n { value: 'PROJECT', label: tr('settings.vibeTypeProject', 'Project') },\n { value: 'REPOSITORY', label: tr('settings.vibeTypeRepository', 'Repository') },\n { value: 'WORKSPACE', label: tr('settings.vibeTypeWorkspace', 'Workspace') },\n { value: 'MONOREPO', label: tr('settings.vibeTypeMonorepo', 'Monorepo') },\n { value: 'PACKAGE', label: tr('settings.vibeTypePackage', 'Package') },\n { value: 'CUSTOM', label: tr('settings.vibeTypeCustom', 'Custom') },\n ],\n [tr]\n );\n return (\n <div className=\"space-y-6\">\n <SectionCard\n title={tr('settings.generalDefaults', 'General Defaults')}\n description={tr(\n 'settings.generalDefaultsDescription',\n 'Defaults applied when you create a new session or vibe'\n )}\n >\n <SelectField\n label={tr('settings.defaultAgent', 'Default Agent')}\n value={data.defaultAgent || ''}\n onChange={(v) => onChange({ ...data, defaultAgent: v || null })}\n options={defaultAgentOptions}\n description={tr(\n 'settings.defaultAgentDescription',\n 'Agent used by default when creating new sessions'\n )}\n />\n <SelectField\n label={tr('settings.defaultSessionType', 'Default Session Type')}\n value={data.defaultSessionType}\n onChange={(v) => onChange({ ...data, defaultSessionType: v })}\n options={sessionTypeOptions}\n />\n <ToggleField\n label={tr('settings.autoStartSessions', 'Auto-start Sessions')}\n description={tr(\n 'settings.autoStartSessionsDescription',\n 'Automatically start sessions when a vibe is activated'\n )}\n value={data.autoStartSessions}\n onChange={(v) => onChange({ ...data, autoStartSessions: v })}\n />\n <SelectField\n label={tr('settings.defaultVibeType', 'Default Vibe Type')}\n value={data.defaultVibeType}\n onChange={(v) => onChange({ ...data, defaultVibeType: v })}\n options={vibeTypeOptions}\n />\n <ToggleField\n label={tr('settings.autoGitSync', 'Auto Git Sync')}\n description={tr(\n 'settings.autoGitSyncDescription',\n 'Automatically sync git status when a vibe is activated'\n )}\n value={data.autoGitSync}\n onChange={(v) => onChange({ ...data, autoGitSync: v })}\n />\n </SectionCard>\n\n <OptionalFields\n title={tr('settings.agentTuning', 'Agent tuning')}\n description={tr(\n 'settings.agentTuningDescription',\n 'Heartbeat, capacity, reconnect — most users keep the defaults'\n )}\n >\n <NumberField\n label={tr('settings.heartbeatInterval', 'Heartbeat Interval (seconds)')}\n value={data.agentHeartbeatInterval}\n onChange={(v) => onChange({ ...data, agentHeartbeatInterval: v })}\n min={10}\n max={300}\n description={tr(\n 'settings.heartbeatIntervalDescription',\n 'How often agents send heartbeat signals (10-300 seconds)'\n )}\n />\n <NumberField\n label={tr('settings.maxSessionsPerAgent', 'Max Sessions Per Agent')}\n value={data.agentMaxSessions}\n onChange={(v) => onChange({ ...data, agentMaxSessions: v })}\n min={1}\n max={100}\n />\n <ToggleField\n label={tr('settings.autoReconnect', 'Auto-reconnect')}\n description={tr(\n 'settings.autoReconnectDescription',\n 'Automatically reconnect agents after network interruptions'\n )}\n value={data.agentAutoReconnect}\n onChange={(v) => onChange({ ...data, agentAutoReconnect: v })}\n />\n <TextAreaField\n label={tr('settings.defaultEnvVars', 'Default Environment Variables')}\n value={data.defaultEnvironmentVariables || ''}\n onChange={(v) => onChange({ ...data, defaultEnvironmentVariables: v || null })}\n placeholder={tr('settings.defaultEnvVarsPlaceholder', 'KEY=value\\nANOTHER_KEY=value')}\n description={tr(\n 'settings.defaultEnvVarsDescription',\n 'Environment variables applied to all new vibes (one per line, KEY=value format)'\n )}\n />\n </OptionalFields>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/components/shared/ConfirmDialog.tsx"],"sourcesContent":["import { AlertTriangle } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: 'danger' | 'warning' | 'default';\n isLoading?: boolean;\n}\n\nconst VARIANT_STYLES: Record<\n NonNullable<ConfirmDialogProps['variant']>,\n { iconWrap: string; confirmBtn: string }\n> = {\n danger: {\n iconWrap: 'bg-status-error-bg-subtle text-status-error-text',\n confirmBtn: 'bg-status-error-bg text-text-inverse hover:bg-status-error-text-hover',\n },\n warning: {\n iconWrap: 'bg-status-warning-bg-subtle text-status-warning-text',\n confirmBtn: 'bg-status-warning-bg text-text-primary hover:bg-status-warning-text-hover',\n },\n default: {\n iconWrap: 'bg-action-primary-bg text-action-primary-text',\n confirmBtn: 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover',\n },\n};\n\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n confirmLabel,\n cancelLabel,\n variant = 'default',\n isLoading = false,\n}: ConfirmDialogProps) {\n const tr = useTr();\n const resolvedConfirmLabel =\n confirmLabel ?? tr('vibecontrols.shared.confirmDialog.confirm', 'Confirm');\n const resolvedCancelLabel =\n cancelLabel ?? tr('vibecontrols.shared.confirmDialog.cancel', 'Cancel');\n const styles = VARIANT_STYLES[variant];\n\n return (\n <ResponsiveDialog\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <div className=\"flex items-start gap-3\">\n <div\n className={`flex-shrink-0 size-10 rounded-full flex items-center justify-center ${styles.iconWrap}`}\n aria-hidden=\"true\"\n >\n <AlertTriangle className=\"size-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription className=\"mt-1\">\n {message}\n </ResponsiveDialogDescription>\n </div>\n </div>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isLoading}\n className=\"min-h-11 px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {resolvedCancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n disabled={isLoading}\n className={`min-h-11 px-4 py-2 text-sm font-medium rounded-md transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 ${styles.confirmBtn}`}\n >\n {isLoading\n ? tr('vibecontrols.shared.confirmDialog.processing', 'Processing...')\n : resolvedConfirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;AAuBA,IAAM,IAGF;CACF,QAAQ;EACN,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACF;AAED,SAAgB,EAAc,EAC5B,WACA,YACA,cACA,UACA,YACA,iBACA,gBACA,aAAU,WACV,eAAY,MACS;CACrB,IAAM,IAAK,GAAO,EACZ,IACJ,KAAgB,EAAG,6CAA6C,UAAU,EACtE,IACJ,KAAe,EAAG,4CAA4C,SAAS,EACnE,IAAS,EAAe;AAE9B,QACE,kBAAC,GAAD;EACE,MAAM;EACN,eAAe,MAAS;AACtB,GAAK,KAAM,GAAS;;YAGtB,kBAAC,GAAD;GAAyB,WAAU;aAAnC,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KACE,WAAW,uEAAuE,EAAO;KACzF,eAAY;eAEZ,kBAAC,GAAD,EAAe,WAAU,UAAW,CAAA;KAChC,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAA,UAAwB,GAA8B,CAAA,EACtD,kBAAC,GAAD;MAA6B,WAAU;gBACpC;MAC2B,CAAA,CAC1B;OACF;OACiB,CAAA,EACzB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU;IACV,WAAU;cAET;IACM,CAAA,EACT,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU;IACV,WAAW,2JAA2J,EAAO;cAE5K,IACG,EAAG,gDAAgD,gBAAgB,GACnE;IACG,CAAA,CACc,EAAA,CAAA,CACD;;EACT,CAAA"}
1
+ {"version":3,"file":"ConfirmDialog.js","names":[],"sources":["../../../src/components/shared/ConfirmDialog.tsx"],"sourcesContent":["import { AlertTriangle } from 'lucide-react';\nimport {\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ConfirmDialogProps {\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: 'danger' | 'warning' | 'default';\n isLoading?: boolean;\n}\n\nconst VARIANT_STYLES: Record<\n NonNullable<ConfirmDialogProps['variant']>,\n { iconWrap: string; confirmBtn: string }\n> = {\n danger: {\n iconWrap: 'bg-status-error-bg-subtle text-status-error-text',\n confirmBtn: 'bg-status-error-bg text-text-inverse hover:bg-status-error-text-hover',\n },\n warning: {\n iconWrap: 'bg-status-warning-bg-subtle text-status-warning-text',\n confirmBtn: 'bg-status-warning-bg text-text-primary hover:bg-status-warning-text-hover',\n },\n default: {\n iconWrap: 'bg-action-primary-bg text-action-primary-text',\n confirmBtn: 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover',\n },\n};\n\nexport function ConfirmDialog({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n confirmLabel,\n cancelLabel,\n variant = 'default',\n isLoading = false,\n}: ConfirmDialogProps) {\n const tr = useTr();\n const resolvedConfirmLabel =\n confirmLabel ?? tr('vibecontrols.shared.confirmDialog.confirm', 'Confirm');\n const resolvedCancelLabel =\n cancelLabel ?? tr('vibecontrols.shared.confirmDialog.cancel', 'Cancel');\n const styles = VARIANT_STYLES[variant];\n\n return (\n <ResponsiveDialog\n open={isOpen}\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <div className=\"flex items-start gap-3\">\n <div\n className={`flex-shrink-0 size-10 rounded-full flex items-center justify-center ${styles.iconWrap}`}\n aria-hidden=\"true\"\n >\n <AlertTriangle className=\"size-5\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <ResponsiveDialogTitle>{title}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription className=\"mt-1\">{message}</ResponsiveDialogDescription>\n </div>\n </div>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isLoading}\n className=\"min-h-11 px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40\"\n >\n {resolvedCancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n disabled={isLoading}\n className={`min-h-11 px-4 py-2 text-sm font-medium rounded-md transition-colors disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 ${styles.confirmBtn}`}\n >\n {isLoading\n ? tr('vibecontrols.shared.confirmDialog.processing', 'Processing...')\n : resolvedConfirmLabel}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;AAuBA,IAAM,IAGF;CACF,QAAQ;EACN,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACD,SAAS;EACP,UAAU;EACV,YAAY;EACb;CACF;AAED,SAAgB,EAAc,EAC5B,WACA,YACA,cACA,UACA,YACA,iBACA,gBACA,aAAU,WACV,eAAY,MACS;CACrB,IAAM,IAAK,GAAO,EACZ,IACJ,KAAgB,EAAG,6CAA6C,UAAU,EACtE,IACJ,KAAe,EAAG,4CAA4C,SAAS,EACnE,IAAS,EAAe;AAE9B,QACE,kBAAC,GAAD;EACE,MAAM;EACN,eAAe,MAAS;AACtB,GAAK,KAAM,GAAS;;YAGtB,kBAAC,GAAD;GAAyB,WAAU;aAAnC,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KACE,WAAW,uEAAuE,EAAO;KACzF,eAAY;eAEZ,kBAAC,GAAD,EAAe,WAAU,UAAW,CAAA;KAChC,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAA,UAAwB,GAA8B,CAAA,EACtD,kBAAC,GAAD;MAA6B,WAAU;gBAAQ;MAAsC,CAAA,CACjF;OACF;OACiB,CAAA,EACzB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU;IACV,WAAU;cAET;IACM,CAAA,EACT,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU;IACV,WAAW,2JAA2J,EAAO;cAE5K,IACG,EAAG,gDAAgD,gBAAgB,GACnE;IACG,CAAA,CACc,EAAA,CAAA,CACD;;EACT,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/components/shared/EmptyState.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { EmptyState as CanonicalEmptyState } from '@burdenoff/fe-libs/ui';\n\ninterface EmptyStateProps {\n icon?: ReactNode;\n title: string;\n description?: string;\n action?: ReactNode;\n}\n\n/**\n * Local wrapper around `EmptyState` from `@burdenoff/fe-libs/ui`.\n *\n * Keeps the existing microfe-vibecontrols call sites stable while routing all\n * empty-state rendering through the canonical primitive.\n */\nexport function EmptyState({ icon, title, description, action }: EmptyStateProps) {\n return (\n <CanonicalEmptyState\n icon={icon}\n title={title}\n description={description}\n action={action}\n />\n );\n}\n"],"mappings":";;;AAgBA,SAAgB,EAAW,EAAE,SAAM,UAAO,gBAAa,aAA2B;AAChF,QACE,kBAAC,GAAD;EACQ;EACC;EACM;EACL;EACR,CAAA"}
1
+ {"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/components/shared/EmptyState.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { EmptyState as CanonicalEmptyState } from '@burdenoff/fe-libs/ui';\n\ninterface EmptyStateProps {\n icon?: ReactNode;\n title: string;\n description?: string;\n action?: ReactNode;\n}\n\n/**\n * Local wrapper around `EmptyState` from `@burdenoff/fe-libs/ui`.\n *\n * Keeps the existing microfe-vibecontrols call sites stable while routing all\n * empty-state rendering through the canonical primitive.\n */\nexport function EmptyState({ icon, title, description, action }: EmptyStateProps) {\n return (\n <CanonicalEmptyState icon={icon} title={title} description={description} action={action} />\n );\n}\n"],"mappings":";;;AAgBA,SAAgB,EAAW,EAAE,SAAM,UAAO,gBAAa,aAA2B;AAChF,QACE,kBAAC,GAAD;EAA2B;EAAa;EAAoB;EAAqB;EAAU,CAAA"}
@@ -2,11 +2,11 @@ import { useTr as e } from "../../shared/hooks/useTr.js";
2
2
  import { StatusBadge as t } from "../shared/StatusBadge.js";
3
3
  import "../shared/index.js";
4
4
  import { useState as n } from "react";
5
- import { CheckCircle as r, Download as i, FlaskConical as a, MoreVertical as o, Pencil as s, Server as c, Terminal as l, Trash2 as u, X as d } from "lucide-react";
6
- import { AnimatePresence as f, motion as p } from "framer-motion";
7
- import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
5
+ import { CheckCircle as r, Download as i, FlaskConical as a, Loader2 as o, MoreVertical as s, Pencil as c, Server as l, Terminal as u, Trash2 as d, X as f } from "lucide-react";
6
+ import { AnimatePresence as p, motion as m } from "framer-motion";
7
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
8
8
  //#region src/components/targets/TargetCard.tsx
9
- var _ = {
9
+ var v = {
10
10
  connected: {
11
11
  variant: "success",
12
12
  label: "Connected"
@@ -19,15 +19,15 @@ var _ = {
19
19
  variant: "neutral",
20
20
  label: "Unknown"
21
21
  }
22
- }, v = {
22
+ }, y = {
23
23
  DIRECT: "bg-accent-blue-subtle text-accent-blue",
24
24
  SSH: "bg-status-success-bg-subtle text-status-success-text",
25
25
  RDP: "bg-status-warning-bg-subtle text-status-warning-text",
26
26
  VNC: "bg-accent-purple-subtle text-accent-purple"
27
- }, y = ({ target: y, onTest: b, onTerminal: x, onOpenDetail: S, onInstallAgent: C, onUninstallAgent: w, onDelete: T, onEdit: E, selected: D = !1, onToggleSelect: O, highlighted: k = !1 }) => {
28
- let A = e(), [j, M] = n(!1), N = y.agents.length > 0;
29
- return /* @__PURE__ */ g(p.div, {
30
- id: `target-row-${y.id}`,
27
+ }, b = ({ target: b, onTest: x, onTerminal: S, onOpenDetail: C, onInstallAgent: w, onUninstallAgent: T, onDelete: E, onEdit: D, selected: O = !1, onToggleSelect: k, highlighted: A = !1, isStartingTerminal: j = !1 }) => {
28
+ let M = e(), [N, P] = n(!1), F = b.agents.length > 0;
29
+ return /* @__PURE__ */ _(m.div, {
30
+ id: `target-row-${b.id}`,
31
31
  whileHover: {
32
32
  y: -1,
33
33
  transition: {
@@ -41,78 +41,78 @@ var _ = {
41
41
  }
42
42
  },
43
43
  whileTap: { scale: .99 },
44
- className: `bg-bg-surface border rounded-lg p-4 h-full hover:border-border-strong hover:shadow-md transition-all cursor-pointer ${D ? "border-action-primary-bg ring-1 ring-action-primary-bg/30" : k ? "border-action-primary-bg bg-action-primary-bg/5 shadow-sm" : "border-border-default"}`,
45
- onClick: () => (S ?? x)?.(y.id),
44
+ className: `bg-bg-surface border rounded-lg p-4 h-full hover:border-border-strong hover:shadow-md transition-all cursor-pointer ${O ? "border-action-primary-bg ring-1 ring-action-primary-bg/30" : A ? "border-action-primary-bg bg-action-primary-bg/5 shadow-sm" : "border-border-default"}`,
45
+ onClick: () => (C ?? S)?.(b.id),
46
46
  children: [
47
- /* @__PURE__ */ g("div", {
47
+ /* @__PURE__ */ _("div", {
48
48
  className: "flex items-start justify-between gap-2",
49
- children: [/* @__PURE__ */ g("div", {
49
+ children: [/* @__PURE__ */ _("div", {
50
50
  className: "flex items-start gap-2 sm:gap-3 min-w-0 flex-1",
51
51
  children: [
52
- O && /* @__PURE__ */ h("button", {
52
+ k && /* @__PURE__ */ g("button", {
53
53
  type: "button",
54
54
  onClick: (e) => {
55
- e.stopPropagation(), O();
55
+ e.stopPropagation(), k();
56
56
  },
57
- className: `flex-shrink-0 size-5 min-w-[1.25rem] min-h-[1.25rem] rounded border transition-colors mt-0.5 ${D ? "bg-action-primary-bg border-action-primary-bg text-action-primary-text" : "border-border-default hover:border-border-strong bg-bg-surface"} flex items-center justify-center`,
58
- children: D && /* @__PURE__ */ h("svg", {
57
+ className: `flex-shrink-0 size-5 min-w-[1.25rem] min-h-[1.25rem] rounded border transition-colors mt-0.5 ${O ? "bg-action-primary-bg border-action-primary-bg text-action-primary-text" : "border-border-default hover:border-border-strong bg-bg-surface"} flex items-center justify-center`,
58
+ children: O && /* @__PURE__ */ g("svg", {
59
59
  className: "size-3",
60
60
  fill: "none",
61
61
  viewBox: "0 0 24 24",
62
62
  stroke: "currentColor",
63
63
  strokeWidth: 3,
64
- children: /* @__PURE__ */ h("path", {
64
+ children: /* @__PURE__ */ g("path", {
65
65
  strokeLinecap: "round",
66
66
  strokeLinejoin: "round",
67
67
  d: "M5 13l4 4L19 7"
68
68
  })
69
69
  })
70
70
  }),
71
- /* @__PURE__ */ h("div", {
71
+ /* @__PURE__ */ g("div", {
72
72
  className: "flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-bg-sunken flex items-center justify-center",
73
- children: /* @__PURE__ */ h(c, { className: "size-4 sm:w-5 sm:h-5 text-text-secondary" })
73
+ children: /* @__PURE__ */ g(l, { className: "size-4 sm:w-5 sm:h-5 text-text-secondary" })
74
74
  }),
75
- /* @__PURE__ */ g("div", {
75
+ /* @__PURE__ */ _("div", {
76
76
  className: "min-w-0 flex-1",
77
- children: [/* @__PURE__ */ g("div", {
77
+ children: [/* @__PURE__ */ _("div", {
78
78
  className: "flex items-center gap-1.5 sm:gap-2 flex-wrap",
79
- children: [/* @__PURE__ */ h("h3", {
79
+ children: [/* @__PURE__ */ g("h3", {
80
80
  className: "font-semibold text-text-primary truncate max-w-[120px] sm:max-w-none text-sm sm:text-base",
81
- children: y.name
82
- }), /* @__PURE__ */ h("span", {
83
- className: `inline-flex items-center px-1.5 py-0.5 text-xs font-semibold rounded ${v[y.type]}`,
84
- children: y.type
81
+ children: b.name
82
+ }), /* @__PURE__ */ g("span", {
83
+ className: `inline-flex items-center px-1.5 py-0.5 text-xs font-semibold rounded ${y[b.type]}`,
84
+ children: b.type
85
85
  })]
86
- }), /* @__PURE__ */ h("p", {
86
+ }), /* @__PURE__ */ g("p", {
87
87
  className: "text-xs sm:text-sm text-text-secondary truncate",
88
- children: y.host ? `${y.username ? `${y.username}@` : ""}${y.host}${y.port ? `:${y.port}` : ""}` : y.label || `ID: ${y.id.slice(0, 8)}`
88
+ children: b.host ? `${b.username ? `${b.username}@` : ""}${b.host}${b.port ? `:${b.port}` : ""}` : b.label || `ID: ${b.id.slice(0, 8)}`
89
89
  })]
90
90
  })
91
91
  ]
92
- }), /* @__PURE__ */ g("div", {
92
+ }), /* @__PURE__ */ _("div", {
93
93
  className: "flex items-center gap-1 sm:gap-2 flex-shrink-0",
94
- children: [/* @__PURE__ */ h(t, {
95
- status: _[y.status].label,
96
- variant: _[y.status].variant
97
- }), /* @__PURE__ */ g("div", {
94
+ children: [/* @__PURE__ */ g(t, {
95
+ status: v[b.status].label,
96
+ variant: v[b.status].variant
97
+ }), /* @__PURE__ */ _("div", {
98
98
  className: "relative",
99
- children: [/* @__PURE__ */ h("button", {
99
+ children: [/* @__PURE__ */ g("button", {
100
100
  type: "button",
101
101
  onClick: (e) => {
102
- e.stopPropagation(), M(!j);
102
+ e.stopPropagation(), P(!N);
103
103
  },
104
104
  className: "p-1 sm:p-1.5 rounded hover:bg-bg-sunken transition-colors flex items-center justify-center",
105
105
  "aria-label": "Target actions menu",
106
- children: /* @__PURE__ */ h(o, { className: "size-4 text-text-primary opacity-70 hover:opacity-100" })
107
- }), /* @__PURE__ */ h(f, { children: j && /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("div", {
106
+ children: /* @__PURE__ */ g(s, { className: "size-4 text-text-primary opacity-70 hover:opacity-100" })
107
+ }), /* @__PURE__ */ g(p, { children: N && /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("div", {
108
108
  role: "button",
109
109
  tabIndex: 0,
110
110
  onKeyDown: (e) => {
111
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), M(!1));
111
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), P(!1));
112
112
  },
113
113
  className: "fixed inset-0 z-10",
114
- onClick: () => M(!1)
115
- }), /* @__PURE__ */ g(p.div, {
114
+ onClick: () => P(!1)
115
+ }), /* @__PURE__ */ _(m.div, {
116
116
  initial: {
117
117
  opacity: 0,
118
118
  scale: .95,
@@ -131,97 +131,105 @@ var _ = {
131
131
  transition: { duration: .15 },
132
132
  className: "absolute right-0 mt-1 w-44 bg-bg-surface border border-border-default rounded-lg shadow-lg z-20",
133
133
  children: [
134
- b && /* @__PURE__ */ g("button", {
134
+ x && /* @__PURE__ */ _("button", {
135
135
  type: "button",
136
136
  onClick: (e) => {
137
- e.stopPropagation(), b(y.id), M(!1);
137
+ e.stopPropagation(), x(b.id), P(!1);
138
138
  },
139
139
  className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-t-lg transition-colors",
140
- children: [/* @__PURE__ */ h(a, { className: "size-4" }), A("vibecontrols.targets.testConnection", "Test Connection")]
140
+ children: [/* @__PURE__ */ g(a, { className: "size-4" }), M("vibecontrols.targets.testConnection", "Test Connection")]
141
141
  }),
142
- x && /* @__PURE__ */ g("button", {
142
+ S && /* @__PURE__ */ g("button", {
143
143
  type: "button",
144
+ disabled: j,
144
145
  onClick: (e) => {
145
- e.stopPropagation(), x(y.id), M(!1);
146
+ e.stopPropagation(), !j && (S(b.id), P(!1));
146
147
  },
147
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
148
- children: [/* @__PURE__ */ h(l, { className: "size-4" }), A("vibecontrols.targets.openTerminal", "Open Terminal")]
148
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-60 disabled:cursor-not-allowed",
149
+ children: j ? /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(o, { className: "size-4 animate-spin" }), M("vibecontrols.targets.startingTerminal", "Starting…")] }) : /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(u, { className: "size-4" }), M("vibecontrols.targets.openTerminal", "Open Terminal")] })
149
150
  }),
150
- E && /* @__PURE__ */ g("button", {
151
+ D && /* @__PURE__ */ _("button", {
151
152
  type: "button",
152
153
  onClick: (e) => {
153
- e.stopPropagation(), E(y), M(!1);
154
+ e.stopPropagation(), D(b), P(!1);
154
155
  },
155
156
  className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
156
- children: [/* @__PURE__ */ h(s, { className: "size-4" }), A("vibecontrols.targets.editTarget", "Edit Target")]
157
+ children: [/* @__PURE__ */ g(c, { className: "size-4" }), M("vibecontrols.targets.editTarget", "Edit Target")]
157
158
  }),
158
- y.type !== "DIRECT" && !N && C && /* @__PURE__ */ g("button", {
159
+ b.type !== "DIRECT" && !F && w && /* @__PURE__ */ _("button", {
159
160
  type: "button",
160
161
  onClick: (e) => {
161
- e.stopPropagation(), C(y), M(!1);
162
+ e.stopPropagation(), w(b), P(!1);
162
163
  },
163
164
  className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-action-primary-bg hover:bg-bg-sunken transition-colors",
164
- children: [/* @__PURE__ */ h(i, { className: "size-4" }), A("vibecontrols.targets.installAgent", "Install Agent")]
165
+ children: [/* @__PURE__ */ g(i, { className: "size-4" }), M("vibecontrols.targets.installAgent", "Install Agent")]
165
166
  }),
166
- y.type !== "DIRECT" && N && w && /* @__PURE__ */ g("button", {
167
+ b.type !== "DIRECT" && F && T && /* @__PURE__ */ _("button", {
167
168
  type: "button",
168
169
  onClick: (e) => {
169
- e.stopPropagation(), w(y), M(!1);
170
+ e.stopPropagation(), T(b), P(!1);
170
171
  },
171
172
  className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-bg-sunken transition-colors",
172
- children: [/* @__PURE__ */ h(u, { className: "size-4" }), A("vibecontrols.targets.uninstallAgent", "Uninstall Agent")]
173
+ children: [/* @__PURE__ */ g(d, { className: "size-4" }), M("vibecontrols.targets.uninstallAgent", "Uninstall Agent")]
173
174
  }),
174
- T && /* @__PURE__ */ g("button", {
175
+ E && /* @__PURE__ */ _("button", {
175
176
  type: "button",
176
177
  onClick: (e) => {
177
- e.stopPropagation(), T(y.id), M(!1);
178
+ e.stopPropagation(), E(b.id), P(!1);
178
179
  },
179
180
  className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-bg-sunken rounded-b-lg transition-colors",
180
- children: [/* @__PURE__ */ h(d, { className: "size-4" }), A("vibecontrols.targets.deleteTarget", "Delete Target")]
181
+ children: [/* @__PURE__ */ g(f, { className: "size-4" }), M("vibecontrols.targets.deleteTarget", "Delete Target")]
181
182
  })
182
183
  ]
183
184
  })] }) })]
184
185
  })]
185
186
  })]
186
187
  }),
187
- /* @__PURE__ */ g("div", {
188
+ j && /* @__PURE__ */ _("div", {
189
+ className: "mt-3 inline-flex items-center gap-2 rounded-md border border-action-primary-border bg-action-primary-bg/10 px-2.5 py-1 text-xs text-action-primary-text",
190
+ children: [/* @__PURE__ */ g(o, {
191
+ size: 12,
192
+ className: "animate-spin"
193
+ }), M("vibecontrols.targets.startingTerminalHint", "Starting terminal session…")]
194
+ }),
195
+ /* @__PURE__ */ _("div", {
188
196
  className: "mt-3 flex items-center gap-3 text-sm",
189
197
  children: [
190
- N ? /* @__PURE__ */ g("span", {
198
+ F ? /* @__PURE__ */ _("span", {
191
199
  className: "inline-flex items-center gap-1 rounded-full border border-status-success-border px-2 py-0.5 text-xs bg-status-success-bg-subtle text-status-success-text",
192
200
  children: [
193
- /* @__PURE__ */ h(r, { size: 10 }),
201
+ /* @__PURE__ */ g(r, { size: 10 }),
194
202
  "Agent: ",
195
- y.agents[0].name
203
+ b.agents[0].name
196
204
  ]
197
- }) : /* @__PURE__ */ h("span", {
205
+ }) : /* @__PURE__ */ g("span", {
198
206
  className: "inline-flex items-center gap-1 rounded-full border border-border-default px-2 py-0.5 text-xs bg-bg-sunken text-text-tertiary",
199
207
  children: "No agent"
200
208
  }),
201
- y.label && !y.host && /* @__PURE__ */ h("span", {
209
+ b.label && !b.host && /* @__PURE__ */ g("span", {
202
210
  className: "text-xs text-text-tertiary",
203
- children: y.label
211
+ children: b.label
204
212
  }),
205
- y.host && y.label && /* @__PURE__ */ h("span", {
213
+ b.host && b.label && /* @__PURE__ */ g("span", {
206
214
  className: "text-xs text-text-tertiary",
207
- children: y.label
215
+ children: b.label
208
216
  })
209
217
  ]
210
218
  }),
211
- y.tags.length > 0 && /* @__PURE__ */ g("div", {
219
+ b.tags.length > 0 && /* @__PURE__ */ _("div", {
212
220
  className: "mt-2 flex flex-wrap gap-1",
213
- children: [y.tags.slice(0, 4).map((e) => /* @__PURE__ */ h("span", {
221
+ children: [b.tags.slice(0, 4).map((e) => /* @__PURE__ */ g("span", {
214
222
  className: "px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded",
215
223
  children: e
216
- }, e)), y.tags.length > 4 && /* @__PURE__ */ g("span", {
224
+ }, e)), b.tags.length > 4 && /* @__PURE__ */ _("span", {
217
225
  className: "px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded",
218
- children: ["+", y.tags.length - 4]
226
+ children: ["+", b.tags.length - 4]
219
227
  })]
220
228
  })
221
229
  ]
222
230
  });
223
231
  };
224
232
  //#endregion
225
- export { y as TargetCard };
233
+ export { b as TargetCard };
226
234
 
227
235
  //# sourceMappingURL=TargetCard.js.map