@burdenoff/microfe-vibecontrols 2026.623.1 → 2026.623.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/dist/components/actions/ActionCard.js +2 -2
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/actions/ExecutionHistory.js +1 -1
  4. package/dist/components/actions/ExecutionHistory.js.map +1 -1
  5. package/dist/components/agent-manager/AgentManagerAdminBar.js +1 -1
  6. package/dist/components/agent-manager/AgentManagerAdminBar.js.map +1 -1
  7. package/dist/components/agent-manager/AgentManagerChatPane.js +2 -2
  8. package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
  9. package/dist/components/agent-manager/AgentManagerInputArea.js +4 -4
  10. package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
  11. package/dist/components/agent-manager/AgentManagerLayout.js +1 -1
  12. package/dist/components/agent-manager/AgentManagerLayout.js.map +1 -1
  13. package/dist/components/agent-manager/AgentManagerMessageItem.js +1 -1
  14. package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
  15. package/dist/components/agent-manager/AgentManagerSidebar.js +5 -5
  16. package/dist/components/agent-manager/AgentManagerSidebar.js.map +1 -1
  17. package/dist/components/agent-manager/AgentManagerTab.js +1 -1
  18. package/dist/components/agent-manager/AgentManagerTab.js.map +1 -1
  19. package/dist/components/agent-manager/AgentManagerTabBar.js +1 -1
  20. package/dist/components/agent-manager/AgentManagerTabBar.js.map +1 -1
  21. package/dist/components/agent-manager/BridleConfigPanel.js +23 -23
  22. package/dist/components/agent-manager/BridleConfigPanel.js.map +1 -1
  23. package/dist/components/agent-manager/PluginInstallModal.js +1 -1
  24. package/dist/components/agent-manager/PluginInstallModal.js.map +1 -1
  25. package/dist/components/agent-manager/ProfilesPanel.js +5 -5
  26. package/dist/components/agent-manager/ProfilesPanel.js.map +1 -1
  27. package/dist/components/agent-manager/controls/AutonomySelector.js +1 -1
  28. package/dist/components/agent-manager/controls/AutonomySelector.js.map +1 -1
  29. package/dist/components/agent-manager/controls/SdkSelector.js +1 -1
  30. package/dist/components/agent-manager/controls/SdkSelector.js.map +1 -1
  31. package/dist/components/agent-manager/controls/VoiceToggle.js +1 -1
  32. package/dist/components/agent-manager/controls/VoiceToggle.js.map +1 -1
  33. package/dist/components/agent-manager/detail/SessionConfigPanel.js +6 -6
  34. package/dist/components/agent-manager/detail/SessionConfigPanel.js.map +1 -1
  35. package/dist/components/agent-manager/detail/SessionLogsPanel.js +5 -5
  36. package/dist/components/agent-manager/detail/SessionLogsPanel.js.map +1 -1
  37. package/dist/components/agent-manager/detail/SessionToolsPanel.js +1 -1
  38. package/dist/components/agent-manager/detail/SessionToolsPanel.js.map +1 -1
  39. package/dist/components/agent-manager/dialogs/NewSessionDialog.js +2 -2
  40. package/dist/components/agent-manager/dialogs/NewSessionDialog.js.map +1 -1
  41. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js +1 -1
  42. package/dist/components/agent-manager/dialogs/RenameSessionDialog.js.map +1 -1
  43. package/dist/components/agents/AgentCard.js +14 -11
  44. package/dist/components/agents/AgentCard.js.map +1 -1
  45. package/dist/components/ai/AIContextsTab.js +1 -1
  46. package/dist/components/ai/AIContextsTab.js.map +1 -1
  47. package/dist/components/ai/AIOverviewTab.js +4 -4
  48. package/dist/components/ai/AIOverviewTab.js.map +1 -1
  49. package/dist/components/ai/AIPlanPanel.js +4 -4
  50. package/dist/components/ai/AIPlanPanel.js.map +1 -1
  51. package/dist/components/ai/AIPlaygroundTab.js +1 -1
  52. package/dist/components/ai/AIPlaygroundTab.js.map +1 -1
  53. package/dist/components/ai/AIPromptsTab.js +2 -2
  54. package/dist/components/ai/AIPromptsTab.js.map +1 -1
  55. package/dist/components/ai/AIProviderCredentialsCard.js +4 -4
  56. package/dist/components/ai/AIProviderCredentialsCard.js.map +1 -1
  57. package/dist/components/ai/AIQueueTab.js +4 -4
  58. package/dist/components/ai/AIQueueTab.js.map +1 -1
  59. package/dist/components/ai/AISessionsTab.js +4 -4
  60. package/dist/components/ai/AISessionsTab.js.map +1 -1
  61. package/dist/components/ai/AITasksTab.js +1 -1
  62. package/dist/components/ai/AITasksTab.js.map +1 -1
  63. package/dist/components/ai/ClaudeCredentialsCard.js +3 -3
  64. package/dist/components/ai/ClaudeCredentialsCard.js.map +1 -1
  65. package/dist/components/ai/PluginHarnessPicker.js +3 -3
  66. package/dist/components/ai/PluginHarnessPicker.js.map +1 -1
  67. package/dist/components/analytics/AnalyticsBreakdownChart.js +8 -8
  68. package/dist/components/analytics/AnalyticsBreakdownChart.js.map +1 -1
  69. package/dist/components/analytics/AnalyticsTimeSeriesChart.js +5 -5
  70. package/dist/components/analytics/AnalyticsTimeSeriesChart.js.map +1 -1
  71. package/dist/components/audit/AuditDeleteDialog.js +2 -2
  72. package/dist/components/audit/AuditDeleteDialog.js.map +1 -1
  73. package/dist/components/audit/AuditExportButton.js +5 -5
  74. package/dist/components/audit/AuditExportButton.js.map +1 -1
  75. package/dist/components/audit/AuditLogDetail.js +9 -9
  76. package/dist/components/audit/AuditLogDetail.js.map +1 -1
  77. package/dist/components/audit/AuditLogFilters.js +1 -1
  78. package/dist/components/audit/AuditLogFilters.js.map +1 -1
  79. package/dist/components/audit/AuditLogStats.js +1 -1
  80. package/dist/components/audit/AuditLogStats.js.map +1 -1
  81. package/dist/components/audit/AuditLogTable.js +28 -28
  82. package/dist/components/audit/AuditLogTable.js.map +1 -1
  83. package/dist/components/catalog/CatalogCard.js +3 -3
  84. package/dist/components/catalog/CatalogCard.js.map +1 -1
  85. package/dist/components/catalog/CatalogForm.js +1 -1
  86. package/dist/components/catalog/CatalogForm.js.map +1 -1
  87. package/dist/components/common/ActionAgentTargetNotice.js +6 -6
  88. package/dist/components/common/ActionAgentTargetNotice.js.map +1 -1
  89. package/dist/components/common/CommandEditor.js +1 -1
  90. package/dist/components/common/CommandEditor.js.map +1 -1
  91. package/dist/components/docs/DocsPageTree.js +1 -1
  92. package/dist/components/docs/DocsPageTree.js.map +1 -1
  93. package/dist/components/docs/DocsPreviewPanel.js +1 -1
  94. package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
  95. package/dist/components/docs/DocsRevisionHistory.js +4 -4
  96. package/dist/components/docs/DocsRevisionHistory.js.map +1 -1
  97. package/dist/components/docs/DocsSettingsPanel.js +7 -7
  98. package/dist/components/docs/DocsSettingsPanel.js.map +1 -1
  99. package/dist/components/docs/DocsTabPanel.js +1 -1
  100. package/dist/components/docs/DocsTabPanel.js.map +1 -1
  101. package/dist/components/graph/ConnectionPermissionsDialog.js +2 -2
  102. package/dist/components/graph/ConnectionPermissionsDialog.js.map +1 -1
  103. package/dist/components/graph/MeshDeployWizard.js +3 -3
  104. package/dist/components/graph/MeshDeployWizard.js.map +1 -1
  105. package/dist/components/graph/MeshRequestPanel.js +2 -2
  106. package/dist/components/graph/MeshRequestPanel.js.map +1 -1
  107. package/dist/components/idp-components/ComponentCard.js +5 -5
  108. package/dist/components/idp-components/ComponentCard.js.map +1 -1
  109. package/dist/components/idp-components/ComponentForm.js +1 -1
  110. package/dist/components/idp-components/ComponentForm.js.map +1 -1
  111. package/dist/components/idp-components/DependencyGraphTab.js +7 -7
  112. package/dist/components/idp-components/DependencyGraphTab.js.map +1 -1
  113. package/dist/components/logs/LogViewer.js +14 -14
  114. package/dist/components/logs/LogViewer.js.map +1 -1
  115. package/dist/components/notes/NoteCard.js +1 -1
  116. package/dist/components/notes/NoteCard.js.map +1 -1
  117. package/dist/components/notes/NoteEditor.js +2 -2
  118. package/dist/components/notes/NoteEditor.js.map +1 -1
  119. package/dist/components/notes/NoteList.js +1 -1
  120. package/dist/components/notes/NoteList.js.map +1 -1
  121. package/dist/components/notes/NotesTabPanel.js +1 -1
  122. package/dist/components/notes/NotesTabPanel.js.map +1 -1
  123. package/dist/components/scorecard/ScorecardEmptyState.js +1 -1
  124. package/dist/components/scorecard/ScorecardEmptyState.js.map +1 -1
  125. package/dist/components/scorecard/ScorecardPanel.js +3 -3
  126. package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
  127. package/dist/components/security/SecurityScanList.js +11 -11
  128. package/dist/components/security/SecurityScanList.js.map +1 -1
  129. package/dist/components/sessions/SessionCard.js +26 -19
  130. package/dist/components/sessions/SessionCard.js.map +1 -1
  131. package/dist/components/sessions/SessionStatusBadge.js +7 -7
  132. package/dist/components/sessions/SessionStatusBadge.js.map +1 -1
  133. package/dist/components/shared/AgentSelector.js +4 -4
  134. package/dist/components/shared/AgentSelector.js.map +1 -1
  135. package/dist/components/shared/AgentSetupBanner.js +3 -3
  136. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  137. package/dist/components/shared/Card.js +4 -4
  138. package/dist/components/shared/Card.js.map +1 -1
  139. package/dist/components/shared/ErrorState.js +15 -9
  140. package/dist/components/shared/ErrorState.js.map +1 -1
  141. package/dist/components/shared/FilterDropdown.js +2 -2
  142. package/dist/components/shared/FilterDropdown.js.map +1 -1
  143. package/dist/components/shared/PageSkeleton.js +6 -6
  144. package/dist/components/shared/PageSkeleton.js.map +1 -1
  145. package/dist/components/shared/SearchInput.js +1 -1
  146. package/dist/components/shared/SearchInput.js.map +1 -1
  147. package/dist/components/shared/StatCard.js +7 -7
  148. package/dist/components/shared/StatCard.js.map +1 -1
  149. package/dist/components/templates/PublishTemplateForm.js +2 -2
  150. package/dist/components/templates/PublishTemplateForm.js.map +1 -1
  151. package/dist/components/templates/TemplateCard.js +5 -5
  152. package/dist/components/templates/TemplateCard.js.map +1 -1
  153. package/dist/components/templates/TemplateWizard.js +2 -2
  154. package/dist/components/templates/TemplateWizard.js.map +1 -1
  155. package/dist/components/tunnels/DomainVerificationBadge.js +4 -4
  156. package/dist/components/tunnels/DomainVerificationBadge.js.map +1 -1
  157. package/dist/components/tunnels/ProviderBadge.js +1 -1
  158. package/dist/components/tunnels/ProviderBadge.js.map +1 -1
  159. package/dist/components/tunnels/TunnelCard.js +16 -16
  160. package/dist/components/tunnels/TunnelCard.js.map +1 -1
  161. package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
  162. package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
  163. package/dist/components/tunnels/TunnelPublicAccessPanel.js +1 -1
  164. package/dist/components/tunnels/TunnelPublicAccessPanel.js.map +1 -1
  165. package/dist/components/tunnels/TunnelStatusBadge.js +4 -4
  166. package/dist/components/tunnels/TunnelStatusBadge.js.map +1 -1
  167. package/dist/components/vibecalendar/LogsDrawer.js +2 -2
  168. package/dist/components/vibecalendar/LogsDrawer.js.map +1 -1
  169. package/dist/components/vibecalendar/ScheduleTaskModal.js +5 -5
  170. package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
  171. package/dist/components/vibecalendar/VibeCalAgendaView.js +2 -2
  172. package/dist/components/vibecalendar/VibeCalAgendaView.js.map +1 -1
  173. package/dist/components/vibecalendar/VibeCalDayView.js +3 -3
  174. package/dist/components/vibecalendar/VibeCalDayView.js.map +1 -1
  175. package/dist/components/vibecalendar/VibeCalMonthView.js +1 -1
  176. package/dist/components/vibecalendar/VibeCalMonthView.js.map +1 -1
  177. package/dist/components/vibecalendar/VibeCalWeekView.js +4 -4
  178. package/dist/components/vibecalendar/VibeCalWeekView.js.map +1 -1
  179. package/dist/components/vibecalendar/VibeCalendarHeader.js +4 -4
  180. package/dist/components/vibecalendar/VibeCalendarHeader.js.map +1 -1
  181. package/dist/components/vibecalendar/VibeTaskBlock.js +2 -2
  182. package/dist/components/vibecalendar/VibeTaskBlock.js.map +1 -1
  183. package/dist/components/vibecalendar/types.js +6 -6
  184. package/dist/components/vibecalendar/types.js.map +1 -1
  185. package/dist/components/vibedeck/VibeDeckButtonForm.js +9 -9
  186. package/dist/components/vibedeck/VibeDeckButtonForm.js.map +1 -1
  187. package/dist/components/vibedeck/VibeDeckButtonTile.js +6 -6
  188. package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
  189. package/dist/components/vibedeck/VibeDeckExecutionLog.js +10 -10
  190. package/dist/components/vibedeck/VibeDeckExecutionLog.js.map +1 -1
  191. package/dist/components/vibedeck/VibeDeckForm.js +8 -8
  192. package/dist/components/vibedeck/VibeDeckForm.js.map +1 -1
  193. package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
  194. package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
  195. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js +2 -2
  196. package/dist/components/vibedeck/VibeDeckPublicLinkPanel.js.map +1 -1
  197. package/dist/components/vibedeck/VibeDeckSwitcher.js +8 -8
  198. package/dist/components/vibedeck/VibeDeckSwitcher.js.map +1 -1
  199. package/dist/components/vibes/VibeCard.js +22 -18
  200. package/dist/components/vibes/VibeCard.js.map +1 -1
  201. package/dist/components/vibes/VibeList.js +16 -12
  202. package/dist/components/vibes/VibeList.js.map +1 -1
  203. package/dist/pages/ActionsPage.js +4 -3
  204. package/dist/pages/ActionsPage.js.map +1 -1
  205. package/dist/pages/AgentDetailsPage.js +9 -9
  206. package/dist/pages/AgentDetailsPage.js.map +1 -1
  207. package/dist/pages/AgentsLandingPage.js +4 -4
  208. package/dist/pages/AgentsLandingPage.js.map +1 -1
  209. package/dist/pages/AgentsPage.js +14 -14
  210. package/dist/pages/AgentsPage.js.map +1 -1
  211. package/dist/pages/AnalyticsPage.js +8 -8
  212. package/dist/pages/AnalyticsPage.js.map +1 -1
  213. package/dist/pages/CatalogDetailPage.js +11 -11
  214. package/dist/pages/CatalogDetailPage.js.map +1 -1
  215. package/dist/pages/CatalogPage.js +12 -9
  216. package/dist/pages/CatalogPage.js.map +1 -1
  217. package/dist/pages/ComponentDetailPage.js +7 -7
  218. package/dist/pages/ComponentDetailPage.js.map +1 -1
  219. package/dist/pages/ComponentsPage.js +12 -9
  220. package/dist/pages/ComponentsPage.js.map +1 -1
  221. package/dist/pages/EnvTopologyPage.js +2 -2
  222. package/dist/pages/EnvTopologyPage.js.map +1 -1
  223. package/dist/pages/GettingStartedPage.js +12 -12
  224. package/dist/pages/GettingStartedPage.js.map +1 -1
  225. package/dist/pages/HealthPage.js +12 -12
  226. package/dist/pages/HealthPage.js.map +1 -1
  227. package/dist/pages/LogsPage.js +4 -4
  228. package/dist/pages/LogsPage.js.map +1 -1
  229. package/dist/pages/NoteDetailsPage.js +5 -5
  230. package/dist/pages/NoteDetailsPage.js.map +1 -1
  231. package/dist/pages/OverviewPage.js +74 -41
  232. package/dist/pages/OverviewPage.js.map +1 -1
  233. package/dist/pages/PluginsCatalogPage.js +6 -3
  234. package/dist/pages/PluginsCatalogPage.js.map +1 -1
  235. package/dist/pages/ScheduledJobDetailPage.js +7 -7
  236. package/dist/pages/ScheduledJobDetailPage.js.map +1 -1
  237. package/dist/pages/SessionDetailsPage.js +21 -21
  238. package/dist/pages/SessionDetailsPage.js.map +1 -1
  239. package/dist/pages/SessionsPage.js +20 -20
  240. package/dist/pages/SessionsPage.js.map +1 -1
  241. package/dist/pages/SettingsPage.js +64 -52
  242. package/dist/pages/SettingsPage.js.map +1 -1
  243. package/dist/pages/SharedSessionPage.js +21 -21
  244. package/dist/pages/SharedSessionPage.js.map +1 -1
  245. package/dist/pages/SharedVibeDeckPage.js +5 -5
  246. package/dist/pages/SharedVibeDeckPage.js.map +1 -1
  247. package/dist/pages/TargetDetailsPage.js +56 -65
  248. package/dist/pages/TargetDetailsPage.js.map +1 -1
  249. package/dist/pages/TargetsPage.js +4 -4
  250. package/dist/pages/TargetsPage.js.map +1 -1
  251. package/dist/pages/TemplateDetailPage.js +10 -10
  252. package/dist/pages/TemplateDetailPage.js.map +1 -1
  253. package/dist/pages/TemplatesPage.js +6 -5
  254. package/dist/pages/TemplatesPage.js.map +1 -1
  255. package/dist/pages/VibeAuditPage.js +3 -3
  256. package/dist/pages/VibeAuditPage.js.map +1 -1
  257. package/dist/pages/VibeCalendarPage.js +3 -3
  258. package/dist/pages/VibeCalendarPage.js.map +1 -1
  259. package/dist/pages/VibeDeckPage.js +3 -3
  260. package/dist/pages/VibeDeckPage.js.map +1 -1
  261. package/dist/pages/VibeDetailsPage.js +15 -15
  262. package/dist/pages/VibeDetailsPage.js.map +1 -1
  263. package/dist/pages/VibeTaskDetailPage.js +5 -5
  264. package/dist/pages/VibeTaskDetailPage.js.map +1 -1
  265. package/dist/pages/VibesPage.js +18 -18
  266. package/dist/pages/VibesPage.js.map +1 -1
  267. package/dist/pages/WebhooksPage.js +11 -11
  268. package/dist/pages/WebhooksPage.js.map +1 -1
  269. package/dist/pages/ai/AIBookmarksPage.js +1 -1
  270. package/dist/pages/ai/AIBookmarksPage.js.map +1 -1
  271. package/dist/pages/ai/AISessionDetailPage.js +6 -6
  272. package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
  273. package/dist/pages/tunnels/AuditTab.js +1 -1
  274. package/dist/pages/tunnels/AuditTab.js.map +1 -1
  275. package/dist/pages/tunnels/DomainsTab.js +1 -1
  276. package/dist/pages/tunnels/DomainsTab.js.map +1 -1
  277. package/dist/pages/tunnels/ProvidersTab.js +1 -1
  278. package/dist/pages/tunnels/ProvidersTab.js.map +1 -1
  279. package/dist/pages/tunnels/SessionsTab.js +1 -1
  280. package/dist/pages/tunnels/SessionsTab.js.map +1 -1
  281. package/dist/pages/tunnels/TunnelDetailsPage.js +3 -3
  282. package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
  283. package/dist/pages/tunnels/UsageTab.js +1 -1
  284. package/dist/pages/tunnels/UsageTab.js.map +1 -1
  285. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js +16 -16
  286. package/dist/pages/tunnels/tabs/TunnelDomainsTab.js.map +1 -1
  287. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js +1 -1
  288. package/dist/pages/tunnels/tabs/TunnelOverviewTab.js.map +1 -1
  289. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js +52 -49
  290. package/dist/pages/tunnels/tabs/TunnelSessionsTab.js.map +1 -1
  291. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js +9 -9
  292. package/dist/pages/tunnels/tabs/TunnelSettingsTab.js.map +1 -1
  293. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentDetailPage.js","names":[],"sources":["../../src/pages/ComponentDetailPage.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport {\n ArrowLeft,\n Box,\n BookOpen,\n BarChart3,\n FileText,\n Settings,\n RefreshCw,\n FileCode,\n Layers,\n Upload,\n Trash2,\n Tag,\n Plus,\n X,\n Share2,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatCard,\n EmptyState,\n ErrorState,\n QuotaExhaustedDialog,\n ConfirmDialog,\n} from '@/components/shared';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\n\nimport { DocsTabPanel } from '@/components/docs';\nimport { ScorecardPanel } from '@/components/scorecard';\nimport { CatalogCard } from '@/components/catalog';\nimport type { CatalogCardData } from '@/components/catalog';\nimport { ComponentForm, DependencyGraphTab } from '@/components/idp-components';\nimport type { ComponentFormData } from '@/components/idp-components';\nimport { PublishTemplateForm } from '@/components/templates';\nimport type { PublishTemplateFormData } from '@/components/templates';\nimport { EntityShareButton } from '@/components/sharing';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { isQuotaExhaustedError, markQuotaHandledLocally } from '@/utils/quotaUtils';\nimport {\n useGetComponentQuery,\n useUpdateComponentMutation,\n useDeleteComponentMutation,\n usePublishComponentAsTemplateMutation,\n useAddComponentToCatalogMutation,\n useListCatalogsQuery,\n} from '@/generated/wspace-operations';\nimport type { VibecontrolsTemplateCategory } from '@/generated/wspace-types';\n\ntype ComponentTab =\n | 'overview'\n | 'catalogs'\n | 'scorecard'\n | 'docs'\n | 'dependencies'\n | 'template'\n | 'settings';\nconst COMPONENT_TABS: readonly ComponentTab[] = [\n 'overview',\n 'catalogs',\n 'scorecard',\n 'docs',\n 'dependencies',\n 'template',\n 'settings',\n];\n\nexport function ComponentDetailPage() {\n const { t } = useI18n();\n const { id } = useParams<{ id: string }>();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canReadComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_READ);\n const canUpdateComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_UPDATE);\n const canDeleteComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_DELETE);\n const canReadCatalog = hasPermission(VIBE_PERMISSIONS.CATALOG_READ);\n const canUpdateCatalog = hasPermission(VIBE_PERMISSIONS.CATALOG_UPDATE);\n const canUseCatalogPicker = canReadCatalog && canUpdateCatalog;\n const canCreateTemplate = hasPermission(VIBE_PERMISSIONS.TEMPLATE_CREATE);\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const [activeTab, setActiveTab] = useQueryBackedTab<ComponentTab>(COMPONENT_TABS, 'overview');\n const [showEditForm, setShowEditForm] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n const [showPublishForm, setShowPublishForm] = useState(false);\n const [showAddToCatalog, setShowAddToCatalog] = useState(false);\n\n const { data, loading, error, refetch } = useGetComponentQuery({\n variables: { id: id || '' },\n skip: !id || permissionsLoading || !canReadComponent,\n fetchPolicy: 'cache-and-network',\n });\n\n const [updateComponent] = useUpdateComponentMutation({ refetchQueries: ['GetComponent'] });\n const [deleteComponent] = useDeleteComponentMutation({ refetchQueries: ['ListComponents'] });\n const [publishAsTemplate] = usePublishComponentAsTemplateMutation({\n refetchQueries: ['GetComponent'],\n });\n const [addToCatalog] = useAddComponentToCatalogMutation({ refetchQueries: ['GetComponent'] });\n const { data: catalogsData } = useListCatalogsQuery({\n variables: { pagination: { limit: 100, offset: 0 } },\n skip: !showAddToCatalog || !canUseCatalogPicker,\n fetchPolicy: 'cache-and-network',\n });\n\n const component = data?.vibecontrolsComponent ?? null;\n\n const catalogs: CatalogCardData[] = useMemo(() => {\n return (component?.catalogs ?? []).map((entry: Record<string, any>) => {\n const c = entry.catalog || {};\n return {\n id: c.id as string,\n name: c.name as string,\n description: (c.description as string) || null,\n visibility: c.visibility as CatalogCardData['visibility'],\n componentCount: (c.componentCount as number) || 0,\n vibeCount: (c.vibeCount as number) || 0,\n tags: (c.tags as string[]) || [],\n createdAt: c.createdAt as string,\n updatedAt: c.updatedAt as string,\n };\n });\n }, [component?.catalogs]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!canReadComponent)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleBack = () => {\n navigate('/components');\n };\n\n const handleCatalogClick = (catalog: CatalogCardData) => {\n navigate(`/catalogs/${catalog.id}`);\n };\n\n const handleUpdateComponent = async (formData: ComponentFormData) => {\n if (!id || !canUpdateComponent) return;\n await updateComponent({\n variables: {\n id,\n input: {\n name: formData.name,\n description: formData.description || undefined,\n type: formData.type,\n lifecycle: formData.lifecycle,\n language: formData.language || undefined,\n framework: formData.framework || undefined,\n version: formData.version || undefined,\n ownerName: formData.ownerName || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n repositoryUrl: formData.repositoryUrl || undefined,\n documentationUrl: formData.documentationUrl || undefined,\n dependencies: formData.dependencies ?? undefined,\n sbomData: formData.sbomData ?? undefined,\n },\n },\n });\n setSuccessMessage(tr('component.updatedSuccess', 'Component updated successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n };\n\n const handleDeleteComponent = async () => {\n if (!id) return;\n setIsDeleting(true);\n try {\n await deleteComponent({ variables: { id } });\n setShowDeleteConfirm(false);\n navigate('/components');\n } finally {\n setIsDeleting(false);\n }\n };\n\n const handlePublishAsTemplate = async (formData: PublishTemplateFormData) => {\n if (!id || !canCreateTemplate) return;\n try {\n const res = await publishAsTemplate({\n variables: {\n componentId: id,\n input: {\n name: formData.name,\n description: formData.description || undefined,\n category: formData.category as VibecontrolsTemplateCategory,\n version: formData.version || undefined,\n setupInstructions: formData.setupInstructions || undefined,\n variables: formData.variables.length > 0 ? formData.variables : undefined,\n sourceRepositoryUrl: formData.sourceRepositoryUrl,\n },\n },\n });\n if (res.error && isQuotaExhaustedError(res.error)) {\n setShowPublishForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n setShowPublishForm(false);\n setSuccessMessage(tr('component.publishedAsTemplate', 'Published as template successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowPublishForm(false);\n markQuotaHandledLocally();\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n const lifecycleStyles: Record<string, string> = {\n EXPERIMENTAL: 'bg-status-warning-bg text-status-warning-text',\n ACTIVE: 'bg-status-success-bg text-status-success-text',\n DEPRECATED: 'bg-status-error-bg text-status-error-text',\n END_OF_LIFE: 'bg-status-error-bg text-status-error-text',\n };\n\n const deps = Array.isArray(component?.dependencies)\n ? (component.dependencies as Array<{\n name: string;\n version?: string | null;\n type?: string | null;\n }>)\n : [];\n\n const tabs: { id: ComponentTab; label: string; icon: typeof Box; badge?: string }[] = [\n { id: 'overview', label: tr('nav.overview', 'Overview'), icon: Box },\n {\n id: 'catalogs',\n label: tr('component.catalogs', 'Catalogs'),\n icon: BookOpen,\n badge: `${catalogs.length}`,\n },\n { id: 'scorecard', label: tr('component.scorecard', 'Scorecard'), icon: BarChart3 },\n { id: 'docs', label: tr('component.docs', 'Docs'), icon: FileText },\n {\n id: 'dependencies',\n label: tr('component.dependencies', 'Dependencies'),\n icon: Share2,\n badge: deps.length > 0 ? `${deps.length}` : undefined,\n },\n { id: 'template', label: tr('component.template', 'Template'), icon: FileCode },\n { id: 'settings', label: tr('common.settings', 'Settings'), icon: Settings },\n ];\n\n // Guard states\n if (loading && !component) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n if (error && !component) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <ErrorState\n title={tr('component.failedLoad', 'Failed to load component')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!component) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <EmptyState\n icon={<Box className=\"size-8 text-text-secondary\" />}\n title={tr('component.notFound', 'Component not found')}\n description={`No component with ID \"${id}\" exists`}\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg\">\n {successMessage}\n </div>\n )}\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n\n {/* Header */}\n <PageHeader\n title={component.name}\n description={component.description || tr('component.noDescription', 'No description')}\n actions={\n <div className=\"flex items-center gap-2 flex-wrap\">\n <EntityShareButton\n entity=\"component\"\n resource={{ id: component.id, name: component.name }}\n label={tr('component.share', 'Share')}\n variant=\"button\"\n />\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n <span className=\"inline-flex items-center px-2.5 py-1 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n {component.type}\n </span>\n <span\n className={`inline-flex items-center px-2.5 py-1 text-xs font-medium rounded ${lifecycleStyles[component.lifecycle] || 'bg-bg-sunken text-text-secondary'}`}\n >\n {component.lifecycle}\n </span>\n </div>\n }\n />\n\n {/* Stat Cards */}\n <MotionList stagger={0.04} className=\"grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4\">\n <MotionItem>\n <StatCard\n title={tr('component.type', 'Type')}\n value={component.type}\n icon={<Box className=\"size-4\" />}\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.lifecycle', 'Lifecycle')}\n value={component.lifecycle}\n icon={<Layers className=\"size-4\" />}\n variant={\n component.lifecycle === 'ACTIVE'\n ? 'success'\n : component.lifecycle === 'DEPRECATED' || component.lifecycle === 'END_OF_LIFE'\n ? 'error'\n : 'warning'\n }\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.version', 'Version')}\n value={component.version || '-'}\n icon={<FileCode className=\"size-4\" />}\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.catalogs', 'Catalogs')}\n value={catalogs.length}\n icon={<BookOpen className=\"size-4\" />}\n />\n </MotionItem>\n </MotionList>\n\n {/* Universal tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center gap-2\">\n <Tag className=\"size-5\" />\n <h3 className=\"font-semibold text-text-primary\">{tr('component.tags', 'Tags')}</h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_COMPONENT\" entityId={component.id} />\n </div>\n </Card>\n\n {/* Tab Navigation */}\n <div className=\"border-b border-border-default\">\n <nav\n className=\"flex gap-1 -mb-px overflow-x-auto pb-1\"\n aria-label={tr('component.tabsAriaLabel', 'Component tabs')}\n >\n {tabs.map((tab) => {\n const Icon = tab.icon;\n const isActiveTab = activeTab === tab.id;\n return (\n <button\n type=\"button\"\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActiveTab\n ? 'border-action-primary-bg text-action-primary-text'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActiveTab}\n role=\"tab\"\n >\n <Icon className=\"size-4\" />\n {tab.label}\n {tab.badge && (\n <span\n className={`hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${\n isActiveTab\n ? 'bg-action-primary-bg/10 text-action-primary-bg'\n : 'bg-bg-sunken text-text-muted'\n }`}\n >\n {tab.badge}\n </span>\n )}\n </button>\n );\n })}\n </nav>\n </div>\n\n {/* Tab Panels */}\n <AnimatePresence mode=\"wait\">\n {activeTab === 'overview' && (\n <motion.div\n key=\"overview\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {component.description && (\n <Card>\n <div className=\"p-4\">\n <p className=\"text-text-primary\">{component.description}</p>\n </div>\n </Card>\n )}\n\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary\">\n {tr('component.metadata', 'Metadata')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">{tr('component.ownerNameLabel', 'Owner')}</p>\n <p className=\"font-medium text-text-primary\">\n {component.ownerName || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">\n {tr('component.languageLabel', 'Language')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {component.language || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">\n {tr('component.frameworkLabel', 'Framework')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {component.framework || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('component.versionLabel', 'Version')}</p>\n <p className=\"font-medium text-text-primary\">\n {component.version || tr('common.unset', 'Unset')}\n </p>\n </div>\n {component.repositoryUrl && (\n <div className=\"sm:col-span-2\">\n <p className=\"text-text-secondary\">\n {tr('component.repository', 'Repository')}\n </p>\n <a\n href={component.repositoryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"font-medium text-action-primary-bg hover:underline break-all\"\n >\n {component.repositoryUrl}\n </a>\n </div>\n )}\n <div>\n <p className=\"text-text-secondary\">{tr('common.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {new Date(component.createdAt).toLocaleDateString()}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('common.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {new Date(component.updatedAt).toLocaleDateString()}\n </p>\n </div>\n </div>\n </div>\n </Card>\n\n {component.tags?.length > 0 && (\n <Card>\n <div className=\"p-4\">\n <h3 className=\"font-semibold text-text-primary mb-3\">\n {tr('component.tags', 'Tags')}\n </h3>\n <div className=\"flex flex-wrap gap-2\">\n {component.tags.map((tag: string) => (\n <span\n key={tag}\n className=\"px-2.5 py-1 text-sm bg-bg-sunken text-text-secondary rounded-md\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n </Card>\n )}\n </motion.div>\n )}\n\n {activeTab === 'catalogs' && (\n <motion.div\n key=\"catalogs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-4\"\n >\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {catalogs.length}{' '}\n {tr('component.catalogsContaining', 'catalogs containing this component')}\n </p>\n {canUseCatalogPicker && (\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(true)}\n className=\"flex items-center gap-2 px-3 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.addToCatalog', 'Add to Catalog')}\n </button>\n )}\n </div>\n {catalogs.length > 0 ? (\n <MotionList\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n >\n {catalogs.map((catalog) => (\n <MotionItem key={catalog.id}>\n <CatalogCard catalog={catalog} onOpen={handleCatalogClick} />\n </MotionItem>\n ))}\n </MotionList>\n ) : (\n <EmptyState\n icon={<BookOpen className=\"size-8 text-text-secondary\" />}\n title={tr('component.noCatalogs', 'Not in any catalogs')}\n description={tr(\n 'component.noCatalogsDescription',\n 'This component has not been added to any catalogs yet'\n )}\n action={\n canUseCatalogPicker ? (\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.addToCatalog', 'Add to Catalog')}\n </button>\n ) : undefined\n }\n />\n )}\n </motion.div>\n )}\n\n {activeTab === 'scorecard' && (\n <motion.div\n key=\"scorecard\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <ScorecardPanel ownerType=\"COMPONENT\" ownerId={id || ''} />\n </motion.div>\n )}\n\n {activeTab === 'docs' && (\n <motion.div\n key=\"docs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <DocsTabPanel ownerType=\"COMPONENT\" ownerId={id || ''} />\n </motion.div>\n )}\n\n {activeTab === 'dependencies' && (\n <motion.div\n key=\"dependencies\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <DependencyGraphTab\n componentName={component.name}\n componentType={component.type}\n dependencies={deps}\n />\n </motion.div>\n )}\n\n {activeTab === 'template' && (\n <motion.div\n key=\"template\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-4\"\n >\n {(component.templates?.length ?? 0) === 0 ? (\n <Card padding=\"lg\">\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <FileCode className=\"size-12 text-text-muted mb-4\" />\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">\n {tr('component.template', 'Publish as Template')}\n </h3>\n <p className=\"text-sm text-text-secondary max-w-md mb-6\">\n {tr(\n 'component.publishDescription',\n 'Turn this component into a reusable template. Others can clone it and fill in configuration variables to create new components.'\n )}\n </p>\n {canCreateTemplate && (\n <button\n type=\"button\"\n onClick={() => setShowPublishForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Upload className=\"size-4\" />\n {tr('component.publishAsTemplate', 'Publish as Template')}\n </button>\n )}\n </div>\n </Card>\n ) : (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary\">Published Templates</h3>\n </div>\n <div className=\"p-4 space-y-3\">\n {component.templates.map((tmpl: Record<string, string>) => (\n <div\n key={tmpl.id}\n className=\"flex items-center justify-between p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"flex items-center gap-3\">\n <FileCode className=\"size-5 text-action-primary-bg\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{tmpl.name}</p>\n <p className=\"text-xs text-text-muted\">\n {tmpl.category} · v{tmpl.version || '—'}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => navigate(`/templates/${tmpl.id}`)}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n View Template →\n </button>\n </div>\n ))}\n {canCreateTemplate && (\n <button\n type=\"button\"\n onClick={() => setShowPublishForm(true)}\n className=\"flex items-center gap-2 px-3 py-2 text-sm text-text-secondary border border-dashed border-border-default hover:border-border-strong rounded-lg w-full justify-center transition-colors\"\n >\n <Upload className=\"size-4\" />\n Update template\n </button>\n )}\n </div>\n </Card>\n )}\n </motion.div>\n )}\n\n {activeTab === 'settings' && (\n <motion.div\n key=\"settings\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <div className=\"space-y-4\">\n {canUpdateComponent && (\n <Card padding=\"lg\">\n <h3 className=\"font-semibold text-text-primary mb-4\">\n {tr('component.editComponent', 'Edit Component')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowEditForm(true)}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('component.editDetails', 'Edit Details')}\n </button>\n </Card>\n )}\n {canDeleteComponent && (\n <Card padding=\"lg\">\n <h3 className=\"font-semibold text-status-error-text mb-2\">\n {tr('component.dangerZone', 'Danger Zone')}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {tr(\n 'component.deleteWarning',\n 'Deleting this component will remove it from all catalogs and break any templates derived from it. This cannot be undone.'\n )}\n </p>\n <button\n type=\"button\"\n data-testid=\"component-delete-button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-status-error-bg text-status-error-text rounded-md hover:opacity-90 transition-opacity\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n {tr('component.deleteComponent', 'Delete Component')}\n </button>\n </Card>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Edit Form */}\n {canUpdateComponent && (\n <ComponentForm\n isOpen={showEditForm}\n onClose={() => setShowEditForm(false)}\n onSubmit={handleUpdateComponent}\n initialData={{\n name: component.name,\n description: component.description || '',\n type: component.type,\n lifecycle: component.lifecycle,\n language: component.language || '',\n framework: component.framework || '',\n version: component.version || '',\n ownerName: component.ownerName || '',\n tags: component.tags || [],\n repositoryUrl: component.repositoryUrl || '',\n documentationUrl: component.documentationUrl || '',\n dependencies: Array.isArray(component.dependencies) ? component.dependencies : null,\n sbomData:\n component.sbomData && typeof component.sbomData === 'object'\n ? (component.sbomData as Record<string, unknown>)\n : null,\n }}\n title={tr('component.editComponent', 'Edit Component')}\n />\n )}\n\n <ConfirmDialog\n isOpen={showDeleteConfirm}\n onClose={() => setShowDeleteConfirm(false)}\n onConfirm={handleDeleteComponent}\n title={tr('component.deleteComponent', 'Delete Component')}\n message={tr(\n 'component.deleteConfirmMessage',\n `Are you sure you want to delete \"${component.name}\"? This action cannot be undone.`\n )}\n confirmLabel={tr('common.delete', 'Delete')}\n variant=\"danger\"\n isLoading={isDeleting}\n />\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Template Quota Reached\"\n message=\"You've reached the maximum number of published templates on your current plan. Upgrade your plan or purchase an add-on to publish more templates.\"\n />\n\n {showPublishForm && canCreateTemplate && (\n <PublishTemplateForm\n componentName={component.name}\n componentRepositoryUrl={component.repositoryUrl}\n onClose={() => setShowPublishForm(false)}\n onSubmit={handlePublishAsTemplate}\n />\n )}\n\n {showAddToCatalog && canUseCatalogPicker && (\n <div\n className=\"fixed inset-0 flex items-center justify-center z-50 p-4\"\n style={{ backgroundColor: 'rgba(0,0,0,0.55)' }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n className=\"bg-bg-surface rounded-lg w-full max-w-md shadow-xl\"\n >\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <h2 className=\"text-base font-semibold text-text-primary\">\n {tr('component.addToCatalog', 'Add to Catalog')}\n </h2>\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(false)}\n className=\"p-1.5 text-text-secondary hover:text-text-primary rounded-md hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n <div className=\"p-2 max-h-80 overflow-y-auto\">\n {(catalogsData?.vibecontrolsCatalogs?.items ?? []).length === 0 ? (\n <p className=\"text-sm text-text-secondary text-center py-6\">\n No catalogs found.{' '}\n <button\n type=\"button\"\n onClick={() => {\n setShowAddToCatalog(false);\n navigate('/catalogs');\n }}\n className=\"text-action-primary-bg hover:underline\"\n >\n Create one first.\n </button>\n </p>\n ) : (\n (catalogsData?.vibecontrolsCatalogs?.items ?? []).map(\n (cat: { id: string; name: string }) => {\n const alreadyIn = catalogs.some((c) => c.id === cat.id);\n return (\n <button\n type=\"button\"\n key={cat.id}\n disabled={alreadyIn}\n onClick={async () => {\n if (!id || alreadyIn) return;\n try {\n await addToCatalog({\n variables: { catalogId: cat.id, componentId: id },\n });\n setShowAddToCatalog(false);\n setSuccessMessage(`Added to ${cat.name}`);\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch {\n // error shown by Apollo\n }\n }}\n className={`flex items-center justify-between w-full px-3 py-2.5 text-left rounded-md transition-colors ${\n alreadyIn\n ? 'opacity-40 cursor-not-allowed'\n : 'hover:bg-bg-sunken cursor-pointer'\n }`}\n >\n <div className=\"flex items-center gap-2\">\n <BookOpen className=\"size-4 text-action-primary-bg flex-shrink-0\" />\n <span className=\"text-sm text-text-primary\">{cat.name}</span>\n </div>\n {alreadyIn && (\n <span className=\"text-xs text-text-muted\">already added</span>\n )}\n </button>\n );\n }\n )\n )}\n </div>\n </motion.div>\n </div>\n )}\n </MotionPage>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ComponentDetailPage.js","names":[],"sources":["../../src/pages/ComponentDetailPage.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport {\n ArrowLeft,\n Box,\n BookOpen,\n BarChart3,\n FileText,\n Settings,\n RefreshCw,\n FileCode,\n Layers,\n Upload,\n Trash2,\n Tag,\n Plus,\n X,\n Share2,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatCard,\n EmptyState,\n ErrorState,\n QuotaExhaustedDialog,\n ConfirmDialog,\n} from '@/components/shared';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\n\nimport { DocsTabPanel } from '@/components/docs';\nimport { ScorecardPanel } from '@/components/scorecard';\nimport { CatalogCard } from '@/components/catalog';\nimport type { CatalogCardData } from '@/components/catalog';\nimport { ComponentForm, DependencyGraphTab } from '@/components/idp-components';\nimport type { ComponentFormData } from '@/components/idp-components';\nimport { PublishTemplateForm } from '@/components/templates';\nimport type { PublishTemplateFormData } from '@/components/templates';\nimport { EntityShareButton } from '@/components/sharing';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useQueryBackedTab } from '@/hooks/useQueryBackedTab';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { isQuotaExhaustedError, markQuotaHandledLocally } from '@/utils/quotaUtils';\nimport {\n useGetComponentQuery,\n useUpdateComponentMutation,\n useDeleteComponentMutation,\n usePublishComponentAsTemplateMutation,\n useAddComponentToCatalogMutation,\n useListCatalogsQuery,\n} from '@/generated/wspace-operations';\nimport type { VibecontrolsTemplateCategory } from '@/generated/wspace-types';\n\ntype ComponentTab =\n | 'overview'\n | 'catalogs'\n | 'scorecard'\n | 'docs'\n | 'dependencies'\n | 'template'\n | 'settings';\nconst COMPONENT_TABS: readonly ComponentTab[] = [\n 'overview',\n 'catalogs',\n 'scorecard',\n 'docs',\n 'dependencies',\n 'template',\n 'settings',\n];\n\nexport function ComponentDetailPage() {\n const { t } = useI18n();\n const { id } = useParams<{ id: string }>();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canReadComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_READ);\n const canUpdateComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_UPDATE);\n const canDeleteComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_DELETE);\n const canReadCatalog = hasPermission(VIBE_PERMISSIONS.CATALOG_READ);\n const canUpdateCatalog = hasPermission(VIBE_PERMISSIONS.CATALOG_UPDATE);\n const canUseCatalogPicker = canReadCatalog && canUpdateCatalog;\n const canCreateTemplate = hasPermission(VIBE_PERMISSIONS.TEMPLATE_CREATE);\n\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n const [activeTab, setActiveTab] = useQueryBackedTab<ComponentTab>(COMPONENT_TABS, 'overview');\n const [showEditForm, setShowEditForm] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n const [showPublishForm, setShowPublishForm] = useState(false);\n const [showAddToCatalog, setShowAddToCatalog] = useState(false);\n\n const { data, loading, error, refetch } = useGetComponentQuery({\n variables: { id: id || '' },\n skip: !id || permissionsLoading || !canReadComponent,\n fetchPolicy: 'cache-and-network',\n });\n\n const [updateComponent] = useUpdateComponentMutation({ refetchQueries: ['GetComponent'] });\n const [deleteComponent] = useDeleteComponentMutation({ refetchQueries: ['ListComponents'] });\n const [publishAsTemplate] = usePublishComponentAsTemplateMutation({\n refetchQueries: ['GetComponent'],\n });\n const [addToCatalog] = useAddComponentToCatalogMutation({ refetchQueries: ['GetComponent'] });\n const { data: catalogsData } = useListCatalogsQuery({\n variables: { pagination: { limit: 100, offset: 0 } },\n skip: !showAddToCatalog || !canUseCatalogPicker,\n fetchPolicy: 'cache-and-network',\n });\n\n const component = data?.vibecontrolsComponent ?? null;\n\n const catalogs: CatalogCardData[] = useMemo(() => {\n return (component?.catalogs ?? []).map((entry: Record<string, any>) => {\n const c = entry.catalog || {};\n return {\n id: c.id as string,\n name: c.name as string,\n description: (c.description as string) || null,\n visibility: c.visibility as CatalogCardData['visibility'],\n componentCount: (c.componentCount as number) || 0,\n vibeCount: (c.vibeCount as number) || 0,\n tags: (c.tags as string[]) || [],\n createdAt: c.createdAt as string,\n updatedAt: c.updatedAt as string,\n };\n });\n }, [component?.catalogs]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!canReadComponent)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleBack = () => {\n navigate('/components');\n };\n\n const handleCatalogClick = (catalog: CatalogCardData) => {\n navigate(`/catalogs/${catalog.id}`);\n };\n\n const handleUpdateComponent = async (formData: ComponentFormData) => {\n if (!id || !canUpdateComponent) return;\n await updateComponent({\n variables: {\n id,\n input: {\n name: formData.name,\n description: formData.description || undefined,\n type: formData.type,\n lifecycle: formData.lifecycle,\n language: formData.language || undefined,\n framework: formData.framework || undefined,\n version: formData.version || undefined,\n ownerName: formData.ownerName || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n repositoryUrl: formData.repositoryUrl || undefined,\n documentationUrl: formData.documentationUrl || undefined,\n dependencies: formData.dependencies ?? undefined,\n sbomData: formData.sbomData ?? undefined,\n },\n },\n });\n setSuccessMessage(tr('component.updatedSuccess', 'Component updated successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n };\n\n const handleDeleteComponent = async () => {\n if (!id) return;\n setIsDeleting(true);\n try {\n await deleteComponent({ variables: { id } });\n setShowDeleteConfirm(false);\n navigate('/components');\n } finally {\n setIsDeleting(false);\n }\n };\n\n const handlePublishAsTemplate = async (formData: PublishTemplateFormData) => {\n if (!id || !canCreateTemplate) return;\n try {\n const res = await publishAsTemplate({\n variables: {\n componentId: id,\n input: {\n name: formData.name,\n description: formData.description || undefined,\n category: formData.category as VibecontrolsTemplateCategory,\n version: formData.version || undefined,\n setupInstructions: formData.setupInstructions || undefined,\n variables: formData.variables.length > 0 ? formData.variables : undefined,\n sourceRepositoryUrl: formData.sourceRepositoryUrl,\n },\n },\n });\n if (res.error && isQuotaExhaustedError(res.error)) {\n setShowPublishForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n setShowPublishForm(false);\n setSuccessMessage(tr('component.publishedAsTemplate', 'Published as template successfully'));\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowPublishForm(false);\n markQuotaHandledLocally();\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n const lifecycleStyles: Record<string, string> = {\n EXPERIMENTAL: 'bg-status-warning-bg text-status-warning-text',\n ACTIVE: 'bg-status-success-bg text-status-success-text',\n DEPRECATED: 'bg-status-error-bg text-status-error-text',\n END_OF_LIFE: 'bg-status-error-bg text-status-error-text',\n };\n\n const deps = Array.isArray(component?.dependencies)\n ? (component.dependencies as Array<{\n name: string;\n version?: string | null;\n type?: string | null;\n }>)\n : [];\n\n const tabs: { id: ComponentTab; label: string; icon: typeof Box; badge?: string }[] = [\n { id: 'overview', label: tr('nav.overview', 'Overview'), icon: Box },\n {\n id: 'catalogs',\n label: tr('component.catalogs', 'Catalogs'),\n icon: BookOpen,\n badge: `${catalogs.length}`,\n },\n { id: 'scorecard', label: tr('component.scorecard', 'Scorecard'), icon: BarChart3 },\n { id: 'docs', label: tr('component.docs', 'Docs'), icon: FileText },\n {\n id: 'dependencies',\n label: tr('component.dependencies', 'Dependencies'),\n icon: Share2,\n badge: deps.length > 0 ? `${deps.length}` : undefined,\n },\n { id: 'template', label: tr('component.template', 'Template'), icon: FileCode },\n { id: 'settings', label: tr('common.settings', 'Settings'), icon: Settings },\n ];\n\n // Guard states\n if (loading && !component) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n if (error && !component) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <ErrorState\n title={tr('component.failedLoad', 'Failed to load component')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!component) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n <EmptyState\n icon={<Box className=\"size-8 text-text-secondary\" />}\n title={tr('component.notFound', 'Component not found')}\n description={`No component with ID \"${id}\" exists`}\n action={\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed top-4 left-4 right-4 sm:left-auto z-50 bg-status-success-bg text-status-success-text px-4 py-3 rounded-md shadow-lg\">\n {successMessage}\n </div>\n )}\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('component.backToComponents', 'Back to Components')}\n </button>\n\n {/* Header */}\n <PageHeader\n title={component.name}\n description={component.description || tr('component.noDescription', 'No description')}\n actions={\n <div className=\"flex items-center gap-2 flex-wrap\">\n <EntityShareButton\n entity=\"component\"\n resource={{ id: component.id, name: component.name }}\n label={tr('component.share', 'Share')}\n variant=\"button\"\n />\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center justify-center p-2 bg-bg-sunken text-text-primary rounded-md hover:bg-action-secondary-bg-hover transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n <span className=\"inline-flex items-center px-2.5 py-1 text-xs font-medium bg-bg-sunken text-text-secondary rounded\">\n {component.type}\n </span>\n <span\n className={`inline-flex items-center px-2.5 py-1 text-xs font-medium rounded ${lifecycleStyles[component.lifecycle] || 'bg-bg-sunken text-text-secondary'}`}\n >\n {component.lifecycle}\n </span>\n </div>\n }\n />\n\n {/* Stat Cards */}\n <MotionList stagger={0.04} className=\"grid grid-cols-2 sm:grid-cols-4 gap-3 sm:gap-4\">\n <MotionItem>\n <StatCard\n title={tr('component.type', 'Type')}\n value={component.type}\n icon={<Box className=\"size-4\" />}\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.lifecycle', 'Lifecycle')}\n value={component.lifecycle}\n icon={<Layers className=\"size-4\" />}\n variant={\n component.lifecycle === 'ACTIVE'\n ? 'success'\n : component.lifecycle === 'DEPRECATED' || component.lifecycle === 'END_OF_LIFE'\n ? 'error'\n : 'warning'\n }\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.version', 'Version')}\n value={component.version || '-'}\n icon={<FileCode className=\"size-4\" />}\n />\n </MotionItem>\n <MotionItem>\n <StatCard\n title={tr('component.catalogs', 'Catalogs')}\n value={catalogs.length}\n icon={<BookOpen className=\"size-4\" />}\n />\n </MotionItem>\n </MotionList>\n\n {/* Universal tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center gap-2\">\n <Tag className=\"size-5\" />\n <h3 className=\"font-semibold text-text-primary\">{tr('component.tags', 'Tags')}</h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_COMPONENT\" entityId={component.id} />\n </div>\n </Card>\n\n {/* Tab Navigation */}\n <div className=\"border-b border-border-default\">\n <nav\n className=\"flex gap-1 -mb-px overflow-x-auto pb-1\"\n aria-label={tr('component.tabsAriaLabel', 'Component tabs')}\n >\n {tabs.map((tab) => {\n const Icon = tab.icon;\n const isActiveTab = activeTab === tab.id;\n return (\n <button\n type=\"button\"\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={`flex shrink-0 items-center gap-1.5 px-3 py-2.5 text-xs sm:gap-2 sm:px-4 sm:text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActiveTab\n ? 'border-action-primary-bg text-action-primary-text'\n : 'border-transparent text-text-secondary hover:text-text-primary hover:border-border-default'\n }`}\n aria-selected={isActiveTab}\n role=\"tab\"\n >\n <Icon className=\"size-4\" />\n {tab.label}\n {tab.badge && (\n <span\n className={`hidden rounded-full px-1.5 py-0.5 text-[10px] sm:inline-flex sm:text-xs ${\n isActiveTab\n ? 'bg-[var(--color-accent-soft)] text-action-primary-bg'\n : 'bg-bg-sunken text-text-muted'\n }`}\n >\n {tab.badge}\n </span>\n )}\n </button>\n );\n })}\n </nav>\n </div>\n\n {/* Tab Panels */}\n <AnimatePresence mode=\"wait\">\n {activeTab === 'overview' && (\n <motion.div\n key=\"overview\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n {component.description && (\n <Card>\n <div className=\"p-4\">\n <p className=\"text-text-primary\">{component.description}</p>\n </div>\n </Card>\n )}\n\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary\">\n {tr('component.metadata', 'Metadata')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">{tr('component.ownerNameLabel', 'Owner')}</p>\n <p className=\"font-medium text-text-primary\">\n {component.ownerName || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">\n {tr('component.languageLabel', 'Language')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {component.language || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">\n {tr('component.frameworkLabel', 'Framework')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {component.framework || tr('common.unset', 'Unset')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('component.versionLabel', 'Version')}</p>\n <p className=\"font-medium text-text-primary\">\n {component.version || tr('common.unset', 'Unset')}\n </p>\n </div>\n {component.repositoryUrl && (\n <div className=\"sm:col-span-2\">\n <p className=\"text-text-secondary\">\n {tr('component.repository', 'Repository')}\n </p>\n <a\n href={component.repositoryUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"font-medium text-action-primary-bg hover:underline break-all\"\n >\n {component.repositoryUrl}\n </a>\n </div>\n )}\n <div>\n <p className=\"text-text-secondary\">{tr('common.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {new Date(component.createdAt).toLocaleDateString()}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('common.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {new Date(component.updatedAt).toLocaleDateString()}\n </p>\n </div>\n </div>\n </div>\n </Card>\n\n {component.tags?.length > 0 && (\n <Card>\n <div className=\"p-4\">\n <h3 className=\"font-semibold text-text-primary mb-3\">\n {tr('component.tags', 'Tags')}\n </h3>\n <div className=\"flex flex-wrap gap-2\">\n {component.tags.map((tag: string) => (\n <span\n key={tag}\n className=\"px-2.5 py-1 text-sm bg-bg-sunken text-text-secondary rounded-md\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n </Card>\n )}\n </motion.div>\n )}\n\n {activeTab === 'catalogs' && (\n <motion.div\n key=\"catalogs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-4\"\n >\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {catalogs.length}{' '}\n {tr('component.catalogsContaining', 'catalogs containing this component')}\n </p>\n {canUseCatalogPicker && (\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(true)}\n className=\"flex items-center gap-2 px-3 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.addToCatalog', 'Add to Catalog')}\n </button>\n )}\n </div>\n {catalogs.length > 0 ? (\n <MotionList\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n >\n {catalogs.map((catalog) => (\n <MotionItem key={catalog.id}>\n <CatalogCard catalog={catalog} onOpen={handleCatalogClick} />\n </MotionItem>\n ))}\n </MotionList>\n ) : (\n <EmptyState\n icon={<BookOpen className=\"size-8 text-text-secondary\" />}\n title={tr('component.noCatalogs', 'Not in any catalogs')}\n description={tr(\n 'component.noCatalogsDescription',\n 'This component has not been added to any catalogs yet'\n )}\n action={\n canUseCatalogPicker ? (\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.addToCatalog', 'Add to Catalog')}\n </button>\n ) : undefined\n }\n />\n )}\n </motion.div>\n )}\n\n {activeTab === 'scorecard' && (\n <motion.div\n key=\"scorecard\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <ScorecardPanel ownerType=\"COMPONENT\" ownerId={id || ''} />\n </motion.div>\n )}\n\n {activeTab === 'docs' && (\n <motion.div\n key=\"docs\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-6\"\n >\n <DocsTabPanel ownerType=\"COMPONENT\" ownerId={id || ''} />\n </motion.div>\n )}\n\n {activeTab === 'dependencies' && (\n <motion.div\n key=\"dependencies\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <DependencyGraphTab\n componentName={component.name}\n componentType={component.type}\n dependencies={deps}\n />\n </motion.div>\n )}\n\n {activeTab === 'template' && (\n <motion.div\n key=\"template\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n className=\"space-y-4\"\n >\n {(component.templates?.length ?? 0) === 0 ? (\n <Card padding=\"lg\">\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <FileCode className=\"size-12 text-text-muted mb-4\" />\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">\n {tr('component.template', 'Publish as Template')}\n </h3>\n <p className=\"text-sm text-text-secondary max-w-md mb-6\">\n {tr(\n 'component.publishDescription',\n 'Turn this component into a reusable template. Others can clone it and fill in configuration variables to create new components.'\n )}\n </p>\n {canCreateTemplate && (\n <button\n type=\"button\"\n onClick={() => setShowPublishForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Upload className=\"size-4\" />\n {tr('component.publishAsTemplate', 'Publish as Template')}\n </button>\n )}\n </div>\n </Card>\n ) : (\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary\">Published Templates</h3>\n </div>\n <div className=\"p-4 space-y-3\">\n {component.templates.map((tmpl: Record<string, string>) => (\n <div\n key={tmpl.id}\n className=\"flex items-center justify-between p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"flex items-center gap-3\">\n <FileCode className=\"size-5 text-action-primary-bg\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{tmpl.name}</p>\n <p className=\"text-xs text-text-muted\">\n {tmpl.category} · v{tmpl.version || '—'}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => navigate(`/templates/${tmpl.id}`)}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n View Template →\n </button>\n </div>\n ))}\n {canCreateTemplate && (\n <button\n type=\"button\"\n onClick={() => setShowPublishForm(true)}\n className=\"flex items-center gap-2 px-3 py-2 text-sm text-text-secondary border border-dashed border-border-default hover:border-border-strong rounded-lg w-full justify-center transition-colors\"\n >\n <Upload className=\"size-4\" />\n Update template\n </button>\n )}\n </div>\n </Card>\n )}\n </motion.div>\n )}\n\n {activeTab === 'settings' && (\n <motion.div\n key=\"settings\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -8 }}\n transition={{ duration: 0.2 }}\n >\n <div className=\"space-y-4\">\n {canUpdateComponent && (\n <Card padding=\"lg\">\n <h3 className=\"font-semibold text-text-primary mb-4\">\n {tr('component.editComponent', 'Edit Component')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowEditForm(true)}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('component.editDetails', 'Edit Details')}\n </button>\n </Card>\n )}\n {canDeleteComponent && (\n <Card padding=\"lg\">\n <h3 className=\"font-semibold text-status-error-text mb-2\">\n {tr('component.dangerZone', 'Danger Zone')}\n </h3>\n <p className=\"text-sm text-text-secondary mb-4\">\n {tr(\n 'component.deleteWarning',\n 'Deleting this component will remove it from all catalogs and break any templates derived from it. This cannot be undone.'\n )}\n </p>\n <button\n type=\"button\"\n data-testid=\"component-delete-button\"\n onClick={() => setShowDeleteConfirm(true)}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-status-error-bg text-status-error-text rounded-md hover:opacity-90 transition-opacity\"\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n {tr('component.deleteComponent', 'Delete Component')}\n </button>\n </Card>\n )}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n\n {/* Edit Form */}\n {canUpdateComponent && (\n <ComponentForm\n isOpen={showEditForm}\n onClose={() => setShowEditForm(false)}\n onSubmit={handleUpdateComponent}\n initialData={{\n name: component.name,\n description: component.description || '',\n type: component.type,\n lifecycle: component.lifecycle,\n language: component.language || '',\n framework: component.framework || '',\n version: component.version || '',\n ownerName: component.ownerName || '',\n tags: component.tags || [],\n repositoryUrl: component.repositoryUrl || '',\n documentationUrl: component.documentationUrl || '',\n dependencies: Array.isArray(component.dependencies) ? component.dependencies : null,\n sbomData:\n component.sbomData && typeof component.sbomData === 'object'\n ? (component.sbomData as Record<string, unknown>)\n : null,\n }}\n title={tr('component.editComponent', 'Edit Component')}\n />\n )}\n\n <ConfirmDialog\n isOpen={showDeleteConfirm}\n onClose={() => setShowDeleteConfirm(false)}\n onConfirm={handleDeleteComponent}\n title={tr('component.deleteComponent', 'Delete Component')}\n message={tr(\n 'component.deleteConfirmMessage',\n `Are you sure you want to delete \"${component.name}\"? This action cannot be undone.`\n )}\n confirmLabel={tr('common.delete', 'Delete')}\n variant=\"danger\"\n isLoading={isDeleting}\n />\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Template Quota Reached\"\n message=\"You've reached the maximum number of published templates on your current plan. Upgrade your plan or purchase an add-on to publish more templates.\"\n />\n\n {showPublishForm && canCreateTemplate && (\n <PublishTemplateForm\n componentName={component.name}\n componentRepositoryUrl={component.repositoryUrl}\n onClose={() => setShowPublishForm(false)}\n onSubmit={handlePublishAsTemplate}\n />\n )}\n\n {showAddToCatalog && canUseCatalogPicker && (\n <div\n className=\"fixed inset-0 flex items-center justify-center z-50 p-4\"\n style={{ backgroundColor: 'rgba(0,0,0,0.55)' }}\n >\n <motion.div\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n className=\"bg-bg-surface rounded-lg w-full max-w-md shadow-xl\"\n >\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default\">\n <h2 className=\"text-base font-semibold text-text-primary\">\n {tr('component.addToCatalog', 'Add to Catalog')}\n </h2>\n <button\n type=\"button\"\n onClick={() => setShowAddToCatalog(false)}\n className=\"p-1.5 text-text-secondary hover:text-text-primary rounded-md hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n <div className=\"p-2 max-h-80 overflow-y-auto\">\n {(catalogsData?.vibecontrolsCatalogs?.items ?? []).length === 0 ? (\n <p className=\"text-sm text-text-secondary text-center py-6\">\n No catalogs found.{' '}\n <button\n type=\"button\"\n onClick={() => {\n setShowAddToCatalog(false);\n navigate('/catalogs');\n }}\n className=\"text-action-primary-bg hover:underline\"\n >\n Create one first.\n </button>\n </p>\n ) : (\n (catalogsData?.vibecontrolsCatalogs?.items ?? []).map(\n (cat: { id: string; name: string }) => {\n const alreadyIn = catalogs.some((c) => c.id === cat.id);\n return (\n <button\n type=\"button\"\n key={cat.id}\n disabled={alreadyIn}\n onClick={async () => {\n if (!id || alreadyIn) return;\n try {\n await addToCatalog({\n variables: { catalogId: cat.id, componentId: id },\n });\n setShowAddToCatalog(false);\n setSuccessMessage(`Added to ${cat.name}`);\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch {\n // error shown by Apollo\n }\n }}\n className={`flex items-center justify-between w-full px-3 py-2.5 text-left rounded-md transition-colors ${\n alreadyIn\n ? 'opacity-40 cursor-not-allowed'\n : 'hover:bg-bg-sunken cursor-pointer'\n }`}\n >\n <div className=\"flex items-center gap-2\">\n <BookOpen className=\"size-4 text-action-primary-bg flex-shrink-0\" />\n <span className=\"text-sm text-text-primary\">{cat.name}</span>\n </div>\n {alreadyIn && (\n <span className=\"text-xs text-text-muted\">already added</span>\n )}\n </button>\n );\n }\n )\n )}\n </div>\n </motion.div>\n </div>\n )}\n </MotionPage>\n );\n}\n"],"mappings":"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"}
@@ -165,7 +165,7 @@ function S() {
165
165
  children: /* @__PURE__ */ v("div", {
166
166
  className: "text-center space-y-2",
167
167
  children: [/* @__PURE__ */ _("h2", {
168
- className: "text-lg font-semibold text-foreground",
168
+ className: "text-lg font-semibold text-text-primary tracking-tight",
169
169
  children: "Access Denied"
170
170
  }), /* @__PURE__ */ _("p", {
171
171
  className: "text-sm text-text-secondary",
@@ -177,14 +177,14 @@ function S() {
177
177
  S(`/components/${e.id}`);
178
178
  };
179
179
  return K && Q.length === 0 ? /* @__PURE__ */ _(x, {
180
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
180
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
181
181
  children: /* @__PURE__ */ _(te, {
182
182
  title: O("component.failedLoad", "Failed to load components"),
183
183
  message: K.message,
184
184
  onRetry: () => q()
185
185
  })
186
186
  }) : /* @__PURE__ */ v(x, {
187
- className: "space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen",
187
+ className: "space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen",
188
188
  children: [
189
189
  /* @__PURE__ */ _(ee, {
190
190
  title: O("component.title", "Components"),
@@ -195,13 +195,13 @@ function S() {
195
195
  type: "button",
196
196
  onClick: () => q(),
197
197
  disabled: G,
198
- className: "flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50",
198
+ className: "flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-button transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
199
199
  title: O("common.refresh", "Refresh"),
200
200
  children: /* @__PURE__ */ _(oe, { className: `size-4 ${G ? "animate-spin" : ""}` })
201
201
  }), E && /* @__PURE__ */ v("button", {
202
202
  type: "button",
203
203
  onClick: () => F(!0),
204
- className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
204
+ className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
205
205
  children: [/* @__PURE__ */ _(g, { className: "size-4" }), O("component.createComponent", "Create Component")]
206
206
  })]
207
207
  })
@@ -266,7 +266,10 @@ function S() {
266
266
  }) }, e.id))
267
267
  }, "component-grid")
268
268
  }) : /* @__PURE__ */ _(ne, {
269
- icon: /* @__PURE__ */ _(ae, { className: "size-8 text-text-secondary" }),
269
+ icon: /* @__PURE__ */ _(ae, {
270
+ className: "size-6 text-action-primary-bg",
271
+ "aria-hidden": "true"
272
+ }),
270
273
  title: k || A !== "all" || M !== "all" ? O("component.emptyNoResults", "No components found") : O("component.emptyNoComponents", "No components yet"),
271
274
  description: k || A !== "all" || M !== "all" ? O("component.emptyAdjustSearch", "Try adjusting your search or filters") : O("component.emptyCreate", "A component is any piece of software in your system — a backend service, a frontend app, a shared library, an API. Register one to start tracking its dependencies, owner, and lifecycle stage."),
272
275
  action: !k && A === "all" && M === "all" ? /* @__PURE__ */ v("div", {
@@ -274,7 +277,7 @@ function S() {
274
277
  children: [E && /* @__PURE__ */ v("button", {
275
278
  type: "button",
276
279
  onClick: () => F(!0),
277
- className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors",
280
+ className: "flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
278
281
  children: [/* @__PURE__ */ _(g, { className: "size-4" }), O("component.createComponent", "Create Component")]
279
282
  }), /* @__PURE__ */ _(l, { prompt: "What is a Component in VibeControls and how do I add one?" })]
280
283
  }) : void 0
@@ -285,12 +288,12 @@ function S() {
285
288
  type: "button",
286
289
  onClick: he,
287
290
  disabled: H,
288
- className: "flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken-hover transition-colors disabled:opacity-50",
291
+ className: "flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-button border border-border-subtle hover:bg-bg-surface hover:border-border-strong transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
289
292
  children: H ? O("common.loading", "Loading...") : O("common.loadMore", "Load more")
290
293
  })
291
294
  }),
292
295
  R && /* @__PURE__ */ _("div", {
293
- className: "fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm",
296
+ className: "fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg-subtle text-status-success-text border border-status-success-border rounded-card shadow-elevation-3 text-sm",
294
297
  children: R
295
298
  }),
296
299
  /* @__PURE__ */ _(n, {
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentsPage.js","names":[],"sources":["../../src/pages/ComponentsPage.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { Plus, Box, RefreshCw } from 'lucide-react';\nimport { ComponentCard } from '@/components/idp-components';\nimport type { ComponentCardData } from '@/components/idp-components';\nimport { ComponentForm } from '@/components/idp-components';\nimport type { ComponentFormData } from '@/components/idp-components';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useDraftEntityTags } from '@/hooks/useDraftEntityTags';\nimport {\n PageHeader,\n SearchInput,\n FilterDropdown,\n EmptyState,\n ErrorState,\n GetHelpButton,\n QuotaExhaustedDialog,\n} from '@/components/shared';\nimport { isQuotaExhaustedError } from '@/utils/quotaUtils';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence } from 'framer-motion';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useListComponentsQuery, useCreateComponentMutation } from '@/generated/wspace-operations';\n\nexport function ComponentsPage() {\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canCreateComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_CREATE);\n const canReadComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_READ);\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n if (!params) return template;\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const typeOptions = [\n { value: 'all', label: tr('component.allTypes', 'All Types') },\n { value: 'SERVICE', label: tr('component.typeService', 'Service') },\n { value: 'FRONTEND', label: tr('component.typeFrontend', 'Frontend') },\n { value: 'LIBRARY', label: tr('component.typeLibrary', 'Library') },\n { value: 'API', label: tr('component.typeApi', 'API') },\n { value: 'MOBILE', label: tr('component.typeMobile', 'Mobile') },\n { value: 'DATABASE', label: tr('component.typeDatabase', 'Database') },\n { value: 'INFRASTRUCTURE', label: tr('component.typeInfrastructure', 'Infrastructure') },\n { value: 'CUSTOM', label: tr('component.typeCustom', 'Custom') },\n ];\n\n const lifecycleOptions = [\n { value: 'all', label: tr('component.allLifecycles', 'All Lifecycles') },\n { value: 'EXPERIMENTAL', label: tr('component.lifecycleExperimental', 'Experimental') },\n { value: 'ACTIVE', label: tr('component.lifecycleActive', 'Active') },\n { value: 'DEPRECATED', label: tr('component.lifecycleDeprecated', 'Deprecated') },\n { value: 'END_OF_LIFE', label: tr('component.lifecycleEndOfLife', 'End of Life') },\n ];\n\n const PAGE_SIZE = 50;\n const [searchQuery, setSearchQuery] = useState('');\n const [typeFilter, setTypeFilter] = useState('all');\n const [lifecycleFilter, setLifecycleFilter] = useState('all');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [accumulated, setAccumulated] = useState<ComponentCardData[]>([]);\n const [loadingMore, setLoadingMore] = useState(false);\n\n const { data, loading, error, refetch, fetchMore } = useListComponentsQuery({\n variables: {\n filter: {\n type: typeFilter !== 'all' ? typeFilter : undefined,\n lifecycle: lifecycleFilter !== 'all' ? lifecycleFilter : undefined,\n search: searchQuery || undefined,\n },\n pagination: { limit: PAGE_SIZE, offset: 0 },\n },\n skip: permissionsLoading || !canReadComponent,\n fetchPolicy: 'cache-and-network',\n notifyOnNetworkStatusChange: true,\n });\n\n const [createComponent] = useCreateComponentMutation({\n refetchQueries: ['ListComponents'],\n awaitRefetchQueries: true,\n });\n const { setDraftTagIds, flushTags } = useDraftEntityTags('VIBECONTROLS_COMPONENT');\n\n const mapItems = useCallback(\n (items: ReadonlyArray<Record<string, unknown>>): ComponentCardData[] =>\n items.map((item) => ({\n id: item.id as string,\n name: item.name as string,\n description: (item.description as string) || null,\n type: item.type as ComponentCardData['type'],\n lifecycle: item.lifecycle as ComponentCardData['lifecycle'],\n version: (item.version as string) || null,\n language: (item.language as string) || null,\n framework: (item.framework as string) || null,\n tags: (item.tags as string[]) || [],\n createdAt: item.createdAt as string,\n updatedAt: item.updatedAt as string,\n })),\n []\n );\n\n useEffect(() => {\n const items = data?.vibecontrolsComponents?.items ?? [];\n setAccumulated(mapItems(items as ReadonlyArray<Record<string, unknown>>));\n }, [data?.vibecontrolsComponents?.items, mapItems]);\n\n const total = data?.vibecontrolsComponents?.total ?? 0;\n const hasMore = accumulated.length < total;\n const components = accumulated;\n const filteredComponents = accumulated;\n\n const handleLoadMore = useCallback(async () => {\n if (loadingMore || !hasMore) return;\n setLoadingMore(true);\n try {\n await fetchMore({\n variables: { pagination: { limit: PAGE_SIZE, offset: accumulated.length } },\n updateQuery: (prev, { fetchMoreResult }) => {\n if (!fetchMoreResult?.vibecontrolsComponents) return prev;\n const prevList = prev.vibecontrolsComponents;\n const nextList = fetchMoreResult.vibecontrolsComponents;\n return {\n ...prev,\n vibecontrolsComponents: {\n ...nextList,\n items: [...(prevList?.items ?? []), ...nextList.items],\n total: nextList.total,\n hasMore: nextList.hasMore,\n },\n };\n },\n });\n } finally {\n setLoadingMore(false);\n }\n }, [fetchMore, accumulated.length, loadingMore, hasMore]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!canReadComponent)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleComponentSelect = (component: ComponentCardData) => {\n navigate(`/components/${component.id}`);\n };\n\n const handleCreateComponent = async (formData: ComponentFormData) => {\n try {\n const result = await createComponent({\n variables: {\n input: {\n name: formData.name,\n description: formData.description || undefined,\n type: formData.type,\n lifecycle: formData.lifecycle,\n language: formData.language || undefined,\n framework: formData.framework || undefined,\n version: formData.version || undefined,\n ownerName: formData.ownerName || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n repositoryUrl: formData.repositoryUrl || undefined,\n documentationUrl: formData.documentationUrl || undefined,\n dependencies: formData.dependencies ?? undefined,\n sbomData: formData.sbomData ?? undefined,\n },\n },\n });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowCreateForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n if (!result.data?.createVibecontrolsComponent?.id) {\n throw new Error(tr('component.failedCreate', 'Failed to create component'));\n }\n const newComponentId = result.data.createVibecontrolsComponent.id;\n setShowCreateForm(false);\n setSuccessMessage(tr('component.createdSuccess', 'Component created successfully'));\n await flushTags(newComponentId);\n await refetch();\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowCreateForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n if (error && components.length === 0) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <ErrorState\n title={tr('component.failedLoad', 'Failed to load components')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <PageHeader\n title={tr('component.title', 'Components')}\n description={\n total > 0\n ? tr('component.description', '{{total}} components in your catalog', {\n total: components.length,\n })\n : tr(\n 'component.descriptionEmpty',\n 'Track every service, frontend, library, and API in your system — dependencies, owners, and lifecycle in one place'\n )\n }\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-md transition-colors disabled:opacity-50\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {canCreateComponent && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.createComponent', 'Create Component')}\n </button>\n )}\n </div>\n }\n />\n\n {/* Filters — SearchInput / FilterDropdown are custom components that don't\n forward rest props onto a DOM node, so the tour anchors live on\n wrapper <div>s. */}\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div data-tour=\"vibecontrols-component-search\" className=\"flex-1 sm:w-64 sm:flex-none\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('component.searchPlaceholder', 'Search components...')}\n className=\"w-full\"\n />\n </div>\n </div>\n <div className=\"flex items-center gap-2 sm:gap-3 flex-wrap\">\n <div data-tour=\"vibecontrols-component-type-filter\">\n <FilterDropdown\n label={tr('component.filterType', 'Type')}\n value={typeFilter}\n options={typeOptions}\n onChange={setTypeFilter}\n />\n </div>\n <div data-tour=\"vibecontrols-component-lifecycle-filter\">\n <FilterDropdown\n label={tr('component.filterLifecycle', 'Lifecycle')}\n value={lifecycleFilter}\n options={lifecycleOptions}\n onChange={setLifecycleFilter}\n />\n </div>\n </div>\n </div>\n\n {/* Results count */}\n <p className=\"text-sm text-text-secondary\">\n {tr('component.showingResults', 'Showing {{filtered}} of {{total}} components', {\n filtered: filteredComponents.length,\n total,\n })}\n {loading && (\n <span className=\"ml-2 text-text-muted\">{tr('common.refreshing', '(refreshing...)')}</span>\n )}\n </p>\n\n {/* Grid */}\n {loading && components.length === 0 ? (\n <PageSkeleton variant=\"cards\" count={6} />\n ) : filteredComponents.length > 0 ? (\n <AnimatePresence mode=\"wait\">\n <MotionList\n key=\"component-grid\"\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n data-tour=\"vibecontrols-component-grid\"\n >\n {filteredComponents.map((component) => (\n <MotionItem key={component.id}>\n <ComponentCard component={component} onOpen={handleComponentSelect} />\n </MotionItem>\n ))}\n </MotionList>\n </AnimatePresence>\n ) : (\n <EmptyState\n icon={<Box className=\"size-8 text-text-secondary\" />}\n title={\n searchQuery || typeFilter !== 'all' || lifecycleFilter !== 'all'\n ? tr('component.emptyNoResults', 'No components found')\n : tr('component.emptyNoComponents', 'No components yet')\n }\n description={\n searchQuery || typeFilter !== 'all' || lifecycleFilter !== 'all'\n ? tr('component.emptyAdjustSearch', 'Try adjusting your search or filters')\n : tr(\n 'component.emptyCreate',\n 'A component is any piece of software in your system — a backend service, a frontend app, a shared library, an API. Register one to start tracking its dependencies, owner, and lifecycle stage.'\n )\n }\n action={\n !searchQuery && typeFilter === 'all' && lifecycleFilter === 'all' ? (\n <div className=\"flex items-center gap-2\">\n {canCreateComponent && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n {tr('component.createComponent', 'Create Component')}\n </button>\n )}\n <GetHelpButton prompt=\"What is a Component in VibeControls and how do I add one?\" />\n </div>\n ) : undefined\n }\n />\n )}\n\n {/* Load more */}\n {hasMore && filteredComponents.length > 0 && (\n <div className=\"flex justify-center pt-2\">\n <button\n type=\"button\"\n onClick={handleLoadMore}\n disabled={loadingMore}\n className=\"flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken-hover transition-colors disabled:opacity-50\"\n >\n {loadingMore ? tr('common.loading', 'Loading...') : tr('common.loadMore', 'Load more')}\n </button>\n </div>\n )}\n\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg text-status-success-text rounded-md shadow-lg text-sm\">\n {successMessage}\n </div>\n )}\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Component Quota Reached\"\n message=\"You've reached the maximum number of components on your current plan. Upgrade your plan or purchase an add-on to register more components.\"\n />\n\n {/* Create Form */}\n <ComponentForm\n isOpen={showCreateForm}\n onClose={() => setShowCreateForm(false)}\n onSubmit={handleCreateComponent}\n extraSection={\n <div>\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">\n {tr('component.tags', 'Tags')}\n </h3>\n <EntityTagPicker entityType=\"VIBECONTROLS_COMPONENT\" onDraftChange={setDraftTagIds} />\n </div>\n }\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ComponentsPage.js","names":[],"sources":["../../src/pages/ComponentsPage.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { Plus, Box, RefreshCw } from 'lucide-react';\nimport { ComponentCard } from '@/components/idp-components';\nimport type { ComponentCardData } from '@/components/idp-components';\nimport { ComponentForm } from '@/components/idp-components';\nimport type { ComponentFormData } from '@/components/idp-components';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useDraftEntityTags } from '@/hooks/useDraftEntityTags';\nimport {\n PageHeader,\n SearchInput,\n FilterDropdown,\n EmptyState,\n ErrorState,\n GetHelpButton,\n QuotaExhaustedDialog,\n} from '@/components/shared';\nimport { isQuotaExhaustedError } from '@/utils/quotaUtils';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { AnimatePresence } from 'framer-motion';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useListComponentsQuery, useCreateComponentMutation } from '@/generated/wspace-operations';\n\nexport function ComponentsPage() {\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canCreateComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_CREATE);\n const canReadComponent = hasPermission(VIBE_PERMISSIONS.COMPONENT_READ);\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n if (!params) return template;\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const typeOptions = [\n { value: 'all', label: tr('component.allTypes', 'All Types') },\n { value: 'SERVICE', label: tr('component.typeService', 'Service') },\n { value: 'FRONTEND', label: tr('component.typeFrontend', 'Frontend') },\n { value: 'LIBRARY', label: tr('component.typeLibrary', 'Library') },\n { value: 'API', label: tr('component.typeApi', 'API') },\n { value: 'MOBILE', label: tr('component.typeMobile', 'Mobile') },\n { value: 'DATABASE', label: tr('component.typeDatabase', 'Database') },\n { value: 'INFRASTRUCTURE', label: tr('component.typeInfrastructure', 'Infrastructure') },\n { value: 'CUSTOM', label: tr('component.typeCustom', 'Custom') },\n ];\n\n const lifecycleOptions = [\n { value: 'all', label: tr('component.allLifecycles', 'All Lifecycles') },\n { value: 'EXPERIMENTAL', label: tr('component.lifecycleExperimental', 'Experimental') },\n { value: 'ACTIVE', label: tr('component.lifecycleActive', 'Active') },\n { value: 'DEPRECATED', label: tr('component.lifecycleDeprecated', 'Deprecated') },\n { value: 'END_OF_LIFE', label: tr('component.lifecycleEndOfLife', 'End of Life') },\n ];\n\n const PAGE_SIZE = 50;\n const [searchQuery, setSearchQuery] = useState('');\n const [typeFilter, setTypeFilter] = useState('all');\n const [lifecycleFilter, setLifecycleFilter] = useState('all');\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [accumulated, setAccumulated] = useState<ComponentCardData[]>([]);\n const [loadingMore, setLoadingMore] = useState(false);\n\n const { data, loading, error, refetch, fetchMore } = useListComponentsQuery({\n variables: {\n filter: {\n type: typeFilter !== 'all' ? typeFilter : undefined,\n lifecycle: lifecycleFilter !== 'all' ? lifecycleFilter : undefined,\n search: searchQuery || undefined,\n },\n pagination: { limit: PAGE_SIZE, offset: 0 },\n },\n skip: permissionsLoading || !canReadComponent,\n fetchPolicy: 'cache-and-network',\n notifyOnNetworkStatusChange: true,\n });\n\n const [createComponent] = useCreateComponentMutation({\n refetchQueries: ['ListComponents'],\n awaitRefetchQueries: true,\n });\n const { setDraftTagIds, flushTags } = useDraftEntityTags('VIBECONTROLS_COMPONENT');\n\n const mapItems = useCallback(\n (items: ReadonlyArray<Record<string, unknown>>): ComponentCardData[] =>\n items.map((item) => ({\n id: item.id as string,\n name: item.name as string,\n description: (item.description as string) || null,\n type: item.type as ComponentCardData['type'],\n lifecycle: item.lifecycle as ComponentCardData['lifecycle'],\n version: (item.version as string) || null,\n language: (item.language as string) || null,\n framework: (item.framework as string) || null,\n tags: (item.tags as string[]) || [],\n createdAt: item.createdAt as string,\n updatedAt: item.updatedAt as string,\n })),\n []\n );\n\n useEffect(() => {\n const items = data?.vibecontrolsComponents?.items ?? [];\n setAccumulated(mapItems(items as ReadonlyArray<Record<string, unknown>>));\n }, [data?.vibecontrolsComponents?.items, mapItems]);\n\n const total = data?.vibecontrolsComponents?.total ?? 0;\n const hasMore = accumulated.length < total;\n const components = accumulated;\n const filteredComponents = accumulated;\n\n const handleLoadMore = useCallback(async () => {\n if (loadingMore || !hasMore) return;\n setLoadingMore(true);\n try {\n await fetchMore({\n variables: { pagination: { limit: PAGE_SIZE, offset: accumulated.length } },\n updateQuery: (prev, { fetchMoreResult }) => {\n if (!fetchMoreResult?.vibecontrolsComponents) return prev;\n const prevList = prev.vibecontrolsComponents;\n const nextList = fetchMoreResult.vibecontrolsComponents;\n return {\n ...prev,\n vibecontrolsComponents: {\n ...nextList,\n items: [...(prevList?.items ?? []), ...nextList.items],\n total: nextList.total,\n hasMore: nextList.hasMore,\n },\n };\n },\n });\n } finally {\n setLoadingMore(false);\n }\n }, [fetchMore, accumulated.length, loadingMore, hasMore]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (!canReadComponent)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary tracking-tight\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const handleComponentSelect = (component: ComponentCardData) => {\n navigate(`/components/${component.id}`);\n };\n\n const handleCreateComponent = async (formData: ComponentFormData) => {\n try {\n const result = await createComponent({\n variables: {\n input: {\n name: formData.name,\n description: formData.description || undefined,\n type: formData.type,\n lifecycle: formData.lifecycle,\n language: formData.language || undefined,\n framework: formData.framework || undefined,\n version: formData.version || undefined,\n ownerName: formData.ownerName || undefined,\n tags: formData.tags.length > 0 ? formData.tags : undefined,\n repositoryUrl: formData.repositoryUrl || undefined,\n documentationUrl: formData.documentationUrl || undefined,\n dependencies: formData.dependencies ?? undefined,\n sbomData: formData.sbomData ?? undefined,\n },\n },\n });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowCreateForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n if (!result.data?.createVibecontrolsComponent?.id) {\n throw new Error(tr('component.failedCreate', 'Failed to create component'));\n }\n const newComponentId = result.data.createVibecontrolsComponent.id;\n setShowCreateForm(false);\n setSuccessMessage(tr('component.createdSuccess', 'Component created successfully'));\n await flushTags(newComponentId);\n await refetch();\n setTimeout(() => setSuccessMessage(null), 3000);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowCreateForm(false);\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n if (error && components.length === 0) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <ErrorState\n title={tr('component.failedLoad', 'Failed to load components')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <PageHeader\n title={tr('component.title', 'Components')}\n description={\n total > 0\n ? tr('component.description', '{{total}} components in your catalog', {\n total: components.length,\n })\n : tr(\n 'component.descriptionEmpty',\n 'Track every service, frontend, library, and API in your system — dependencies, owners, and lifecycle in one place'\n )\n }\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 text-text-secondary hover:bg-bg-sunken rounded-button transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n title={tr('common.refresh', 'Refresh')}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {canCreateComponent && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <Plus className=\"size-4\" />\n {tr('component.createComponent', 'Create Component')}\n </button>\n )}\n </div>\n }\n />\n\n {/* Filters — SearchInput / FilterDropdown are custom components that don't\n forward rest props onto a DOM node, so the tour anchors live on\n wrapper <div>s. */}\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div data-tour=\"vibecontrols-component-search\" className=\"flex-1 sm:w-64 sm:flex-none\">\n <SearchInput\n value={searchQuery}\n onChange={setSearchQuery}\n placeholder={tr('component.searchPlaceholder', 'Search components...')}\n className=\"w-full\"\n />\n </div>\n </div>\n <div className=\"flex items-center gap-2 sm:gap-3 flex-wrap\">\n <div data-tour=\"vibecontrols-component-type-filter\">\n <FilterDropdown\n label={tr('component.filterType', 'Type')}\n value={typeFilter}\n options={typeOptions}\n onChange={setTypeFilter}\n />\n </div>\n <div data-tour=\"vibecontrols-component-lifecycle-filter\">\n <FilterDropdown\n label={tr('component.filterLifecycle', 'Lifecycle')}\n value={lifecycleFilter}\n options={lifecycleOptions}\n onChange={setLifecycleFilter}\n />\n </div>\n </div>\n </div>\n\n {/* Results count */}\n <p className=\"text-sm text-text-secondary\">\n {tr('component.showingResults', 'Showing {{filtered}} of {{total}} components', {\n filtered: filteredComponents.length,\n total,\n })}\n {loading && (\n <span className=\"ml-2 text-text-muted\">{tr('common.refreshing', '(refreshing...)')}</span>\n )}\n </p>\n\n {/* Grid */}\n {loading && components.length === 0 ? (\n <PageSkeleton variant=\"cards\" count={6} />\n ) : filteredComponents.length > 0 ? (\n <AnimatePresence mode=\"wait\">\n <MotionList\n key=\"component-grid\"\n stagger={0.04}\n className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\"\n data-tour=\"vibecontrols-component-grid\"\n >\n {filteredComponents.map((component) => (\n <MotionItem key={component.id}>\n <ComponentCard component={component} onOpen={handleComponentSelect} />\n </MotionItem>\n ))}\n </MotionList>\n </AnimatePresence>\n ) : (\n <EmptyState\n icon={<Box className=\"size-6 text-action-primary-bg\" aria-hidden=\"true\" />}\n title={\n searchQuery || typeFilter !== 'all' || lifecycleFilter !== 'all'\n ? tr('component.emptyNoResults', 'No components found')\n : tr('component.emptyNoComponents', 'No components yet')\n }\n description={\n searchQuery || typeFilter !== 'all' || lifecycleFilter !== 'all'\n ? tr('component.emptyAdjustSearch', 'Try adjusting your search or filters')\n : tr(\n 'component.emptyCreate',\n 'A component is any piece of software in your system — a backend service, a frontend app, a shared library, an API. Register one to start tracking its dependencies, owner, and lifecycle stage.'\n )\n }\n action={\n !searchQuery && typeFilter === 'all' && lifecycleFilter === 'all' ? (\n <div className=\"flex items-center gap-2\">\n {canCreateComponent && (\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(true)}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <Plus className=\"size-4\" />\n {tr('component.createComponent', 'Create Component')}\n </button>\n )}\n <GetHelpButton prompt=\"What is a Component in VibeControls and how do I add one?\" />\n </div>\n ) : undefined\n }\n />\n )}\n\n {/* Load more */}\n {hasMore && filteredComponents.length > 0 && (\n <div className=\"flex justify-center pt-2\">\n <button\n type=\"button\"\n onClick={handleLoadMore}\n disabled={loadingMore}\n className=\"flex items-center gap-2 px-4 py-2 bg-bg-sunken text-text-primary rounded-button border border-border-subtle hover:bg-bg-surface hover:border-border-strong transition-colors disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n {loadingMore ? tr('common.loading', 'Loading...') : tr('common.loadMore', 'Load more')}\n </button>\n </div>\n )}\n\n {/* Success Toast */}\n {successMessage && (\n <div className=\"fixed bottom-4 right-4 z-50 px-4 py-3 bg-status-success-bg-subtle text-status-success-text border border-status-success-border rounded-card shadow-elevation-3 text-sm\">\n {successMessage}\n </div>\n )}\n\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Component Quota Reached\"\n message=\"You've reached the maximum number of components on your current plan. Upgrade your plan or purchase an add-on to register more components.\"\n />\n\n {/* Create Form */}\n <ComponentForm\n isOpen={showCreateForm}\n onClose={() => setShowCreateForm(false)}\n onSubmit={handleCreateComponent}\n extraSection={\n <div>\n <h3 className=\"text-sm font-medium text-text-secondary mb-2\">\n {tr('component.tags', 'Tags')}\n </h3>\n <EntityTagPicker entityType=\"VIBECONTROLS_COMPONENT\" onDraftChange={setDraftTagIds} />\n </div>\n }\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
@@ -233,10 +233,10 @@ var x = [
233
233
  ]
234
234
  });
235
235
  }, w = ({ title: e, onClose: t, children: n }) => /* @__PURE__ */ y("div", {
236
- className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
236
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay p-4",
237
237
  onClick: t,
238
238
  children: /* @__PURE__ */ b("div", {
239
- className: "w-full max-w-md rounded-lg border border-border-default bg-bg-surface p-5 shadow-lg",
239
+ className: "w-full max-w-md rounded-card border border-border-subtle bg-bg-elevated p-6 shadow-[var(--shadow-elevation-4)]",
240
240
  onClick: (e) => e.stopPropagation(),
241
241
  children: [/* @__PURE__ */ y("h3", {
242
242
  className: "mb-4 text-lg font-semibold text-text-primary",