@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
@@ -100,7 +100,7 @@ var s = ({ gridColumns: s, gridRows: c, buttons: l, onExecuteButton: u, onEditBu
100
100
  onDragLeave: A,
101
101
  onDrop: (e) => j(e, t, n),
102
102
  children: C.draggingId ? /* @__PURE__ */ o("div", {
103
- className: `w-full h-full min-h-[80px] rounded-lg border-2 border-dashed flex items-center justify-center transition-all ${e ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default/30 text-text-tertiary/30"}`,
103
+ className: `w-full h-full min-h-[80px] rounded-lg border-2 border-dashed flex items-center justify-center transition-all ${e ? "border-action-primary-bg bg-[var(--color-accent-soft)] text-action-primary-bg" : "border-border-default/30 text-text-tertiary/30"}`,
104
104
  children: e && /* @__PURE__ */ o("span", {
105
105
  className: "text-xs font-medium",
106
106
  children: S("vibeDeck.dropHere", "Drop here")
@@ -108,7 +108,7 @@ var s = ({ gridColumns: s, gridRows: c, buttons: l, onExecuteButton: u, onEditBu
108
108
  }) : g ? /* @__PURE__ */ o("button", {
109
109
  type: "button",
110
110
  onClick: () => m(t, n),
111
- className: "w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-strong text-text-tertiary hover:border-border-focus hover:text-text-secondary flex items-center justify-center transition-all hover:bg-bg-secondary/50",
111
+ className: "w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-strong text-text-tertiary hover:border-border-focus hover:text-text-secondary flex items-center justify-center transition-all hover:bg-bg-sunken",
112
112
  children: /* @__PURE__ */ o(a, { size: 18 })
113
113
  }) : /* @__PURE__ */ o("div", { className: "w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-default" })
114
114
  }, r));
@@ -1 +1 @@
1
- {"version":3,"file":"VibeDeckGrid.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckGrid.tsx"],"sourcesContent":["import { type FC, type ReactElement, useState, useCallback, useMemo } from 'react';\nimport { Plus } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { VibeDeckButtonTile } from './VibeDeckButtonTile';\n\ninterface ActionRef {\n id: string;\n name: string;\n displayName: string | null;\n actionType: string;\n command: string | null;\n script: string | null;\n webhookUrl: string | null;\n targetAgentId: string | null;\n}\n\ninterface ButtonData {\n id: string;\n label: string;\n icon: string | null;\n color: string | null;\n command: string | null;\n actionType: string;\n category: string | null;\n confirmationRequired: boolean;\n keyboardShortcut: string | null;\n targetAgentId: string | null;\n scriptInterpreter: string | null;\n webhookUrl: string | null;\n webhookMethod: string | null;\n actionId?: string | null;\n action?: ActionRef | null;\n row: number;\n column: number;\n rowSpan: number;\n colSpan: number;\n}\n\ninterface VibeDeckGridProps {\n gridColumns: number;\n gridRows: number;\n buttons: ButtonData[];\n onExecuteButton: (id: string) => void;\n onEditButton: (id: string) => void;\n onDeleteButton: (id: string) => void;\n onDropButton: (buttonId: string, targetRow: number, targetColumn: number) => void;\n onAddButton: (row: number, column: number) => void;\n executingButtonId: string | null;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n canExecute: boolean;\n /**\n * When true, the grid is in Preview mode — tile clicks execute (and route\n * through the parent's confirmation check for buttons with\n * `confirmationRequired: true`). Defaults to false so the tile behaves as a\n * static editor surface.\n */\n previewMode?: boolean;\n}\n\nexport const VibeDeckGrid: FC<VibeDeckGridProps> = ({\n gridColumns,\n gridRows,\n buttons,\n onExecuteButton,\n onEditButton,\n onDeleteButton,\n onDropButton,\n onAddButton,\n executingButtonId,\n canCreate,\n canUpdate,\n canDelete,\n canExecute,\n previewMode = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const [dragState, setDragState] = useState<{\n draggingId: string | null;\n targetKey: string | null;\n }>({ draggingId: null, targetKey: null });\n\n // Build a map of occupied cells (memoized to stabilize hook dependencies)\n const { occupiedCells, buttonAtCell } = useMemo(() => {\n const occupied = new Set<string>();\n const cellMap = new Map<string, ButtonData>();\n for (const btn of buttons) {\n for (let r = btn.row; r < btn.row + btn.rowSpan; r++) {\n for (let c = btn.column; c < btn.column + btn.colSpan; c++) {\n occupied.add(`${r},${c}`);\n }\n }\n cellMap.set(`${btn.row},${btn.column}`, btn);\n }\n return { occupiedCells: occupied, buttonAtCell: cellMap };\n }, [buttons]);\n\n const handleDragStart = useCallback((e: React.DragEvent, buttonId: string) => {\n e.dataTransfer.setData('text/plain', buttonId);\n e.dataTransfer.effectAllowed = 'move';\n setDragState({ draggingId: buttonId, targetKey: null });\n }, []);\n\n const isDropValid = useCallback(\n (targetRow: number, targetCol: number) => {\n if (!dragState.draggingId) return false;\n const btn = buttons.find((b) => b.id === dragState.draggingId);\n if (!btn) return false;\n // Check grid boundary\n if (targetRow + btn.rowSpan > gridRows || targetCol + btn.colSpan > gridColumns) return false;\n // Check collision with other buttons\n for (let r = targetRow; r < targetRow + btn.rowSpan; r++) {\n for (let c = targetCol; c < targetCol + btn.colSpan; c++) {\n if (occupiedCells.has(`${r},${c}`)) {\n // Allow overlap with the dragged button's own current footprint\n const isOwnCell =\n r >= btn.row &&\n r < btn.row + btn.rowSpan &&\n c >= btn.column &&\n c < btn.column + btn.colSpan;\n if (!isOwnCell) return false;\n }\n }\n }\n return true;\n },\n [dragState.draggingId, buttons, gridRows, gridColumns, occupiedCells]\n );\n\n const handleDragOver = useCallback(\n (e: React.DragEvent, key: string, row: number, col: number) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (isDropValid(row, col)) {\n setDragState((prev) => ({ ...prev, targetKey: key }));\n } else {\n setDragState((prev) => ({ ...prev, targetKey: null }));\n }\n },\n [isDropValid]\n );\n\n const handleDragLeave = useCallback(() => {\n setDragState((prev) => ({ ...prev, targetKey: null }));\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent, row: number, col: number) => {\n e.preventDefault();\n const buttonId = e.dataTransfer.getData('text/plain');\n setDragState({ draggingId: null, targetKey: null });\n if (buttonId && isDropValid(row, col)) {\n onDropButton(buttonId, row, col);\n }\n },\n [onDropButton, isDropValid]\n );\n\n const handleDragEnd = useCallback(() => {\n setDragState({ draggingId: null, targetKey: null });\n }, []);\n\n // Build grid cells\n const cells: ReactElement[] = [];\n for (let row = 0; row < gridRows; row++) {\n for (let col = 0; col < gridColumns; col++) {\n const key = `${row},${col}`;\n const button = buttonAtCell.get(key);\n\n if (button) {\n const isDragging = dragState.draggingId === button.id;\n cells.push(\n <div\n key={key}\n style={{\n gridRow: `${row + 1} / span ${button.rowSpan}`,\n gridColumn: `${col + 1} / span ${button.colSpan}`,\n }}\n draggable={canUpdate}\n onDragStart={(e) => handleDragStart(e, button.id)}\n onDragEnd={handleDragEnd}\n className={`${isDragging ? 'opacity-40' : ''} ${canUpdate ? 'cursor-grab active:cursor-grabbing' : ''}`}\n >\n <VibeDeckButtonTile\n button={button}\n onExecute={onExecuteButton}\n onEdit={onEditButton}\n onDelete={onDeleteButton}\n canUpdate={canUpdate}\n canDelete={canDelete}\n canExecute={canExecute}\n executing={executingButtonId === button.id}\n previewMode={previewMode}\n />\n </div>\n );\n } else if (!occupiedCells.has(key)) {\n const isDropTarget = dragState.draggingId && dragState.targetKey === key;\n cells.push(\n <div\n key={key}\n style={{ gridRow: row + 1, gridColumn: col + 1 }}\n onDragOver={(e) => handleDragOver(e, key, row, col)}\n onDragLeave={handleDragLeave}\n onDrop={(e) => handleDrop(e, row, col)}\n >\n {dragState.draggingId ? (\n <div\n className={`w-full h-full min-h-[80px] rounded-lg border-2 border-dashed flex items-center justify-center transition-all ${\n isDropTarget\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default/30 text-text-tertiary/30'\n }`}\n >\n {isDropTarget && (\n <span className=\"text-xs font-medium\">\n {tr('vibeDeck.dropHere', 'Drop here')}\n </span>\n )}\n </div>\n ) : canCreate ? (\n <button\n type=\"button\"\n onClick={() => onAddButton(row, col)}\n className=\"w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-strong text-text-tertiary hover:border-border-focus hover:text-text-secondary flex items-center justify-center transition-all hover:bg-bg-secondary/50\"\n >\n <Plus size={18} />\n </button>\n ) : (\n <div className=\"w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-default\" />\n )}\n </div>\n );\n }\n }\n }\n\n return (\n <div\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns: `repeat(${gridColumns}, 1fr)`,\n gridTemplateRows: `repeat(${gridRows}, auto)`,\n }}\n >\n {cells}\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeDeckGrid.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckGrid.tsx"],"sourcesContent":["import { type FC, type ReactElement, useState, useCallback, useMemo } from 'react';\nimport { Plus } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { VibeDeckButtonTile } from './VibeDeckButtonTile';\n\ninterface ActionRef {\n id: string;\n name: string;\n displayName: string | null;\n actionType: string;\n command: string | null;\n script: string | null;\n webhookUrl: string | null;\n targetAgentId: string | null;\n}\n\ninterface ButtonData {\n id: string;\n label: string;\n icon: string | null;\n color: string | null;\n command: string | null;\n actionType: string;\n category: string | null;\n confirmationRequired: boolean;\n keyboardShortcut: string | null;\n targetAgentId: string | null;\n scriptInterpreter: string | null;\n webhookUrl: string | null;\n webhookMethod: string | null;\n actionId?: string | null;\n action?: ActionRef | null;\n row: number;\n column: number;\n rowSpan: number;\n colSpan: number;\n}\n\ninterface VibeDeckGridProps {\n gridColumns: number;\n gridRows: number;\n buttons: ButtonData[];\n onExecuteButton: (id: string) => void;\n onEditButton: (id: string) => void;\n onDeleteButton: (id: string) => void;\n onDropButton: (buttonId: string, targetRow: number, targetColumn: number) => void;\n onAddButton: (row: number, column: number) => void;\n executingButtonId: string | null;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n canExecute: boolean;\n /**\n * When true, the grid is in Preview mode — tile clicks execute (and route\n * through the parent's confirmation check for buttons with\n * `confirmationRequired: true`). Defaults to false so the tile behaves as a\n * static editor surface.\n */\n previewMode?: boolean;\n}\n\nexport const VibeDeckGrid: FC<VibeDeckGridProps> = ({\n gridColumns,\n gridRows,\n buttons,\n onExecuteButton,\n onEditButton,\n onDeleteButton,\n onDropButton,\n onAddButton,\n executingButtonId,\n canCreate,\n canUpdate,\n canDelete,\n canExecute,\n previewMode = false,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const [dragState, setDragState] = useState<{\n draggingId: string | null;\n targetKey: string | null;\n }>({ draggingId: null, targetKey: null });\n\n // Build a map of occupied cells (memoized to stabilize hook dependencies)\n const { occupiedCells, buttonAtCell } = useMemo(() => {\n const occupied = new Set<string>();\n const cellMap = new Map<string, ButtonData>();\n for (const btn of buttons) {\n for (let r = btn.row; r < btn.row + btn.rowSpan; r++) {\n for (let c = btn.column; c < btn.column + btn.colSpan; c++) {\n occupied.add(`${r},${c}`);\n }\n }\n cellMap.set(`${btn.row},${btn.column}`, btn);\n }\n return { occupiedCells: occupied, buttonAtCell: cellMap };\n }, [buttons]);\n\n const handleDragStart = useCallback((e: React.DragEvent, buttonId: string) => {\n e.dataTransfer.setData('text/plain', buttonId);\n e.dataTransfer.effectAllowed = 'move';\n setDragState({ draggingId: buttonId, targetKey: null });\n }, []);\n\n const isDropValid = useCallback(\n (targetRow: number, targetCol: number) => {\n if (!dragState.draggingId) return false;\n const btn = buttons.find((b) => b.id === dragState.draggingId);\n if (!btn) return false;\n // Check grid boundary\n if (targetRow + btn.rowSpan > gridRows || targetCol + btn.colSpan > gridColumns) return false;\n // Check collision with other buttons\n for (let r = targetRow; r < targetRow + btn.rowSpan; r++) {\n for (let c = targetCol; c < targetCol + btn.colSpan; c++) {\n if (occupiedCells.has(`${r},${c}`)) {\n // Allow overlap with the dragged button's own current footprint\n const isOwnCell =\n r >= btn.row &&\n r < btn.row + btn.rowSpan &&\n c >= btn.column &&\n c < btn.column + btn.colSpan;\n if (!isOwnCell) return false;\n }\n }\n }\n return true;\n },\n [dragState.draggingId, buttons, gridRows, gridColumns, occupiedCells]\n );\n\n const handleDragOver = useCallback(\n (e: React.DragEvent, key: string, row: number, col: number) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (isDropValid(row, col)) {\n setDragState((prev) => ({ ...prev, targetKey: key }));\n } else {\n setDragState((prev) => ({ ...prev, targetKey: null }));\n }\n },\n [isDropValid]\n );\n\n const handleDragLeave = useCallback(() => {\n setDragState((prev) => ({ ...prev, targetKey: null }));\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent, row: number, col: number) => {\n e.preventDefault();\n const buttonId = e.dataTransfer.getData('text/plain');\n setDragState({ draggingId: null, targetKey: null });\n if (buttonId && isDropValid(row, col)) {\n onDropButton(buttonId, row, col);\n }\n },\n [onDropButton, isDropValid]\n );\n\n const handleDragEnd = useCallback(() => {\n setDragState({ draggingId: null, targetKey: null });\n }, []);\n\n // Build grid cells\n const cells: ReactElement[] = [];\n for (let row = 0; row < gridRows; row++) {\n for (let col = 0; col < gridColumns; col++) {\n const key = `${row},${col}`;\n const button = buttonAtCell.get(key);\n\n if (button) {\n const isDragging = dragState.draggingId === button.id;\n cells.push(\n <div\n key={key}\n style={{\n gridRow: `${row + 1} / span ${button.rowSpan}`,\n gridColumn: `${col + 1} / span ${button.colSpan}`,\n }}\n draggable={canUpdate}\n onDragStart={(e) => handleDragStart(e, button.id)}\n onDragEnd={handleDragEnd}\n className={`${isDragging ? 'opacity-40' : ''} ${canUpdate ? 'cursor-grab active:cursor-grabbing' : ''}`}\n >\n <VibeDeckButtonTile\n button={button}\n onExecute={onExecuteButton}\n onEdit={onEditButton}\n onDelete={onDeleteButton}\n canUpdate={canUpdate}\n canDelete={canDelete}\n canExecute={canExecute}\n executing={executingButtonId === button.id}\n previewMode={previewMode}\n />\n </div>\n );\n } else if (!occupiedCells.has(key)) {\n const isDropTarget = dragState.draggingId && dragState.targetKey === key;\n cells.push(\n <div\n key={key}\n style={{ gridRow: row + 1, gridColumn: col + 1 }}\n onDragOver={(e) => handleDragOver(e, key, row, col)}\n onDragLeave={handleDragLeave}\n onDrop={(e) => handleDrop(e, row, col)}\n >\n {dragState.draggingId ? (\n <div\n className={`w-full h-full min-h-[80px] rounded-lg border-2 border-dashed flex items-center justify-center transition-all ${\n isDropTarget\n ? 'border-action-primary-bg bg-[var(--color-accent-soft)] text-action-primary-bg'\n : 'border-border-default/30 text-text-tertiary/30'\n }`}\n >\n {isDropTarget && (\n <span className=\"text-xs font-medium\">\n {tr('vibeDeck.dropHere', 'Drop here')}\n </span>\n )}\n </div>\n ) : canCreate ? (\n <button\n type=\"button\"\n onClick={() => onAddButton(row, col)}\n className=\"w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-strong text-text-tertiary hover:border-border-focus hover:text-text-secondary flex items-center justify-center transition-all hover:bg-bg-sunken\"\n >\n <Plus size={18} />\n </button>\n ) : (\n <div className=\"w-full h-full min-h-[80px] rounded-lg border-2 border-dashed border-border-default\" />\n )}\n </div>\n );\n }\n }\n }\n\n return (\n <div\n className=\"grid gap-3\"\n style={{\n gridTemplateColumns: `repeat(${gridColumns}, 1fr)`,\n gridTemplateRows: `repeat(${gridRows}, auto)`,\n }}\n >\n {cells}\n </div>\n );\n};\n"],"mappings":"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"}
@@ -68,10 +68,10 @@ var x = [
68
68
  }
69
69
  };
70
70
  return /* @__PURE__ */ y("div", {
71
- className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",
71
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay p-4",
72
72
  onClick: T,
73
73
  children: /* @__PURE__ */ b("div", {
74
- className: "w-full max-w-lg rounded-lg border border-border-default bg-bg-surface p-5 shadow-lg",
74
+ className: "w-full max-w-lg rounded-card border border-border-subtle bg-bg-elevated p-6 shadow-[var(--shadow-elevation-4)]",
75
75
  onClick: (e) => e.stopPropagation(),
76
76
  children: [
77
77
  /* @__PURE__ */ b("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"VibeDeckPublicLinkPanel.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckPublicLinkPanel.tsx"],"sourcesContent":["import type { FC, FormEvent, ReactNode } from 'react';\nimport { useState } from 'react';\nimport { Link2, Play, Eye, Lock, Copy, Trash2, Plus, X, Check } from 'lucide-react';\n\nimport { LoadingState, ErrorState } from '@/components/shared';\nimport { notify } from '@/lib/toast';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useListVibeDeckShareLinksQuery,\n useCreateVibeDeckShareLinkMutation,\n useRevokeVibeDeckShareLinkMutation,\n type VibeDeckShareLinkFieldsFragment,\n} from '@/generated/wspace-operations';\nimport { VibeDeckSharePermission } from '@/generated/wspace-types';\n\ninterface VibeDeckPublicLinkPanelProps {\n vibeDeckId: string;\n vibeDeckName: string;\n onClose: () => void;\n}\n\nconst EXPIRY_OPTIONS = [\n { label: '4 hours', hours: 4 },\n { label: '24 hours', hours: 24 },\n { label: '7 days', hours: 168 },\n { label: 'No expiry', hours: 0 },\n];\n\n/**\n * VibeDeckPublicLinkPanel — create and manage public links to a VibeDeck with explicit\n * **execution** control. Unlike the generic member-share dialog, this exposes the deck story's\n * promised controls: \"Public access + Allow execution + optional password + expiry + usage limit\".\n * Links carry a `VibeDeckSharePermission` (VIEW or EXECUTE); the URL points at the live\n * `deck/:token` page (not an auth'd accept page). Backed by the existing `createVibeDeckShareLink`\n * mutation — no backend change.\n */\nexport const VibeDeckPublicLinkPanel: FC<VibeDeckPublicLinkPanelProps> = ({\n vibeDeckId,\n vibeDeckName,\n onClose,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const { data, loading, error, refetch } = useListVibeDeckShareLinksQuery({\n variables: { vibeDeckId },\n fetchPolicy: 'cache-and-network',\n });\n const [createLink, { loading: creating }] = useCreateVibeDeckShareLinkMutation();\n const [revokeLink] = useRevokeVibeDeckShareLinkMutation();\n\n const [allowExecution, setAllowExecution] = useState(true);\n const [expiryHours, setExpiryHours] = useState(4);\n const [password, setPassword] = useState('');\n const [maxUses, setMaxUses] = useState('');\n const [copiedId, setCopiedId] = useState<string | null>(null);\n\n const links: VibeDeckShareLinkFieldsFragment[] = data?.vibeDeckShareLinks ?? [];\n const activeLinks = links.filter((l) => l.status === 'ACTIVE');\n\n const copy = async (url: string, id: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(url);\n setCopiedId(id);\n notify.success(tr('deckLink.copied', 'Link copied'));\n window.setTimeout(() => setCopiedId(null), 1500);\n } catch {\n notify.error(tr('deckLink.copyFailed', 'Could not copy — copy it manually'), url);\n }\n };\n\n const handleCreate = async (e: FormEvent): Promise<void> => {\n e.preventDefault();\n const parsedMax = maxUses.trim() ? Number.parseInt(maxUses.trim(), 10) : null;\n if (parsedMax !== null && (!Number.isFinite(parsedMax) || parsedMax < 1)) {\n notify.error(tr('deckLink.badMax', 'Max uses must be a positive number'));\n return;\n }\n try {\n const res = await createLink({\n variables: {\n input: {\n vibeDeckId,\n permission: allowExecution\n ? VibeDeckSharePermission.Execute\n : VibeDeckSharePermission.View,\n expiresInHours: expiryHours > 0 ? expiryHours : null,\n password: password.trim() ? password.trim() : null,\n maxUses: parsedMax,\n },\n },\n });\n await refetch();\n const url = res.data?.createVibeDeckShareLink.shareUrl;\n if (url) await copy(url, res.data?.createVibeDeckShareLink.id ?? 'new');\n notify.success(\n tr('deckLink.created', 'Public link created'),\n allowExecution\n ? tr('deckLink.createdExec', 'Anyone with the link can run the deck tiles')\n : tr('deckLink.createdView', 'Anyone with the link can view the deck')\n );\n setPassword('');\n setMaxUses('');\n } catch (err) {\n notify.error(tr('deckLink.createFailed', 'Could not create link'), (err as Error).message);\n }\n };\n\n const handleRevoke = async (id: string): Promise<void> => {\n try {\n await revokeLink({ variables: { id } });\n await refetch();\n notify.success(tr('deckLink.revoked', 'Link revoked — it no longer works'));\n } catch (err) {\n notify.error(tr('deckLink.revokeFailed', 'Could not revoke'), (err as Error).message);\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4\"\n onClick={onClose}\n >\n <div\n className=\"w-full max-w-lg rounded-lg border border-border-default bg-bg-surface p-5 shadow-lg\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"mb-4 flex items-start justify-between\">\n <div>\n <h3 className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <Link2 className=\"size-5\" />\n {tr('deckLink.title', 'Public links')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">{vibeDeckName}</p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 text-text-tertiary hover:text-text-primary\"\n aria-label={tr('common.close', 'Close')}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Existing links */}\n <div className=\"mb-4 space-y-2\">\n {loading && links.length === 0 ? (\n <LoadingState />\n ) : error ? (\n <ErrorState message={error.message} onRetry={() => void refetch()} />\n ) : activeLinks.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {tr('deckLink.none', 'No public links yet. Create one below.')}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {activeLinks.map((l) => (\n <li\n key={l.id}\n className=\"flex items-center gap-2 rounded-md border border-border-default px-3 py-2\"\n >\n <Badge>\n {l.permission === VibeDeckSharePermission.Execute ? (\n <>\n <Play className=\"size-3\" /> {tr('deckLink.execute', 'Execute')}\n </>\n ) : (\n <>\n <Eye className=\"size-3\" /> {tr('deckLink.view', 'View')}\n </>\n )}\n </Badge>\n {l.hasPassword && (\n <Lock className=\"size-3.5 text-text-tertiary\" aria-label=\"password\" />\n )}\n <span className=\"flex-1 truncate font-mono text-xs text-text-secondary\">\n {l.shareUrl}\n </span>\n <span className=\"shrink-0 text-xs text-text-tertiary\">\n {l.useCount}\n {l.maxUses ? `/${l.maxUses}` : ''} {tr('deckLink.uses', 'uses')}\n </span>\n <button\n type=\"button\"\n onClick={() => void copy(l.shareUrl, l.id)}\n className=\"p-1 text-text-secondary hover:text-text-primary\"\n aria-label={tr('common.copy', 'Copy')}\n >\n {copiedId === l.id ? (\n <Check className=\"size-4 text-status-success-text\" />\n ) : (\n <Copy className=\"size-4\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleRevoke(l.id)}\n className=\"p-1 text-text-secondary hover:text-action-danger-text\"\n aria-label={tr('common.revoke', 'Revoke')}\n >\n <Trash2 className=\"size-4\" />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n {/* Create form */}\n <form\n onSubmit={(e) => void handleCreate(e)}\n className=\"space-y-3 border-t border-border-default pt-4\"\n >\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={allowExecution}\n onChange={(e) => setAllowExecution(e.target.checked)}\n className=\"rounded border-border-default\"\n />\n <Play className=\"size-3.5\" />\n {tr('deckLink.allowExecution', 'Allow execution (anyone with the link can run tiles)')}\n </label>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <label className=\"flex-1\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.expiry', 'Expires')}\n </span>\n <select\n value={expiryHours}\n onChange={(e) => setExpiryHours(Number(e.target.value))}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n {EXPIRY_OPTIONS.map((o) => (\n <option key={o.label} value={o.hours}>\n {o.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex-1\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.maxUses', 'Max uses (optional)')}\n </span>\n <input\n value={maxUses}\n onChange={(e) => setMaxUses(e.target.value)}\n inputMode=\"numeric\"\n placeholder={tr('deckLink.unlimited', 'unlimited')}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n </div>\n <label className=\"block\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.password', 'Password (optional)')}\n </span>\n <input\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n type=\"password\"\n autoComplete=\"new-password\"\n placeholder={tr('deckLink.noPassword', 'no password')}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n <div className=\"flex justify-end\">\n <button\n type=\"submit\"\n disabled={creating}\n className=\"flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n <Plus className=\"size-4\" />\n {tr('deckLink.create', 'Create public link')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nconst Badge: FC<{ children: ReactNode }> = ({ children }) => (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-primary\">\n {children}\n </span>\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeDeckPublicLinkPanel.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckPublicLinkPanel.tsx"],"sourcesContent":["import type { FC, FormEvent, ReactNode } from 'react';\nimport { useState } from 'react';\nimport { Link2, Play, Eye, Lock, Copy, Trash2, Plus, X, Check } from 'lucide-react';\n\nimport { LoadingState, ErrorState } from '@/components/shared';\nimport { notify } from '@/lib/toast';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useListVibeDeckShareLinksQuery,\n useCreateVibeDeckShareLinkMutation,\n useRevokeVibeDeckShareLinkMutation,\n type VibeDeckShareLinkFieldsFragment,\n} from '@/generated/wspace-operations';\nimport { VibeDeckSharePermission } from '@/generated/wspace-types';\n\ninterface VibeDeckPublicLinkPanelProps {\n vibeDeckId: string;\n vibeDeckName: string;\n onClose: () => void;\n}\n\nconst EXPIRY_OPTIONS = [\n { label: '4 hours', hours: 4 },\n { label: '24 hours', hours: 24 },\n { label: '7 days', hours: 168 },\n { label: 'No expiry', hours: 0 },\n];\n\n/**\n * VibeDeckPublicLinkPanel — create and manage public links to a VibeDeck with explicit\n * **execution** control. Unlike the generic member-share dialog, this exposes the deck story's\n * promised controls: \"Public access + Allow execution + optional password + expiry + usage limit\".\n * Links carry a `VibeDeckSharePermission` (VIEW or EXECUTE); the URL points at the live\n * `deck/:token` page (not an auth'd accept page). Backed by the existing `createVibeDeckShareLink`\n * mutation — no backend change.\n */\nexport const VibeDeckPublicLinkPanel: FC<VibeDeckPublicLinkPanelProps> = ({\n vibeDeckId,\n vibeDeckName,\n onClose,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const { data, loading, error, refetch } = useListVibeDeckShareLinksQuery({\n variables: { vibeDeckId },\n fetchPolicy: 'cache-and-network',\n });\n const [createLink, { loading: creating }] = useCreateVibeDeckShareLinkMutation();\n const [revokeLink] = useRevokeVibeDeckShareLinkMutation();\n\n const [allowExecution, setAllowExecution] = useState(true);\n const [expiryHours, setExpiryHours] = useState(4);\n const [password, setPassword] = useState('');\n const [maxUses, setMaxUses] = useState('');\n const [copiedId, setCopiedId] = useState<string | null>(null);\n\n const links: VibeDeckShareLinkFieldsFragment[] = data?.vibeDeckShareLinks ?? [];\n const activeLinks = links.filter((l) => l.status === 'ACTIVE');\n\n const copy = async (url: string, id: string): Promise<void> => {\n try {\n await navigator.clipboard.writeText(url);\n setCopiedId(id);\n notify.success(tr('deckLink.copied', 'Link copied'));\n window.setTimeout(() => setCopiedId(null), 1500);\n } catch {\n notify.error(tr('deckLink.copyFailed', 'Could not copy — copy it manually'), url);\n }\n };\n\n const handleCreate = async (e: FormEvent): Promise<void> => {\n e.preventDefault();\n const parsedMax = maxUses.trim() ? Number.parseInt(maxUses.trim(), 10) : null;\n if (parsedMax !== null && (!Number.isFinite(parsedMax) || parsedMax < 1)) {\n notify.error(tr('deckLink.badMax', 'Max uses must be a positive number'));\n return;\n }\n try {\n const res = await createLink({\n variables: {\n input: {\n vibeDeckId,\n permission: allowExecution\n ? VibeDeckSharePermission.Execute\n : VibeDeckSharePermission.View,\n expiresInHours: expiryHours > 0 ? expiryHours : null,\n password: password.trim() ? password.trim() : null,\n maxUses: parsedMax,\n },\n },\n });\n await refetch();\n const url = res.data?.createVibeDeckShareLink.shareUrl;\n if (url) await copy(url, res.data?.createVibeDeckShareLink.id ?? 'new');\n notify.success(\n tr('deckLink.created', 'Public link created'),\n allowExecution\n ? tr('deckLink.createdExec', 'Anyone with the link can run the deck tiles')\n : tr('deckLink.createdView', 'Anyone with the link can view the deck')\n );\n setPassword('');\n setMaxUses('');\n } catch (err) {\n notify.error(tr('deckLink.createFailed', 'Could not create link'), (err as Error).message);\n }\n };\n\n const handleRevoke = async (id: string): Promise<void> => {\n try {\n await revokeLink({ variables: { id } });\n await refetch();\n notify.success(tr('deckLink.revoked', 'Link revoked — it no longer works'));\n } catch (err) {\n notify.error(tr('deckLink.revokeFailed', 'Could not revoke'), (err as Error).message);\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay p-4\"\n onClick={onClose}\n >\n <div\n className=\"w-full max-w-lg rounded-card border border-border-subtle bg-bg-elevated p-6 shadow-[var(--shadow-elevation-4)]\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"mb-4 flex items-start justify-between\">\n <div>\n <h3 className=\"flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <Link2 className=\"size-5\" />\n {tr('deckLink.title', 'Public links')}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">{vibeDeckName}</p>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 text-text-tertiary hover:text-text-primary\"\n aria-label={tr('common.close', 'Close')}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Existing links */}\n <div className=\"mb-4 space-y-2\">\n {loading && links.length === 0 ? (\n <LoadingState />\n ) : error ? (\n <ErrorState message={error.message} onRetry={() => void refetch()} />\n ) : activeLinks.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {tr('deckLink.none', 'No public links yet. Create one below.')}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {activeLinks.map((l) => (\n <li\n key={l.id}\n className=\"flex items-center gap-2 rounded-md border border-border-default px-3 py-2\"\n >\n <Badge>\n {l.permission === VibeDeckSharePermission.Execute ? (\n <>\n <Play className=\"size-3\" /> {tr('deckLink.execute', 'Execute')}\n </>\n ) : (\n <>\n <Eye className=\"size-3\" /> {tr('deckLink.view', 'View')}\n </>\n )}\n </Badge>\n {l.hasPassword && (\n <Lock className=\"size-3.5 text-text-tertiary\" aria-label=\"password\" />\n )}\n <span className=\"flex-1 truncate font-mono text-xs text-text-secondary\">\n {l.shareUrl}\n </span>\n <span className=\"shrink-0 text-xs text-text-tertiary\">\n {l.useCount}\n {l.maxUses ? `/${l.maxUses}` : ''} {tr('deckLink.uses', 'uses')}\n </span>\n <button\n type=\"button\"\n onClick={() => void copy(l.shareUrl, l.id)}\n className=\"p-1 text-text-secondary hover:text-text-primary\"\n aria-label={tr('common.copy', 'Copy')}\n >\n {copiedId === l.id ? (\n <Check className=\"size-4 text-status-success-text\" />\n ) : (\n <Copy className=\"size-4\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleRevoke(l.id)}\n className=\"p-1 text-text-secondary hover:text-action-danger-text\"\n aria-label={tr('common.revoke', 'Revoke')}\n >\n <Trash2 className=\"size-4\" />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n {/* Create form */}\n <form\n onSubmit={(e) => void handleCreate(e)}\n className=\"space-y-3 border-t border-border-default pt-4\"\n >\n <label className=\"flex cursor-pointer items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={allowExecution}\n onChange={(e) => setAllowExecution(e.target.checked)}\n className=\"rounded border-border-default\"\n />\n <Play className=\"size-3.5\" />\n {tr('deckLink.allowExecution', 'Allow execution (anyone with the link can run tiles)')}\n </label>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <label className=\"flex-1\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.expiry', 'Expires')}\n </span>\n <select\n value={expiryHours}\n onChange={(e) => setExpiryHours(Number(e.target.value))}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n {EXPIRY_OPTIONS.map((o) => (\n <option key={o.label} value={o.hours}>\n {o.label}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex-1\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.maxUses', 'Max uses (optional)')}\n </span>\n <input\n value={maxUses}\n onChange={(e) => setMaxUses(e.target.value)}\n inputMode=\"numeric\"\n placeholder={tr('deckLink.unlimited', 'unlimited')}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n </div>\n <label className=\"block\">\n <span className=\"text-sm text-text-secondary\">\n {tr('deckLink.password', 'Password (optional)')}\n </span>\n <input\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n type=\"password\"\n autoComplete=\"new-password\"\n placeholder={tr('deckLink.noPassword', 'no password')}\n className=\"mt-1 w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n <div className=\"flex justify-end\">\n <button\n type=\"submit\"\n disabled={creating}\n className=\"flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n <Plus className=\"size-4\" />\n {tr('deckLink.create', 'Create public link')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nconst Badge: FC<{ children: ReactNode }> = ({ children }) => (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-primary\">\n {children}\n </span>\n);\n"],"mappings":"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"}
@@ -34,7 +34,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
34
34
  /* @__PURE__ */ p("button", {
35
35
  type: "button",
36
36
  onClick: () => y(e.id),
37
- className: `px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${n ? "bg-action-primary-bg text-action-primary-text" : v.has(e.id) ? "bg-action-primary-bg/10 text-text-primary border border-action-primary-bg/30" : "bg-bg-secondary text-text-secondary hover:bg-bg-tertiary hover:text-text-primary"}`,
37
+ className: `px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${n ? "bg-action-primary-bg text-action-primary-text" : v.has(e.id) ? "bg-[var(--color-accent-soft)] text-text-primary border border-[var(--color-accent-soft)]" : "bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
38
38
  children: /* @__PURE__ */ m("span", {
39
39
  className: "flex items-center gap-1.5",
40
40
  children: [e.isDefault && /* @__PURE__ */ p(u, {
@@ -55,7 +55,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
55
55
  }), M(e.id);
56
56
  }
57
57
  },
58
- className: `p-1 rounded transition-colors ${r ? "bg-bg-tertiary text-text-primary" : "text-text-tertiary hover:text-text-primary hover:bg-bg-tertiary"}`,
58
+ className: `p-1 rounded transition-colors ${r ? "bg-bg-sunken text-text-primary" : "text-text-tertiary hover:text-text-primary hover:bg-bg-sunken"}`,
59
59
  title: "Deck actions",
60
60
  children: /* @__PURE__ */ p(a, { size: 14 })
61
61
  })
@@ -64,7 +64,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
64
64
  }), D && /* @__PURE__ */ m("button", {
65
65
  type: "button",
66
66
  onClick: x,
67
- className: "flex items-center gap-1 px-3 py-1.5 rounded-lg text-sm text-text-tertiary hover:text-text-primary hover:bg-bg-tertiary transition-colors shrink-0 border border-dashed border-border-default",
67
+ className: "flex items-center gap-1 px-3 py-1.5 rounded-lg text-sm text-text-tertiary hover:text-text-primary hover:bg-bg-sunken transition-colors shrink-0 border border-dashed border-border-default",
68
68
  children: [/* @__PURE__ */ p(s, { size: 14 }), A("vibecontrols.vibedeck.switcher.newDeck", "New Deck")]
69
69
  })]
70
70
  }), j && N && L && h(/* @__PURE__ */ m("div", {
@@ -82,7 +82,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
82
82
  onClick: () => {
83
83
  S(L.id), I();
84
84
  },
85
- className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary",
85
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
86
86
  children: [/* @__PURE__ */ p(u, { size: 14 }), A("vibecontrols.vibedeck.switcher.setDefault", "Set as default")]
87
87
  }),
88
88
  O && /* @__PURE__ */ m("button", {
@@ -90,7 +90,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
90
90
  onClick: () => {
91
91
  T(L.id), I();
92
92
  },
93
- className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary",
93
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
94
94
  children: [/* @__PURE__ */ p(c, { size: 14 }), A("vibecontrols.vibedeck.switcher.editDeck", "Edit deck")]
95
95
  }),
96
96
  E && /* @__PURE__ */ m("button", {
@@ -98,7 +98,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
98
98
  onClick: () => {
99
99
  E(L.id), I();
100
100
  },
101
- className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary",
101
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
102
102
  children: [/* @__PURE__ */ p(l, { size: 14 }), A("vibecontrols.vibedeck.switcher.share", "Share")]
103
103
  }),
104
104
  D && /* @__PURE__ */ m("button", {
@@ -106,7 +106,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
106
106
  onClick: () => {
107
107
  C(L.id), I();
108
108
  },
109
- className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary",
109
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
110
110
  children: [/* @__PURE__ */ p(o, { size: 14 }), A("vibecontrols.vibedeck.switcher.duplicate", "Duplicate")]
111
111
  }),
112
112
  k && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p("div", { className: "border-t border-border-default my-1" }), /* @__PURE__ */ m("button", {
@@ -114,7 +114,7 @@ var g = ({ decks: g, activeDeckId: _, selectedDeckIds: v, onSelectDeck: y, onTog
114
114
  onClick: () => {
115
115
  w(L.id), I();
116
116
  },
117
- className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-status-error-text hover:bg-bg-tertiary",
117
+ className: "flex items-center gap-2 w-full px-3 py-1.5 text-sm text-status-error-text hover:bg-bg-sunken",
118
118
  children: [/* @__PURE__ */ p(d, { size: 14 }), A("vibecontrols.vibedeck.switcher.delete", "Delete")]
119
119
  })] })
120
120
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"VibeDeckSwitcher.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckSwitcher.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Plus, Star, Copy, Trash2, Settings, ChevronDown, Share2 } from 'lucide-react';\nimport { SelectionCheckbox } from '../shared/SelectionCheckbox';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DeckSummary {\n id: string;\n name: string;\n icon: string | null;\n colorTheme: string | null;\n isDefault: boolean;\n}\n\ninterface VibeDeckSwitcherProps {\n decks: DeckSummary[];\n activeDeckId: string | null;\n selectedDeckIds: Set<string>;\n onSelectDeck: (id: string) => void;\n onToggleSelectDeck: (id: string, checked: boolean) => void;\n onCreateDeck: () => void;\n onSetDefault: (id: string) => void;\n onDuplicate: (id: string) => void;\n onDelete: (id: string) => void;\n onEdit: (id: string) => void;\n onShare?: (id: string) => void;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n}\n\nexport const VibeDeckSwitcher: FC<VibeDeckSwitcherProps> = ({\n decks,\n activeDeckId,\n selectedDeckIds,\n onSelectDeck,\n onToggleSelectDeck,\n onCreateDeck,\n onSetDefault,\n onDuplicate,\n onDelete,\n onEdit,\n onShare,\n canCreate,\n canUpdate,\n canDelete,\n}) => {\n const tr = useTr();\n const [dropdownDeckId, setDropdownDeckId] = useState<string | null>(null);\n const [dropdownPos, setDropdownPos] = useState<{ top: number; left: number } | null>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownDeckId(null);\n setDropdownPos(null);\n }\n };\n if (dropdownDeckId) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [dropdownDeckId]);\n\n const closeDropdown = () => {\n setDropdownDeckId(null);\n setDropdownPos(null);\n };\n\n const activeDeck = dropdownDeckId ? decks.find((d) => d.id === dropdownDeckId) : null;\n\n return (\n <>\n <div className=\"flex items-center gap-2 overflow-x-auto pb-1\">\n {decks.map((deck) => {\n const isActive = deck.id === activeDeckId;\n const showDropdown = dropdownDeckId === deck.id;\n\n return (\n <div key={deck.id} className=\"flex items-center gap-1 shrink-0\">\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedDeckIds.has(deck.id)}\n onChange={(checked) => onToggleSelectDeck(deck.id, checked)}\n ariaLabel={`Select deck ${deck.name}`}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => onSelectDeck(deck.id)}\n className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${\n isActive\n ? 'bg-action-primary-bg text-action-primary-text'\n : selectedDeckIds.has(deck.id)\n ? 'bg-action-primary-bg/10 text-text-primary border border-action-primary-bg/30'\n : 'bg-bg-secondary text-text-secondary hover:bg-bg-tertiary hover:text-text-primary'\n }`}\n >\n <span className=\"flex items-center gap-1.5\">\n {deck.isDefault && (\n <Star size={12} className=\"fill-current text-status-warning-text\" />\n )}\n {deck.name}\n </span>\n </button>\n\n {isActive && (canUpdate || canDelete || canCreate) && (\n <button\n type=\"button\"\n onClick={(e) => {\n if (showDropdown) {\n closeDropdown();\n } else {\n const rect = e.currentTarget.getBoundingClientRect();\n setDropdownPos({ top: rect.bottom + 4, left: rect.left });\n setDropdownDeckId(deck.id);\n }\n }}\n className={`p-1 rounded transition-colors ${\n showDropdown\n ? 'bg-bg-tertiary text-text-primary'\n : 'text-text-tertiary hover:text-text-primary hover:bg-bg-tertiary'\n }`}\n title=\"Deck actions\"\n >\n <ChevronDown size={14} />\n </button>\n )}\n </div>\n );\n })}\n {canCreate && (\n <button\n type=\"button\"\n onClick={onCreateDeck}\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-lg text-sm text-text-tertiary hover:text-text-primary hover:bg-bg-tertiary transition-colors shrink-0 border border-dashed border-border-default\"\n >\n <Plus size={14} />\n {tr('vibecontrols.vibedeck.switcher.newDeck', 'New Deck')}\n </button>\n )}\n </div>\n\n {/* Dropdown rendered via portal to escape Framer Motion CSS transforms */}\n {dropdownDeckId &&\n dropdownPos &&\n activeDeck &&\n createPortal(\n <div\n ref={dropdownRef}\n style={{\n position: 'fixed',\n top: dropdownPos.top,\n left: dropdownPos.left,\n zIndex: 9999,\n }}\n className=\"bg-bg-elevated border border-border-default rounded-lg shadow-lg py-1 min-w-[160px]\"\n >\n {canUpdate && !activeDeck.isDefault && (\n <button\n type=\"button\"\n onClick={() => {\n onSetDefault(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary\"\n >\n <Star size={14} />\n {tr('vibecontrols.vibedeck.switcher.setDefault', 'Set as default')}\n </button>\n )}\n {canUpdate && (\n <button\n type=\"button\"\n onClick={() => {\n onEdit(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary\"\n >\n <Settings size={14} />\n {tr('vibecontrols.vibedeck.switcher.editDeck', 'Edit deck')}\n </button>\n )}\n {onShare && (\n <button\n type=\"button\"\n onClick={() => {\n onShare(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary\"\n >\n <Share2 size={14} />\n {tr('vibecontrols.vibedeck.switcher.share', 'Share')}\n </button>\n )}\n {canCreate && (\n <button\n type=\"button\"\n onClick={() => {\n onDuplicate(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-tertiary hover:text-text-primary\"\n >\n <Copy size={14} />\n {tr('vibecontrols.vibedeck.switcher.duplicate', 'Duplicate')}\n </button>\n )}\n {canDelete && (\n <>\n <div className=\"border-t border-border-default my-1\" />\n <button\n type=\"button\"\n onClick={() => {\n onDelete(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-status-error-text hover:bg-bg-tertiary\"\n >\n <Trash2 size={14} />\n {tr('vibecontrols.vibedeck.switcher.delete', 'Delete')}\n </button>\n </>\n )}\n </div>,\n document.body\n )}\n </>\n );\n};\n"],"mappings":";;;;;;;AA+BA,IAAa,KAA+C,EAC1D,UACA,iBACA,oBACA,iBACA,uBACA,iBACA,iBACA,gBACA,aACA,WACA,YACA,cACA,cACA,mBACI;CACJ,IAAM,IAAK,GAAO,EACZ,CAAC,GAAgB,KAAqB,EAAwB,KAAK,EACnE,CAAC,GAAa,KAAkB,EAA+C,KAAK,EACpF,IAAc,EAAuB,KAAK;AAEhD,SAAgB;EACd,IAAM,KAAsB,MAAkB;AAC5C,GAAI,EAAY,WAAW,CAAC,EAAY,QAAQ,SAAS,EAAE,OAAe,KACxE,EAAkB,KAAK,EACvB,EAAe,KAAK;;AAGxB,MAAI,EAEF,QADA,SAAS,iBAAiB,aAAa,EAAmB,QAC7C,SAAS,oBAAoB,aAAa,EAAmB;IAE3E,CAAC,EAAe,CAAC;CAEpB,IAAM,UAAsB;AAE1B,EADA,EAAkB,KAAK,EACvB,EAAe,KAAK;IAGhB,IAAa,IAAiB,EAAM,MAAM,MAAM,EAAE,OAAO,EAAe,GAAG;AAEjF,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,EAAM,KAAK,MAAS;GACnB,IAAM,IAAW,EAAK,OAAO,GACvB,IAAe,MAAmB,EAAK;AAE7C,UACE,kBAAC,OAAD;IAAmB,WAAU;cAA7B;KACE,kBAAC,OAAD;MAAK,UAAU,MAAU,EAAM,iBAAiB;gBAC9C,kBAAC,GAAD;OACE,SAAS,EAAgB,IAAI,EAAK,GAAG;OACrC,WAAW,MAAY,EAAmB,EAAK,IAAI,EAAQ;OAC3D,WAAW,eAAe,EAAK;OAC/B,CAAA;MACE,CAAA;KACN,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAa,EAAK,GAAG;MACpC,WAAW,gEACT,IACI,kDACA,EAAgB,IAAI,EAAK,GAAG,GAC1B,iFACA;gBAGR,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACG,EAAK,aACJ,kBAAC,GAAD;QAAM,MAAM;QAAI,WAAU;QAA0C,CAAA,EAErE,EAAK,KACD;;MACA,CAAA;KAER,MAAa,KAAa,KAAa,MACtC,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,MAAM;AACd,WAAI,EACF,IAAe;YACV;QACL,IAAM,IAAO,EAAE,cAAc,uBAAuB;AAEpD,QADA,EAAe;SAAE,KAAK,EAAK,SAAS;SAAG,MAAM,EAAK;SAAM,CAAC,EACzD,EAAkB,EAAK,GAAG;;;MAG9B,WAAW,iCACT,IACI,qCACA;MAEN,OAAM;gBAEN,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;MAClB,CAAA;KAEP;MAjDI,EAAK,GAiDT;IAER,EACD,KACC,kBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAU;aAHZ,CAKE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,0CAA0C,WAAW,CAClD;KAEP;KAGL,KACC,KACA,KACA,EACE,kBAAC,OAAD;EACE,KAAK;EACL,OAAO;GACL,UAAU;GACV,KAAK,EAAY;GACjB,MAAM,EAAY;GAClB,QAAQ;GACT;EACD,WAAU;YARZ;GAUG,KAAa,CAAC,EAAW,aACxB,kBAAC,UAAD;IACE,MAAK;IACL,eAAe;AAEb,KADA,EAAa,EAAW,GAAG,EAC3B,GAAe;;IAEjB,WAAU;cANZ,CAQE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,6CAA6C,iBAAiB,CAC3D;;GAEV,KACC,kBAAC,UAAD;IACE,MAAK;IACL,eAAe;AAEb,KADA,EAAO,EAAW,GAAG,EACrB,GAAe;;IAEjB,WAAU;cANZ,CAQE,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA,EACrB,EAAG,2CAA2C,YAAY,CACpD;;GAEV,KACC,kBAAC,UAAD;IACE,MAAK;IACL,eAAe;AAEb,KADA,EAAQ,EAAW,GAAG,EACtB,GAAe;;IAEjB,WAAU;cANZ,CAQE,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA,EACnB,EAAG,wCAAwC,QAAQ,CAC7C;;GAEV,KACC,kBAAC,UAAD;IACE,MAAK;IACL,eAAe;AAEb,KADA,EAAY,EAAW,GAAG,EAC1B,GAAe;;IAEjB,WAAU;cANZ,CAQE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,4CAA4C,YAAY,CACrD;;GAEV,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD,EAAK,WAAU,uCAAwC,CAAA,EACvD,kBAAC,UAAD;IACE,MAAK;IACL,eAAe;AAEb,KADA,EAAS,EAAW,GAAG,EACvB,GAAe;;IAEjB,WAAU;cANZ,CAQE,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA,EACnB,EAAG,yCAAyC,SAAS,CAC/C;MACR,EAAA,CAAA;GAED;KACN,SAAS,KACV,CACF,EAAA,CAAA"}
1
+ {"version":3,"file":"VibeDeckSwitcher.js","names":[],"sources":["../../../src/components/vibedeck/VibeDeckSwitcher.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Plus, Star, Copy, Trash2, Settings, ChevronDown, Share2 } from 'lucide-react';\nimport { SelectionCheckbox } from '../shared/SelectionCheckbox';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface DeckSummary {\n id: string;\n name: string;\n icon: string | null;\n colorTheme: string | null;\n isDefault: boolean;\n}\n\ninterface VibeDeckSwitcherProps {\n decks: DeckSummary[];\n activeDeckId: string | null;\n selectedDeckIds: Set<string>;\n onSelectDeck: (id: string) => void;\n onToggleSelectDeck: (id: string, checked: boolean) => void;\n onCreateDeck: () => void;\n onSetDefault: (id: string) => void;\n onDuplicate: (id: string) => void;\n onDelete: (id: string) => void;\n onEdit: (id: string) => void;\n onShare?: (id: string) => void;\n canCreate: boolean;\n canUpdate: boolean;\n canDelete: boolean;\n}\n\nexport const VibeDeckSwitcher: FC<VibeDeckSwitcherProps> = ({\n decks,\n activeDeckId,\n selectedDeckIds,\n onSelectDeck,\n onToggleSelectDeck,\n onCreateDeck,\n onSetDefault,\n onDuplicate,\n onDelete,\n onEdit,\n onShare,\n canCreate,\n canUpdate,\n canDelete,\n}) => {\n const tr = useTr();\n const [dropdownDeckId, setDropdownDeckId] = useState<string | null>(null);\n const [dropdownPos, setDropdownPos] = useState<{ top: number; left: number } | null>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setDropdownDeckId(null);\n setDropdownPos(null);\n }\n };\n if (dropdownDeckId) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [dropdownDeckId]);\n\n const closeDropdown = () => {\n setDropdownDeckId(null);\n setDropdownPos(null);\n };\n\n const activeDeck = dropdownDeckId ? decks.find((d) => d.id === dropdownDeckId) : null;\n\n return (\n <>\n <div className=\"flex items-center gap-2 overflow-x-auto pb-1\">\n {decks.map((deck) => {\n const isActive = deck.id === activeDeckId;\n const showDropdown = dropdownDeckId === deck.id;\n\n return (\n <div key={deck.id} className=\"flex items-center gap-1 shrink-0\">\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedDeckIds.has(deck.id)}\n onChange={(checked) => onToggleSelectDeck(deck.id, checked)}\n ariaLabel={`Select deck ${deck.name}`}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => onSelectDeck(deck.id)}\n className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${\n isActive\n ? 'bg-action-primary-bg text-action-primary-text'\n : selectedDeckIds.has(deck.id)\n ? 'bg-[var(--color-accent-soft)] text-text-primary border border-[var(--color-accent-soft)]'\n : 'bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary'\n }`}\n >\n <span className=\"flex items-center gap-1.5\">\n {deck.isDefault && (\n <Star size={12} className=\"fill-current text-status-warning-text\" />\n )}\n {deck.name}\n </span>\n </button>\n\n {isActive && (canUpdate || canDelete || canCreate) && (\n <button\n type=\"button\"\n onClick={(e) => {\n if (showDropdown) {\n closeDropdown();\n } else {\n const rect = e.currentTarget.getBoundingClientRect();\n setDropdownPos({ top: rect.bottom + 4, left: rect.left });\n setDropdownDeckId(deck.id);\n }\n }}\n className={`p-1 rounded transition-colors ${\n showDropdown\n ? 'bg-bg-sunken text-text-primary'\n : 'text-text-tertiary hover:text-text-primary hover:bg-bg-sunken'\n }`}\n title=\"Deck actions\"\n >\n <ChevronDown size={14} />\n </button>\n )}\n </div>\n );\n })}\n {canCreate && (\n <button\n type=\"button\"\n onClick={onCreateDeck}\n className=\"flex items-center gap-1 px-3 py-1.5 rounded-lg text-sm text-text-tertiary hover:text-text-primary hover:bg-bg-sunken transition-colors shrink-0 border border-dashed border-border-default\"\n >\n <Plus size={14} />\n {tr('vibecontrols.vibedeck.switcher.newDeck', 'New Deck')}\n </button>\n )}\n </div>\n\n {/* Dropdown rendered via portal to escape Framer Motion CSS transforms */}\n {dropdownDeckId &&\n dropdownPos &&\n activeDeck &&\n createPortal(\n <div\n ref={dropdownRef}\n style={{\n position: 'fixed',\n top: dropdownPos.top,\n left: dropdownPos.left,\n zIndex: 9999,\n }}\n className=\"bg-bg-elevated border border-border-default rounded-lg shadow-lg py-1 min-w-[160px]\"\n >\n {canUpdate && !activeDeck.isDefault && (\n <button\n type=\"button\"\n onClick={() => {\n onSetDefault(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <Star size={14} />\n {tr('vibecontrols.vibedeck.switcher.setDefault', 'Set as default')}\n </button>\n )}\n {canUpdate && (\n <button\n type=\"button\"\n onClick={() => {\n onEdit(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <Settings size={14} />\n {tr('vibecontrols.vibedeck.switcher.editDeck', 'Edit deck')}\n </button>\n )}\n {onShare && (\n <button\n type=\"button\"\n onClick={() => {\n onShare(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <Share2 size={14} />\n {tr('vibecontrols.vibedeck.switcher.share', 'Share')}\n </button>\n )}\n {canCreate && (\n <button\n type=\"button\"\n onClick={() => {\n onDuplicate(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n >\n <Copy size={14} />\n {tr('vibecontrols.vibedeck.switcher.duplicate', 'Duplicate')}\n </button>\n )}\n {canDelete && (\n <>\n <div className=\"border-t border-border-default my-1\" />\n <button\n type=\"button\"\n onClick={() => {\n onDelete(activeDeck.id);\n closeDropdown();\n }}\n className=\"flex items-center gap-2 w-full px-3 py-1.5 text-sm text-status-error-text hover:bg-bg-sunken\"\n >\n <Trash2 size={14} />\n {tr('vibecontrols.vibedeck.switcher.delete', 'Delete')}\n </button>\n </>\n )}\n </div>,\n document.body\n )}\n </>\n );\n};\n"],"mappings":"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"}
@@ -16,7 +16,7 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
16
16
  whileHover: "hover",
17
17
  whileTap: "tap",
18
18
  variants: n,
19
- className: `bg-bg-surface border rounded-lg p-4 hover:border-border-strong transition-colors cursor-pointer ${D ? "border-action-primary-bg ring-1 ring-action-primary-bg/25" : "border-border-default"} ${E}`,
19
+ className: `bg-bg-surface border rounded-card p-5 hover:border-border-strong transition-colors duration-200 cursor-pointer ${D ? "border-transparent ring-1 ring-[var(--color-focus-ring)] bg-[var(--color-accent-soft)]" : "border-border-subtle"} ${E}`,
20
20
  onClick: () => b?.(y),
21
21
  children: [
22
22
  /* @__PURE__ */ v("div", {
@@ -34,13 +34,13 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
34
34
  })
35
35
  }),
36
36
  /* @__PURE__ */ _("div", {
37
- className: "flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-action-primary-bg/10 flex items-center justify-center",
38
- children: /* @__PURE__ */ _(M, { className: "size-4 sm:w-5 sm:h-5 text-action-primary-bg" })
37
+ className: "flex-shrink-0 size-9 sm:size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
38
+ children: /* @__PURE__ */ _(M, { className: "size-4 sm:size-5 text-action-primary-bg" })
39
39
  }),
40
40
  /* @__PURE__ */ v("div", {
41
41
  className: "min-w-0 flex-1",
42
42
  children: [/* @__PURE__ */ _("h3", {
43
- className: "font-semibold text-text-primary truncate text-sm sm:text-base",
43
+ className: "font-semibold text-text-primary truncate text-sm sm:text-base tracking-tight",
44
44
  children: y.name
45
45
  }), y.description && /* @__PURE__ */ _("p", {
46
46
  className: "text-xs sm:text-sm text-text-secondary truncate",
@@ -57,8 +57,12 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
57
57
  onClick: (e) => {
58
58
  e.stopPropagation(), j(!A);
59
59
  },
60
- className: "p-1 sm:p-1.5 rounded hover:bg-bg-sunken transition-colors",
61
- children: /* @__PURE__ */ _(u, { className: "size-4 text-text-secondary" })
60
+ className: "inline-flex size-8 items-center justify-center rounded-button text-text-secondary hover:bg-bg-sunken hover:text-text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
61
+ "aria-label": "Vibe actions",
62
+ children: /* @__PURE__ */ _(u, {
63
+ className: "size-4",
64
+ "aria-hidden": "true"
65
+ })
62
66
  }), /* @__PURE__ */ _(h, { children: A && /* @__PURE__ */ v(g.div, {
63
67
  initial: {
64
68
  opacity: 0,
@@ -76,14 +80,14 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
76
80
  y: -4
77
81
  },
78
82
  transition: { duration: .15 },
79
- className: "absolute right-0 mt-1 w-40 bg-bg-surface border border-border-default rounded-lg shadow-lg z-10",
83
+ className: "absolute right-0 mt-1.5 w-44 bg-bg-elevated border border-border-subtle rounded-card shadow-elevation-3 z-10 overflow-hidden py-1",
80
84
  children: [
81
85
  w && y.status !== "ACTIVE" && /* @__PURE__ */ v(g.button, {
82
86
  whileTap: { scale: .97 },
83
87
  onClick: (e) => {
84
88
  e.stopPropagation(), w(y), j(!1);
85
89
  },
86
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-t-lg",
90
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
87
91
  children: [/* @__PURE__ */ _(d, { className: "size-4" }), "Activate"]
88
92
  }),
89
93
  x && /* @__PURE__ */ v(g.button, {
@@ -91,7 +95,7 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
91
95
  onClick: (e) => {
92
96
  e.stopPropagation(), x(y), j(!1);
93
97
  },
94
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken",
98
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
95
99
  children: [/* @__PURE__ */ _(f, { className: "size-4" }), "Edit"]
96
100
  }),
97
101
  T && y.path && /* @__PURE__ */ v(g.button, {
@@ -99,7 +103,7 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
99
103
  onClick: (e) => {
100
104
  e.stopPropagation(), T(y), j(!1);
101
105
  },
102
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken",
106
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
103
107
  children: [/* @__PURE__ */ _(s, { className: "size-4" }), "Open in VS Code"]
104
108
  }),
105
109
  S && y.status !== "ARCHIVED" && /* @__PURE__ */ v(g.button, {
@@ -107,7 +111,7 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
107
111
  onClick: (e) => {
108
112
  e.stopPropagation(), S(y), j(!1);
109
113
  },
110
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-b-lg",
114
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors",
111
115
  children: [/* @__PURE__ */ _(o, { className: "size-4" }), "Archive"]
112
116
  }),
113
117
  C && /* @__PURE__ */ v(g.button, {
@@ -115,7 +119,7 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
115
119
  onClick: (e) => {
116
120
  e.stopPropagation(), C(y), j(!1);
117
121
  },
118
- className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-bg-sunken rounded-b-lg",
122
+ className: "flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-status-error-bg-subtle transition-colors",
119
123
  children: [/* @__PURE__ */ _(m, { className: "size-4" }), "Delete"]
120
124
  })
121
125
  ]
@@ -128,11 +132,11 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
128
132
  children: y.description
129
133
  }),
130
134
  y.path && /* @__PURE__ */ _("div", {
131
- className: "mt-3 text-xs text-text-secondary font-mono bg-bg-sunken p-2 rounded truncate",
135
+ className: "mt-4 text-xs text-text-secondary font-mono bg-bg-sunken/60 px-2 py-1.5 rounded truncate",
132
136
  children: y.path
133
137
  }),
134
138
  y.gitBranch && /* @__PURE__ */ v("div", {
135
- className: "mt-2 flex items-center gap-2 text-sm text-text-secondary",
139
+ className: "mt-3 flex items-center gap-2 text-sm text-text-secondary",
136
140
  children: [
137
141
  /* @__PURE__ */ _(l, { className: "size-4" }),
138
142
  /* @__PURE__ */ _("span", {
@@ -140,18 +144,18 @@ var y = ({ vibe: y, onOpen: b, onEdit: x, onArchive: S, onDelete: C, onActivate:
140
144
  children: y.gitBranch
141
145
  }),
142
146
  y.gitStatus && y.gitStatus !== "clean" && /* @__PURE__ */ _("span", {
143
- className: "px-1.5 py-0.5 text-xs bg-status-warning-bg text-status-warning-text rounded",
147
+ className: "px-1.5 py-0.5 text-xs bg-status-warning-bg-subtle text-status-warning-text rounded",
144
148
  children: y.gitStatus
145
149
  })
146
150
  ]
147
151
  }),
148
152
  y.tags && y.tags.length > 0 && /* @__PURE__ */ v("div", {
149
- className: "mt-3 flex flex-wrap gap-1",
153
+ className: "mt-4 flex flex-wrap gap-1.5",
150
154
  children: [y.tags.slice(0, 3).map((e) => /* @__PURE__ */ v("span", {
151
- className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded",
155
+ className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded-full",
152
156
  children: [/* @__PURE__ */ _(p, { className: "size-3" }), e]
153
157
  }, e)), y.tags.length > 3 && /* @__PURE__ */ v("span", {
154
- className: "px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded",
158
+ className: "px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded-full",
155
159
  children: ["+", y.tags.length - 3]
156
160
  })]
157
161
  })
@@ -1 +1 @@
1
- {"version":3,"file":"VibeCard.js","names":[],"sources":["../../../src/components/vibes/VibeCard.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { FC } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n FolderOpen,\n GitBranch,\n MoreVertical,\n Play,\n Archive,\n Settings,\n Tag,\n ExternalLink,\n Trash2,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport type { Vibe } from './types';\nimport { vibeTypeIcons } from './icons';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { SelectionCheckbox } from '../shared/SelectionCheckbox';\nimport { cardHoverVariants } from '../shared/cardMotion';\n\nexport interface VibeCardProps {\n vibe: Vibe;\n onOpen?: (vibe: Vibe) => void;\n onEdit?: (vibe: Vibe) => void;\n onArchive?: (vibe: Vibe) => void;\n onDelete?: (vibe: Vibe) => void;\n onActivate?: (vibe: Vibe) => void;\n onOpenInEditor?: (vibe: Vibe) => void;\n className?: string;\n selected?: boolean;\n onToggleSelect?: (checked: boolean) => void;\n}\n\n/**\n * VibeCard - Display project/vibe information\n */\nexport const VibeCard: FC<VibeCardProps> = ({\n vibe,\n onOpen,\n onEdit,\n onArchive,\n onDelete,\n onActivate,\n onOpenInEditor,\n className = '',\n selected = false,\n onToggleSelect,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const [showMenu, setShowMenu] = useState(false);\n const Icon = vibeTypeIcons[vibe.type] || FolderOpen;\n\n return (\n <motion.div\n initial=\"rest\"\n animate=\"rest\"\n whileHover=\"hover\"\n whileTap=\"tap\"\n variants={cardHoverVariants}\n className={`bg-bg-surface border rounded-lg p-4 hover:border-border-strong transition-colors cursor-pointer ${\n selected\n ? 'border-action-primary-bg ring-1 ring-action-primary-bg/25'\n : 'border-border-default'\n } ${className}`}\n onClick={() => onOpen?.(vibe)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-2 sm:gap-3 min-w-0 flex-1\">\n {onToggleSelect && (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selected}\n onChange={onToggleSelect}\n ariaLabel={`Select vibe ${vibe.name}`}\n className=\"mt-2\"\n />\n </div>\n )}\n <div className=\"flex-shrink-0 size-8 sm:w-10 sm:h-10 rounded-lg bg-action-primary-bg/10 flex items-center justify-center\">\n <Icon className=\"size-4 sm:w-5 sm:h-5 text-action-primary-bg\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold text-text-primary truncate text-sm sm:text-base\">\n {vibe.name}\n </h3>\n {vibe.description && (\n <p className=\"text-xs sm:text-sm text-text-secondary truncate\">{vibe.description}</p>\n )}\n </div>\n </div>\n {/* Status and Actions - always visible */}\n <div className=\"flex items-center gap-1 sm:gap-2 flex-shrink-0\">\n <StatusBadge status={vibe.status} />\n {(onEdit || onArchive || onDelete || onActivate || onOpenInEditor) && (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(!showMenu);\n }}\n className=\"p-1 sm:p-1.5 rounded hover:bg-bg-sunken transition-colors\"\n >\n <MoreVertical className=\"size-4 text-text-secondary\" />\n </button>\n <AnimatePresence>\n {showMenu && (\n <motion.div\n initial={{ opacity: 0, scale: 0.95, y: -4 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, y: -4 }}\n transition={{ duration: 0.15 }}\n className=\"absolute right-0 mt-1 w-40 bg-bg-surface border border-border-default rounded-lg shadow-lg z-10\"\n >\n {onActivate && vibe.status !== 'ACTIVE' && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onActivate(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-t-lg\"\n >\n <Play className=\"size-4\" />\n Activate\n </motion.button>\n )}\n {onEdit && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onEdit(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken\"\n >\n <Settings className=\"size-4\" />\n Edit\n </motion.button>\n )}\n {onOpenInEditor && vibe.path && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onOpenInEditor(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken\"\n >\n <ExternalLink className=\"size-4\" />\n Open in VS Code\n </motion.button>\n )}\n {onArchive && vibe.status !== 'ARCHIVED' && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onArchive(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken rounded-b-lg\"\n >\n <Archive className=\"size-4\" />\n Archive\n </motion.button>\n )}\n {onDelete && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onDelete(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-bg-sunken rounded-b-lg\"\n >\n <Trash2 className=\"size-4\" />\n Delete\n </motion.button>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )}\n </div>\n </div>\n\n {vibe.description && (\n <p className=\"mt-2 text-sm text-text-secondary line-clamp-2\">{vibe.description}</p>\n )}\n\n {vibe.path && (\n <div className=\"mt-3 text-xs text-text-secondary font-mono bg-bg-sunken p-2 rounded truncate\">\n {vibe.path}\n </div>\n )}\n\n {vibe.gitBranch && (\n <div className=\"mt-2 flex items-center gap-2 text-sm text-text-secondary\">\n <GitBranch className=\"size-4\" />\n <span className=\"truncate\">{vibe.gitBranch}</span>\n {vibe.gitStatus && vibe.gitStatus !== 'clean' && (\n <span className=\"px-1.5 py-0.5 text-xs bg-status-warning-bg text-status-warning-text rounded\">\n {vibe.gitStatus}\n </span>\n )}\n </div>\n )}\n\n {vibe.tags && vibe.tags.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1\">\n {vibe.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\"\n >\n <Tag className=\"size-3\" />\n {tag}\n </span>\n ))}\n {vibe.tags.length > 3 && (\n <span className=\"px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\">\n +{vibe.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </motion.div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeCard.js","names":[],"sources":["../../../src/components/vibes/VibeCard.tsx"],"sourcesContent":["import { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { FC } from 'react';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport {\n FolderOpen,\n GitBranch,\n MoreVertical,\n Play,\n Archive,\n Settings,\n Tag,\n ExternalLink,\n Trash2,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport type { Vibe } from './types';\nimport { vibeTypeIcons } from './icons';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { SelectionCheckbox } from '../shared/SelectionCheckbox';\nimport { cardHoverVariants } from '../shared/cardMotion';\n\nexport interface VibeCardProps {\n vibe: Vibe;\n onOpen?: (vibe: Vibe) => void;\n onEdit?: (vibe: Vibe) => void;\n onArchive?: (vibe: Vibe) => void;\n onDelete?: (vibe: Vibe) => void;\n onActivate?: (vibe: Vibe) => void;\n onOpenInEditor?: (vibe: Vibe) => void;\n className?: string;\n selected?: boolean;\n onToggleSelect?: (checked: boolean) => void;\n}\n\n/**\n * VibeCard - Display project/vibe information\n */\nexport const VibeCard: FC<VibeCardProps> = ({\n vibe,\n onOpen,\n onEdit,\n onArchive,\n onDelete,\n onActivate,\n onOpenInEditor,\n className = '',\n selected = false,\n onToggleSelect,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const [showMenu, setShowMenu] = useState(false);\n const Icon = vibeTypeIcons[vibe.type] || FolderOpen;\n\n return (\n <motion.div\n initial=\"rest\"\n animate=\"rest\"\n whileHover=\"hover\"\n whileTap=\"tap\"\n variants={cardHoverVariants}\n className={`bg-bg-surface border rounded-card p-5 hover:border-border-strong transition-colors duration-200 cursor-pointer ${\n selected\n ? 'border-transparent ring-1 ring-[var(--color-focus-ring)] bg-[var(--color-accent-soft)]'\n : 'border-border-subtle'\n } ${className}`}\n onClick={() => onOpen?.(vibe)}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-2 sm:gap-3 min-w-0 flex-1\">\n {onToggleSelect && (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selected}\n onChange={onToggleSelect}\n ariaLabel={`Select vibe ${vibe.name}`}\n className=\"mt-2\"\n />\n </div>\n )}\n <div className=\"flex-shrink-0 size-9 sm:size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center\">\n <Icon className=\"size-4 sm:size-5 text-action-primary-bg\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"font-semibold text-text-primary truncate text-sm sm:text-base tracking-tight\">\n {vibe.name}\n </h3>\n {vibe.description && (\n <p className=\"text-xs sm:text-sm text-text-secondary truncate\">{vibe.description}</p>\n )}\n </div>\n </div>\n {/* Status and Actions - always visible */}\n <div className=\"flex items-center gap-1 sm:gap-2 flex-shrink-0\">\n <StatusBadge status={vibe.status} />\n {(onEdit || onArchive || onDelete || onActivate || onOpenInEditor) && (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(!showMenu);\n }}\n className=\"inline-flex size-8 items-center justify-center rounded-button text-text-secondary hover:bg-bg-sunken hover:text-text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n aria-label=\"Vibe actions\"\n >\n <MoreVertical className=\"size-4\" aria-hidden=\"true\" />\n </button>\n <AnimatePresence>\n {showMenu && (\n <motion.div\n initial={{ opacity: 0, scale: 0.95, y: -4 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.95, y: -4 }}\n transition={{ duration: 0.15 }}\n className=\"absolute right-0 mt-1.5 w-44 bg-bg-elevated border border-border-subtle rounded-card shadow-elevation-3 z-10 overflow-hidden py-1\"\n >\n {onActivate && vibe.status !== 'ACTIVE' && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onActivate(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Play className=\"size-4\" />\n Activate\n </motion.button>\n )}\n {onEdit && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onEdit(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Settings className=\"size-4\" />\n Edit\n </motion.button>\n )}\n {onOpenInEditor && vibe.path && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onOpenInEditor(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <ExternalLink className=\"size-4\" />\n Open in VS Code\n </motion.button>\n )}\n {onArchive && vibe.status !== 'ARCHIVED' && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onArchive(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Archive className=\"size-4\" />\n Archive\n </motion.button>\n )}\n {onDelete && (\n <motion.button\n whileTap={{ scale: 0.97 }}\n onClick={(e) => {\n e.stopPropagation();\n onDelete(vibe);\n setShowMenu(false);\n }}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-sm text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <Trash2 className=\"size-4\" />\n Delete\n </motion.button>\n )}\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )}\n </div>\n </div>\n\n {vibe.description && (\n <p className=\"mt-2 text-sm text-text-secondary line-clamp-2\">{vibe.description}</p>\n )}\n\n {vibe.path && (\n <div className=\"mt-4 text-xs text-text-secondary font-mono bg-bg-sunken/60 px-2 py-1.5 rounded truncate\">\n {vibe.path}\n </div>\n )}\n\n {vibe.gitBranch && (\n <div className=\"mt-3 flex items-center gap-2 text-sm text-text-secondary\">\n <GitBranch className=\"size-4\" />\n <span className=\"truncate\">{vibe.gitBranch}</span>\n {vibe.gitStatus && vibe.gitStatus !== 'clean' && (\n <span className=\"px-1.5 py-0.5 text-xs bg-status-warning-bg-subtle text-status-warning-text rounded\">\n {vibe.gitStatus}\n </span>\n )}\n </div>\n )}\n\n {vibe.tags && vibe.tags.length > 0 && (\n <div className=\"mt-4 flex flex-wrap gap-1.5\">\n {vibe.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded-full\"\n >\n <Tag className=\"size-3\" />\n {tag}\n </span>\n ))}\n {vibe.tags.length > 3 && (\n <span className=\"px-2 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded-full\">\n +{vibe.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </motion.div>\n );\n};\n"],"mappings":"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"}