@wopr-network/platform-ui-core 1.27.8 → 1.27.9

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 (353) hide show
  1. package/next.config.ts +1 -2
  2. package/package.json +17 -17
  3. package/src/__tests__/account-switcher.test.tsx +21 -20
  4. package/src/__tests__/activity-page.test.tsx +2 -6
  5. package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
  6. package/src/__tests__/admin-api.test.ts +1 -6
  7. package/src/__tests__/admin-gpu-api.test.ts +1 -3
  8. package/src/__tests__/admin-marketplace-api.test.ts +1 -4
  9. package/src/__tests__/admin-middleware.test.ts +76 -83
  10. package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
  11. package/src/__tests__/api-401-redirect.test.ts +46 -9
  12. package/src/__tests__/api-client.test.ts +3 -5
  13. package/src/__tests__/api-config.test.ts +22 -42
  14. package/src/__tests__/api-fleet-resources.test.ts +1 -2
  15. package/src/__tests__/api-fleet-trpc.test.ts +2 -8
  16. package/src/__tests__/api-null-guards.test.ts +3 -1
  17. package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
  18. package/src/__tests__/auth-password-reset.test.tsx +7 -21
  19. package/src/__tests__/auth-redirect.test.tsx +8 -2
  20. package/src/__tests__/auth.test.tsx +25 -23
  21. package/src/__tests__/auto-topup-card.test.tsx +4 -12
  22. package/src/__tests__/backups-tab.test.tsx +3 -4
  23. package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
  24. package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
  25. package/src/__tests__/billing.test.tsx +8 -39
  26. package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
  27. package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
  28. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
  29. package/src/__tests__/bot-settings-restart.test.tsx +1 -3
  30. package/src/__tests__/bot-settings.test.tsx +2 -6
  31. package/src/__tests__/brand.test.ts +6 -26
  32. package/src/__tests__/buy-credits-panel.test.tsx +1 -3
  33. package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
  34. package/src/__tests__/capability-conflicts.test.ts +2 -8
  35. package/src/__tests__/capability-resolver.test.tsx +2 -12
  36. package/src/__tests__/channel-wizard.test.tsx +4 -17
  37. package/src/__tests__/chat/chat-panel.test.tsx +1 -4
  38. package/src/__tests__/chat-store.test.ts +5 -15
  39. package/src/__tests__/command-center.test.tsx +10 -12
  40. package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
  41. package/src/__tests__/confirmation-tracker.test.tsx +3 -18
  42. package/src/__tests__/coupon-input.test.tsx +1 -3
  43. package/src/__tests__/create-instance.test.tsx +1 -3
  44. package/src/__tests__/credit-balance.test.tsx +4 -12
  45. package/src/__tests__/credits.test.tsx +32 -85
  46. package/src/__tests__/email-verification-banner.test.tsx +2 -6
  47. package/src/__tests__/error-boundaries.test.tsx +0 -1
  48. package/src/__tests__/fetch-pricing.test.ts +2 -1
  49. package/src/__tests__/field-oauth.test.tsx +2 -6
  50. package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
  51. package/src/__tests__/fixtures/mock-manifests.ts +2 -4
  52. package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
  53. package/src/__tests__/fleet-health-update.test.tsx +1 -8
  54. package/src/__tests__/gpu-dashboard.test.tsx +2 -6
  55. package/src/__tests__/instance-detail.test.tsx +3 -9
  56. package/src/__tests__/instance-list.test.tsx +1 -5
  57. package/src/__tests__/layout-snapshots.test.tsx +64 -11
  58. package/src/__tests__/marketplace-admin.test.tsx +2 -6
  59. package/src/__tests__/marketplace.test.tsx +11 -35
  60. package/src/__tests__/merge-api-rates.test.ts +1 -6
  61. package/src/__tests__/middleware.test.ts +32 -219
  62. package/src/__tests__/next-config-headers.test.ts +1 -3
  63. package/src/__tests__/notifications.test.tsx +4 -11
  64. package/src/__tests__/oauth-buttons.test.tsx +36 -59
  65. package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
  66. package/src/__tests__/observability.test.tsx +23 -36
  67. package/src/__tests__/onboarding-page.test.tsx +4 -6
  68. package/src/__tests__/org-billing-api.test.tsx +1 -6
  69. package/src/__tests__/plugin-install-flow.test.tsx +28 -58
  70. package/src/__tests__/plugin-registry.test.tsx +3 -11
  71. package/src/__tests__/plugin-tool-sync.test.ts +1 -3
  72. package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
  73. package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
  74. package/src/__tests__/portfolio-chart.test.tsx +2 -6
  75. package/src/__tests__/promotion-form.test.tsx +2 -6
  76. package/src/__tests__/promotions-list.test.tsx +1 -3
  77. package/src/__tests__/provider-key-api.test.ts +2 -1
  78. package/src/__tests__/resend-verification-button.test.tsx +8 -24
  79. package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
  80. package/src/__tests__/settings.test.tsx +11 -21
  81. package/src/__tests__/setup-checklist.test.tsx +3 -9
  82. package/src/__tests__/setup.ts +25 -6
  83. package/src/__tests__/snapshot-api.test.ts +2 -1
  84. package/src/__tests__/step-superpowers.test.tsx +1 -3
  85. package/src/__tests__/tenant-context.test.tsx +1 -6
  86. package/src/__tests__/tenant-keys-api.test.ts +3 -4
  87. package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
  88. package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
  89. package/src/__tests__/transaction-history.test.tsx +190 -238
  90. package/src/__tests__/trpc-types.test.ts +2 -6
  91. package/src/__tests__/use-chat.test.ts +1 -3
  92. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
  93. package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
  94. package/src/__tests__/use-webmcp.test.ts +1 -3
  95. package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
  96. package/src/__tests__/verify-page.test.tsx +4 -13
  97. package/src/__tests__/verify-redirect.test.tsx +2 -6
  98. package/src/app/(auth)/error.tsx +1 -7
  99. package/src/app/(auth)/forgot-password/page.tsx +4 -18
  100. package/src/app/(auth)/login/page.tsx +5 -22
  101. package/src/app/(auth)/reset-password/page.tsx +2 -12
  102. package/src/app/(auth)/signup/page.tsx +10 -44
  103. package/src/app/(auth)/verify/page.tsx +47 -0
  104. package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
  105. package/src/app/(dashboard)/billing/error.tsx +2 -10
  106. package/src/app/(dashboard)/billing/layout.tsx +12 -62
  107. package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
  108. package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
  109. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
  110. package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
  111. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
  112. package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
  113. package/src/app/(dashboard)/changesets/error.tsx +1 -7
  114. package/src/app/(dashboard)/chat/page.tsx +2 -6
  115. package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
  116. package/src/app/(dashboard)/error.tsx +1 -7
  117. package/src/app/(dashboard)/layout.tsx +15 -36
  118. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
  119. package/src/app/(dashboard)/marketplace/error.tsx +1 -7
  120. package/src/app/(dashboard)/marketplace/page.tsx +6 -27
  121. package/src/app/(dashboard)/not-found.tsx +2 -5
  122. package/src/app/(dashboard)/onboarding/page.tsx +5 -22
  123. package/src/app/(dashboard)/settings/account/page.tsx +1 -6
  124. package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
  125. package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
  126. package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
  127. package/src/app/(dashboard)/settings/error.tsx +2 -10
  128. package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
  129. package/src/app/(dashboard)/settings/org/page.tsx +13 -56
  130. package/src/app/(dashboard)/settings/page.tsx +1 -0
  131. package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
  132. package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
  133. package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
  134. package/src/app/(dashboard)/settings/security/page.tsx +31 -111
  135. package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
  136. package/src/app/admin/error.tsx +1 -7
  137. package/src/app/admin/fleet-updates/error.tsx +1 -7
  138. package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
  139. package/src/app/admin/layout.tsx +4 -0
  140. package/src/app/admin/payment-methods/page.tsx +9 -38
  141. package/src/app/admin/products/error.tsx +2 -7
  142. package/src/app/admin/products/page.tsx +1 -4
  143. package/src/app/admin/promotions/[id]/page.tsx +9 -38
  144. package/src/app/admin/promotions/page.tsx +9 -36
  145. package/src/app/admin/rate-overrides/page.tsx +9 -45
  146. package/src/app/auth/callback/[provider]/page.tsx +1 -8
  147. package/src/app/auth/verify/page.tsx +9 -36
  148. package/src/app/channels/error.tsx +2 -10
  149. package/src/app/channels/layout.tsx +9 -0
  150. package/src/app/channels/page.tsx +8 -20
  151. package/src/app/channels/setup/[plugin]/page.tsx +3 -5
  152. package/src/app/error.tsx +1 -7
  153. package/src/app/fleet/error.tsx +1 -7
  154. package/src/app/fleet/layout.tsx +5 -0
  155. package/src/app/fleet/settings/page.tsx +1 -3
  156. package/src/app/global-error.tsx +2 -10
  157. package/src/app/globals.css +1 -4
  158. package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
  159. package/src/app/instances/error.tsx +2 -10
  160. package/src/app/instances/instance-list-client.tsx +20 -69
  161. package/src/app/instances/layout.tsx +9 -0
  162. package/src/app/instances/new/create-instance-client.tsx +10 -31
  163. package/src/app/layout.tsx +2 -10
  164. package/src/app/not-found.tsx +1 -3
  165. package/src/app/page.tsx +1 -2
  166. package/src/app/plugins/error.tsx +2 -10
  167. package/src/app/plugins/layout.tsx +5 -0
  168. package/src/app/plugins/page.tsx +16 -48
  169. package/src/app/pricing/error.tsx +1 -7
  170. package/src/app/privacy/page.tsx +93 -150
  171. package/src/app/status/error.tsx +1 -7
  172. package/src/app/terms/page.tsx +89 -144
  173. package/src/components/account-switcher.tsx +25 -52
  174. package/src/components/admin/accounting-dashboard.tsx +1 -3
  175. package/src/components/admin/admin-guard.tsx +1 -3
  176. package/src/components/admin/admin-nav.tsx +1 -3
  177. package/src/components/admin/affiliate-dashboard.tsx +25 -94
  178. package/src/components/admin/audit-log-table.tsx +13 -49
  179. package/src/components/admin/billing-health-dashboard.tsx +7 -25
  180. package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
  181. package/src/components/admin/bulk-actions-bar.tsx +1 -3
  182. package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
  183. package/src/components/admin/bulk-export-dialog.tsx +6 -32
  184. package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
  185. package/src/components/admin/bulk-grant-dialog.tsx +4 -15
  186. package/src/components/admin/bulk-preview-dialog.tsx +3 -12
  187. package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
  188. package/src/components/admin/bulk-select-all-banner.tsx +1 -6
  189. package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
  190. package/src/components/admin/bulk-undo-toast.tsx +1 -2
  191. package/src/components/admin/compliance-dashboard.tsx +31 -101
  192. package/src/components/admin/gpu-dashboard.tsx +21 -70
  193. package/src/components/admin/grant-credits-dialog.tsx +4 -17
  194. package/src/components/admin/incident-dashboard.tsx +10 -25
  195. package/src/components/admin/inference-dashboard.tsx +14 -54
  196. package/src/components/admin/marketplace-admin.tsx +18 -60
  197. package/src/components/admin/migrations-dashboard.tsx +9 -42
  198. package/src/components/admin/onboarding-dashboard.tsx +14 -64
  199. package/src/components/admin/pool-config-dashboard.tsx +4 -10
  200. package/src/components/admin/products/fleet-form.tsx +2 -11
  201. package/src/components/admin/products/nav-editor.tsx +3 -10
  202. package/src/components/admin/promotions/promotion-form.tsx +9 -42
  203. package/src/components/admin/roles-dashboard.tsx +7 -34
  204. package/src/components/admin/suspend-dialog.tsx +4 -11
  205. package/src/components/admin/tenant-notes-panel.tsx +1 -3
  206. package/src/components/admin/tenant-row-actions.tsx +4 -20
  207. package/src/components/admin/tenant-table.tsx +12 -49
  208. package/src/components/auth/auth-redirect.tsx +11 -3
  209. package/src/components/auth/email-verification-result-banner.tsx +1 -3
  210. package/src/components/auth/resend-verification-button.tsx +2 -10
  211. package/src/components/auth/wopr-wordmark.tsx +1 -3
  212. package/src/components/billing/add-payment-method-dialog.tsx +1 -2
  213. package/src/components/billing/affiliate-dashboard.tsx +4 -16
  214. package/src/components/billing/amount-selector.tsx +1 -3
  215. package/src/components/billing/auto-topup-card.tsx +2 -11
  216. package/src/components/billing/buy-credits-panel.tsx +4 -14
  217. package/src/components/billing/byok-callout.tsx +6 -8
  218. package/src/components/billing/confirmation-tracker.tsx +4 -14
  219. package/src/components/billing/credit-balance-badge.tsx +22 -0
  220. package/src/components/billing/credit-balance.tsx +3 -9
  221. package/src/components/billing/crypto-checkout.tsx +5 -24
  222. package/src/components/billing/degraded-state-banner.tsx +1 -3
  223. package/src/components/billing/deposit-view.tsx +301 -41
  224. package/src/components/billing/dividend-banner.tsx +1 -3
  225. package/src/components/billing/dividend-eligibility.tsx +3 -12
  226. package/src/components/billing/dividend-pool-stats.tsx +6 -20
  227. package/src/components/billing/first-dividend-dialog.tsx +2 -2
  228. package/src/components/billing/org-billing-page.tsx +8 -31
  229. package/src/components/billing/payment-method-picker.tsx +2 -10
  230. package/src/components/billing/suspension-banner.tsx +2 -7
  231. package/src/components/billing/transaction-history.tsx +10 -58
  232. package/src/components/billing/unified-checkout.tsx +547 -0
  233. package/src/components/bot-settings/backups-tab.tsx +9 -33
  234. package/src/components/bot-settings/bot-settings-client.tsx +32 -134
  235. package/src/components/bot-settings/resources-tab.tsx +2 -9
  236. package/src/components/bot-settings/storage-tab.tsx +19 -48
  237. package/src/components/bot-settings/vps-info-panel.tsx +3 -11
  238. package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
  239. package/src/components/brand-hydrator.tsx +13 -0
  240. package/src/components/channel-wizard/field-interactive.tsx +1 -3
  241. package/src/components/channel-wizard/field-qr.tsx +10 -39
  242. package/src/components/channel-wizard/step-renderer.tsx +5 -28
  243. package/src/components/channel-wizard/wizard.tsx +6 -31
  244. package/src/components/chat/chat-message.tsx +1 -4
  245. package/src/components/chat/chat-panel.tsx +4 -18
  246. package/src/components/chat/chat-widget.tsx +3 -14
  247. package/src/components/dashboard/command-center.tsx +15 -61
  248. package/src/components/fleet/update-settings-card.tsx +7 -23
  249. package/src/components/instance-update-banner.tsx +130 -0
  250. package/src/components/instances/friends-tab.test.tsx +2 -9
  251. package/src/components/instances/friends-tab.tsx +18 -74
  252. package/src/components/instances/update-available-badge.tsx +2 -11
  253. package/src/components/landing/hero.tsx +3 -9
  254. package/src/components/landing/landing-page.tsx +1 -3
  255. package/src/components/landing/portfolio-chart.tsx +4 -9
  256. package/src/components/landing/story-sections.tsx +1 -3
  257. package/src/components/landing/terminal-sequence.tsx +4 -17
  258. package/src/components/marketplace/empty-state.tsx +2 -6
  259. package/src/components/marketplace/first-visit-hero.tsx +1 -3
  260. package/src/components/marketplace/install-wizard.tsx +20 -77
  261. package/src/components/marketplace/marketplace-tabs.tsx +1 -4
  262. package/src/components/marketplace/plugin-card.tsx +2 -9
  263. package/src/components/marketplace/superpower-content.tsx +1 -3
  264. package/src/components/marketplace/terminal-search.tsx +2 -8
  265. package/src/components/oauth-buttons.tsx +29 -14
  266. package/src/components/observability/fleet-health.tsx +5 -18
  267. package/src/components/observability/health-overview.tsx +7 -20
  268. package/src/components/observability/logs-viewer.tsx +8 -32
  269. package/src/components/observability/metrics-dashboard.tsx +2 -15
  270. package/src/components/onboarding/fallback-setup.tsx +6 -25
  271. package/src/components/onboarding/setup-checklist.tsx +18 -51
  272. package/src/components/onboarding/step-superpowers.tsx +1 -4
  273. package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
  274. package/src/components/pricing/dividend-calculator.tsx +6 -12
  275. package/src/components/pricing/dividend-stats.tsx +5 -17
  276. package/src/components/pricing/pricing-page.tsx +17 -36
  277. package/src/components/settings/create-org-wizard.tsx +2 -5
  278. package/src/components/sidebar.tsx +7 -42
  279. package/src/components/sidecar-frame.tsx +78 -0
  280. package/src/components/status/status-page.tsx +6 -28
  281. package/src/components/ui/alert-dialog.tsx +8 -25
  282. package/src/components/ui/badge.tsx +2 -8
  283. package/src/components/ui/banner.tsx +1 -6
  284. package/src/components/ui/card.tsx +5 -24
  285. package/src/components/ui/checkbox.tsx +1 -5
  286. package/src/components/ui/collapsible.tsx +3 -8
  287. package/src/components/ui/dialog.tsx +4 -10
  288. package/src/components/ui/dropdown-menu.tsx +9 -18
  289. package/src/components/ui/form.tsx +2 -16
  290. package/src/components/ui/popover.tsx +3 -23
  291. package/src/components/ui/progress.tsx +1 -5
  292. package/src/components/ui/radio-group.tsx +3 -15
  293. package/src/components/ui/select.tsx +4 -17
  294. package/src/components/ui/sheet.tsx +5 -19
  295. package/src/components/ui/skeleton.tsx +1 -7
  296. package/src/components/ui/table.tsx +5 -22
  297. package/src/components/ui/tabs.tsx +3 -13
  298. package/src/components/ui/tooltip.tsx +1 -1
  299. package/src/components/unified-sidebar.tsx +493 -0
  300. package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
  301. package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
  302. package/src/hooks/use-credit-balance.ts +27 -0
  303. package/src/hooks/use-my-org-role.ts +1 -3
  304. package/src/hooks/use-plugin-registry.ts +8 -14
  305. package/src/hooks/use-plugin-setup-chat.ts +2 -5
  306. package/src/hooks/use-sidecar-bridge.tsx +148 -0
  307. package/src/hooks/use-webmcp.ts +1 -4
  308. package/src/lib/__tests__/admin-api.test.ts +1 -3
  309. package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
  310. package/src/lib/__tests__/api-fetch.test.ts +4 -16
  311. package/src/lib/__tests__/org-billing-api.test.ts +1 -3
  312. package/src/lib/__tests__/pricing-data.test.ts +0 -8
  313. package/src/lib/__tests__/settings-api.test.ts +1 -3
  314. package/src/lib/admin-affiliate-api.ts +2 -7
  315. package/src/lib/admin-api.ts +6 -26
  316. package/src/lib/admin-incident-api.ts +11 -19
  317. package/src/lib/admin-marketplace-api.ts +1 -5
  318. package/src/lib/api-config.test.ts +5 -50
  319. package/src/lib/api.ts +143 -122
  320. package/src/lib/auth-client.ts +1 -2
  321. package/src/lib/bot-settings-data.ts +11 -36
  322. package/src/lib/brand-config.ts +56 -115
  323. package/src/lib/brand.ts +2 -15
  324. package/src/lib/chat/use-chat.ts +2 -7
  325. package/src/lib/cost-comparison-data.test.ts +1 -3
  326. package/src/lib/cost-comparison-data.ts +1 -4
  327. package/src/lib/errors.ts +1 -4
  328. package/src/lib/fetch-utils.test.ts +26 -9
  329. package/src/lib/fetch-utils.ts +40 -11
  330. package/src/lib/logger.ts +2 -0
  331. package/src/lib/marketplace-data.ts +3 -11
  332. package/src/lib/oauth-errors.ts +2 -4
  333. package/src/lib/onboarding-data.ts +3 -11
  334. package/src/lib/org-api.ts +2 -10
  335. package/src/lib/org-billing-api.ts +5 -19
  336. package/src/lib/plugin/tool-definitions.ts +1 -2
  337. package/src/lib/require-auth.ts +57 -0
  338. package/src/lib/settings-api.ts +1 -4
  339. package/src/lib/sidecar-routes.ts +43 -0
  340. package/src/lib/trpc-server.ts +49 -0
  341. package/src/lib/trpc-types.ts +4 -6
  342. package/src/lib/trpc.tsx +12 -4
  343. package/src/lib/validate-redirect-url.ts +1 -4
  344. package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
  345. package/src/lib/webmcp/register.ts +1 -4
  346. package/src/lib/webmcp/tools.ts +2 -9
  347. package/src/proxy.ts +35 -212
  348. package/src/types/missing-deps.d.ts +2 -8
  349. package/tsconfig.json +1 -8
  350. package/biome.json +0 -52
  351. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
  352. package/src/__tests__/billing-byok-callout.test.tsx +0 -76
  353. package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
@@ -13,12 +13,11 @@ export function DividendCalculator() {
13
13
  <div className="space-y-2 text-center">
14
14
  <p className="text-lg text-foreground">
15
15
  <span className="font-semibold text-terminal">100K active users</span> &middot;{" "}
16
- <span className="font-semibold text-terminal">$20/month average spend</span> &middot;
17
- equal daily share
16
+ <span className="font-semibold text-terminal">$20/month average spend</span> &middot; equal daily share
18
17
  </p>
19
18
  <p className="text-muted-foreground">
20
- Projected dividend: <span className="font-semibold text-terminal">~$0.67/day</span>.
21
- Average daily spend: <span className="font-semibold text-terminal">~$0.67</span>.
19
+ Projected dividend: <span className="font-semibold text-terminal">~$0.67/day</span>. Average daily spend:{" "}
20
+ <span className="font-semibold text-terminal">~$0.67</span>.
22
21
  </p>
23
22
  <p className="text-xl font-bold text-terminal" data-testid="net-cost">
24
23
  Net cost of credits at scale: $0.
@@ -29,17 +28,12 @@ export function DividendCalculator() {
29
28
 
30
29
  <Card className="border-amber-500/20 bg-amber-500/5">
31
30
  <CardContent className="space-y-2 py-6 text-center">
32
- <p className="text-sm uppercase tracking-widest text-amber-500">
33
- Early adopter advantage
34
- </p>
31
+ <p className="text-sm uppercase tracking-widest text-amber-500">Early adopter advantage</p>
35
32
  <p className="text-foreground">
36
33
  The earlier you join, the more you accumulate. Day 1 users in a 100K community collect{" "}
37
- <span className="font-semibold text-terminal">~$132</span> in their first 60 days on a
38
- $5 minimum spend.
39
- </p>
40
- <p className="text-sm text-muted-foreground">
41
- The math doesn&apos;t lie — being early pays.
34
+ <span className="font-semibold text-terminal">~$132</span> in their first 60 days on a $5 minimum spend.
42
35
  </p>
36
+ <p className="text-sm text-muted-foreground">The math doesn&apos;t lie — being early pays.</p>
43
37
  </CardContent>
44
38
  </Card>
45
39
  </div>
@@ -14,10 +14,7 @@ function useCountUp(target: number, duration = 1200) {
14
14
  return;
15
15
  }
16
16
  // Respect prefers-reduced-motion: skip animation, set immediately
17
- if (
18
- typeof window !== "undefined" &&
19
- window.matchMedia("(prefers-reduced-motion: reduce)").matches
20
- ) {
17
+ if (typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
21
18
  setValue(target);
22
19
  return;
23
20
  }
@@ -79,9 +76,7 @@ export function DividendStats() {
79
76
  {error && <p className="col-span-full text-center text-sm text-red-500">{error}</p>}
80
77
  <Card className="border-terminal/30">
81
78
  <CardContent className="flex flex-col items-center gap-1 py-6 text-center">
82
- <p className="text-xs uppercase tracking-widest text-muted-foreground">
83
- Today&apos;s community pool
84
- </p>
79
+ <p className="text-xs uppercase tracking-widest text-muted-foreground">Today&apos;s community pool</p>
85
80
  <p className="text-3xl font-bold text-terminal sm:text-4xl" data-testid="pool-amount">
86
81
  {loaded && pool > 0 ? formatDollars(animatedPool) : "--"}
87
82
  </p>
@@ -90,9 +85,7 @@ export function DividendStats() {
90
85
 
91
86
  <Card className="border-terminal/30">
92
87
  <CardContent className="flex flex-col items-center gap-1 py-6 text-center">
93
- <p className="text-xs uppercase tracking-widest text-muted-foreground">
94
- Active users in pool
95
- </p>
88
+ <p className="text-xs uppercase tracking-widest text-muted-foreground">Active users in pool</p>
96
89
  <p className="text-3xl font-bold text-terminal sm:text-4xl" data-testid="active-users">
97
90
  {loaded && users > 0 ? Math.round(animatedUsers).toLocaleString() : "--"}
98
91
  </p>
@@ -101,13 +94,8 @@ export function DividendStats() {
101
94
 
102
95
  <Card className="border-terminal/30">
103
96
  <CardContent className="flex flex-col items-center gap-1 py-6 text-center">
104
- <p className="text-xs uppercase tracking-widest text-muted-foreground">
105
- Your projected daily dividend
106
- </p>
107
- <p
108
- className="text-3xl font-bold text-terminal sm:text-4xl"
109
- data-testid="projected-dividend"
110
- >
97
+ <p className="text-xs uppercase tracking-widest text-muted-foreground">Your projected daily dividend</p>
98
+ <p className="text-3xl font-bold text-terminal sm:text-4xl" data-testid="projected-dividend">
111
99
  {loaded && dividend > 0 ? `~${formatCreditStandard(animatedDividend)}` : "--"}
112
100
  </p>
113
101
  </CardContent>
@@ -47,13 +47,13 @@ export async function PricingPage() {
47
47
  </h1>
48
48
 
49
49
  <p className="mt-6 max-w-xl text-lg text-muted-foreground">
50
- Every day, the platform distributes credits back to active users from its own margin. The
51
- bigger the community grows, the more you receive. Early users get the most.
50
+ Every day, the platform distributes credits back to active users from its own margin. The bigger the community
51
+ grows, the more you receive. Early users get the most.
52
52
  </p>
53
53
 
54
54
  <p className="mt-4 max-w-lg text-sm text-muted-foreground">
55
- At scale, the daily dividend covers your entire credit spend. You&apos;re not paying to
56
- run your bots. {brandName()} is.
55
+ At scale, the daily dividend covers your entire credit spend. You&apos;re not paying to run your bots.{" "}
56
+ {brandName()} is.
57
57
  </p>
58
58
  </section>
59
59
 
@@ -75,22 +75,17 @@ export async function PricingPage() {
75
75
  <span className="font-semibold text-terminal">
76
76
  ${pricingData.bot_price.amount}/{pricingData.bot_price.period}
77
77
  </span>
78
- . That&apos;s the minimum to be eligible for the daily dividend. Usage is billed at cost
79
- from credits.
78
+ . That&apos;s the minimum to be eligible for the daily dividend. Usage is billed at cost from credits.
80
79
  </p>
81
80
 
82
81
  <Card className="w-full max-w-md border-terminal">
83
82
  <CardHeader className="items-center text-center">
84
- <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">
85
- Pool eligibility
86
- </CardTitle>
83
+ <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">Pool eligibility</CardTitle>
87
84
  </CardHeader>
88
85
  <CardContent className="flex flex-col items-center gap-4">
89
86
  <p className="text-5xl font-bold text-terminal sm:text-6xl" data-testid="bot-price">
90
87
  ${pricingData.bot_price.amount}
91
- <span className="text-xl font-normal text-muted-foreground">
92
- /{pricingData.bot_price.period}
93
- </span>
88
+ <span className="text-xl font-normal text-muted-foreground">/{pricingData.bot_price.period}</span>
94
89
  </p>
95
90
  <p className="text-muted-foreground">Minimum spend to stay in the dividend pool.</p>
96
91
  </CardContent>
@@ -121,9 +116,7 @@ export async function PricingPage() {
121
116
  <p className="font-medium">{model.name}</p>
122
117
  <p className="text-sm text-muted-foreground">per {model.unit}</p>
123
118
  </div>
124
- <p className="text-lg font-bold text-terminal">
125
- {formatPrice(model.price)}
126
- </p>
119
+ <p className="text-lg font-bold text-terminal">{formatPrice(model.price)}</p>
127
120
  </CardContent>
128
121
  </Card>
129
122
  ))}
@@ -136,19 +129,15 @@ export async function PricingPage() {
136
129
 
137
130
  {/* --- VPS Tier --- */}
138
131
  <section className="mx-auto max-w-4xl px-6 pb-24">
139
- <h2 className="mb-4 text-center text-2xl font-bold tracking-tight sm:text-3xl">
140
- Need a dedicated machine?
141
- </h2>
132
+ <h2 className="mb-4 text-center text-2xl font-bold tracking-tight sm:text-3xl">Need a dedicated machine?</h2>
142
133
  <p className="mb-8 text-center text-muted-foreground">
143
- The VPS tier gives your bot a persistent container with fixed monthly pricing — no
144
- per-credit billing for compute.
134
+ The VPS tier gives your bot a persistent container with fixed monthly pricing — no per-credit billing for
135
+ compute.
145
136
  </p>
146
137
  <div className="mx-auto max-w-sm">
147
138
  <Card className="border-terminal/50">
148
139
  <CardHeader className="items-center text-center">
149
- <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">
150
- VPS tier
151
- </CardTitle>
140
+ <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">VPS tier</CardTitle>
152
141
  </CardHeader>
153
142
  <CardContent className="flex flex-col items-center gap-4">
154
143
  <p className="text-5xl font-bold text-terminal sm:text-6xl">
@@ -160,8 +149,7 @@ export async function PricingPage() {
160
149
  <span className="text-terminal">✓</span> 2 GB RAM / 2 vCPU / 20 GB SSD
161
150
  </li>
162
151
  <li className="flex items-center gap-2">
163
- <span className="text-terminal">✓</span> Persistent container — data survives
164
- restarts
152
+ <span className="text-terminal">✓</span> Persistent container — data survives restarts
165
153
  </li>
166
154
  <li className="flex items-center gap-2">
167
155
  <span className="text-terminal">✓</span> Dedicated hostname
@@ -173,12 +161,7 @@ export async function PricingPage() {
173
161
  <span className="text-terminal">✓</span> Flat monthly price — no metered compute
174
162
  </li>
175
163
  </ul>
176
- <Button
177
- data-onboarding-id="pricing.subscribe.vps"
178
- variant="terminal"
179
- className="w-full"
180
- asChild
181
- >
164
+ <Button data-onboarding-id="pricing.subscribe.vps" variant="terminal" className="w-full" asChild>
182
165
  <Link href="/signup">Get started</Link>
183
166
  </Button>
184
167
  </CardContent>
@@ -189,8 +172,8 @@ export async function PricingPage() {
189
172
  {/* --- Credits Explainer --- */}
190
173
  <section className="flex flex-col items-center justify-center gap-6 px-6 pb-24 text-center">
191
174
  <p className="max-w-lg text-lg text-muted-foreground">
192
- Your bot is ${pricingData.bot_price.amount}/mo. Usage is billed from credits. Free tier
193
- includes ${pricingData.signup_credit} signup credit.
175
+ Your bot is ${pricingData.bot_price.amount}/mo. Usage is billed from credits. Free tier includes $
176
+ {pricingData.signup_credit} signup credit.
194
177
  </p>
195
178
  <p className="text-sm text-muted-foreground">
196
179
  Credits in, dividend back. The community grows, your costs shrink.
@@ -207,9 +190,7 @@ export async function PricingPage() {
207
190
  <Link href="/signup">Get Started</Link>
208
191
  </Button>
209
192
 
210
- <span className="mt-4 text-sm text-muted-foreground opacity-60">
211
- {getBrandConfig().domain}
212
- </span>
193
+ <span className="mt-4 text-sm text-muted-foreground opacity-60">{getBrandConfig().domain}</span>
213
194
  </section>
214
195
 
215
196
  {/* --- Footer --- */}
@@ -155,9 +155,7 @@ export default function CreateOrgWizard() {
155
155
  >
156
156
  <DialogHeader>
157
157
  <DialogTitle>Confirm</DialogTitle>
158
- <DialogDescription>
159
- You{"'"}ll be the admin. You can invite members after setup.
160
- </DialogDescription>
158
+ <DialogDescription>You{"'"}ll be the admin. You can invite members after setup.</DialogDescription>
161
159
  </DialogHeader>
162
160
  <div className="mt-4 space-y-3">
163
161
  <div className="rounded-md border px-4 py-3 text-sm">
@@ -165,8 +163,7 @@ export default function CreateOrgWizard() {
165
163
  <span className="text-muted-foreground">Name:</span> <strong>{orgName}</strong>
166
164
  </p>
167
165
  <p>
168
- <span className="text-muted-foreground">Slug:</span>{" "}
169
- <code className="text-xs">{slug}</code>
166
+ <span className="text-muted-foreground">Slug:</span> <code className="text-xs">{slug}</code>
170
167
  </p>
171
168
  </div>
172
169
  {error && <p className="text-sm text-destructive">{error}</p>}
@@ -20,8 +20,8 @@ import {
20
20
  import Image from "next/image";
21
21
  import Link from "next/link";
22
22
  import { usePathname, useRouter } from "next/navigation";
23
- import { useCallback, useEffect, useState } from "react";
24
23
  import { AccountSwitcher } from "@/components/account-switcher";
24
+ import { CreditBalanceBadge } from "@/components/billing/credit-balance-badge";
25
25
  import {
26
26
  DropdownMenu,
27
27
  DropdownMenuContent,
@@ -31,10 +31,8 @@ import {
31
31
  DropdownMenuTrigger,
32
32
  } from "@/components/ui/dropdown-menu";
33
33
  import { Skeleton } from "@/components/ui/skeleton";
34
- import { getCreditBalance } from "@/lib/api";
35
34
  import { signOut, useSession } from "@/lib/auth-client";
36
35
  import { getBrandConfig, productName } from "@/lib/brand-config";
37
- import { formatCreditStandard } from "@/lib/format-credit";
38
36
  import { cn } from "@/lib/utils";
39
37
 
40
38
  function getNavItems() {
@@ -44,21 +42,13 @@ function getNavItems() {
44
42
  function isNavActive(href: string, pathname: string): boolean {
45
43
  if (href === "/dashboard") return pathname === "/dashboard";
46
44
  if (href === "/marketplace") return pathname === "/marketplace";
47
- if (href === "/settings/profile") return pathname.startsWith("/settings");
48
- if (href === "/billing/plans")
49
- return pathname.startsWith("/billing") && !pathname.startsWith("/billing/credits");
45
+ if (href === "/settings") return pathname.startsWith("/settings");
46
+ if (href === "/billing/plans") return pathname.startsWith("/billing") && !pathname.startsWith("/billing/credits");
50
47
  if (href === "/billing/credits") return pathname.startsWith("/billing/credits");
51
48
  if (href === "/admin/tenants" || href === "/admin") return pathname.startsWith("/admin");
52
49
  return pathname.startsWith(href);
53
50
  }
54
51
 
55
- function balanceColorClass(balance: number): string {
56
- if (balance === 0) return "text-red-500";
57
- if (balance < 1) return "text-red-500";
58
- if (balance <= 2) return "text-amber-500";
59
- return "text-terminal";
60
- }
61
-
62
52
  function getInitials(name: string): string {
63
53
  return name
64
54
  .split(" ")
@@ -90,23 +80,9 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
90
80
  const pathname = usePathname();
91
81
  const router = useRouter();
92
82
  const { data: session, isPending } = useSession();
93
- const [creditBalance, setCreditBalance] = useState<number | null>(null);
94
83
 
95
84
  const user = session?.user;
96
85
 
97
- const loadBalance = useCallback(async () => {
98
- try {
99
- const data = await getCreditBalance();
100
- setCreditBalance(data.balance);
101
- } catch {
102
- // Silently fail — balance is non-critical UI decoration
103
- }
104
- }, []);
105
-
106
- useEffect(() => {
107
- if (user) loadBalance();
108
- }, [user, loadBalance]);
109
-
110
86
  async function handleSignOut() {
111
87
  try {
112
88
  await signOut();
@@ -131,8 +107,7 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
131
107
  {getNavItems()
132
108
  .filter(
133
109
  (item) =>
134
- !item.href.startsWith("/admin") ||
135
- (user as { role?: string } | undefined)?.role === "platform_admin",
110
+ !item.href.startsWith("/admin") || (user as { role?: string } | undefined)?.role === "platform_admin",
136
111
  )
137
112
  .map((item) => {
138
113
  const NavIcon = getNavIcon(item.href);
@@ -153,11 +128,7 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
153
128
  {NavIcon && <NavIcon className="size-4 shrink-0 opacity-70" />}
154
129
  {item.label}
155
130
  </span>
156
- {item.label === "Credits" && creditBalance !== null && (
157
- <span className={cn("text-xs font-mono", balanceColorClass(creditBalance))}>
158
- {formatCreditStandard(creditBalance)}
159
- </span>
160
- )}
131
+ {item.label === "Credits" && <CreditBalanceBadge />}
161
132
  </Link>
162
133
  );
163
134
  })}
@@ -190,17 +161,11 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
190
161
  <DropdownMenuLabel className="font-normal">
191
162
  <div className="flex flex-col gap-1">
192
163
  {user.name && <span className="text-sm font-medium">{user.name}</span>}
193
- {user.email && (
194
- <span className="text-xs text-muted-foreground">{user.email}</span>
195
- )}
164
+ {user.email && <span className="text-xs text-muted-foreground">{user.email}</span>}
196
165
  </div>
197
166
  </DropdownMenuLabel>
198
167
  <DropdownMenuSeparator />
199
- <DropdownMenuItem onClick={() => router.push("/settings/profile")}>
200
- <UserIcon />
201
- Profile
202
- </DropdownMenuItem>
203
- <DropdownMenuItem onClick={() => router.push("/settings/providers")}>
168
+ <DropdownMenuItem onClick={() => router.push("/settings")}>
204
169
  <SettingsIcon />
205
170
  Settings
206
171
  </DropdownMenuItem>
@@ -0,0 +1,78 @@
1
+ "use client";
2
+
3
+ import { usePathname } from "next/navigation";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { Skeleton } from "@/components/ui/skeleton";
6
+ import { useSidecarBridge } from "@/hooks/use-sidecar-bridge";
7
+ import { getRouteType } from "@/lib/sidecar-routes";
8
+
9
+ /**
10
+ * Build the iframe src. For deep-link paths (non-/dashboard iframe routes),
11
+ * pass the path as an `initial-path` query so the sidecar's root redirect
12
+ * can land on the right page directly instead of racing with the shell's
13
+ * postMessage forwarding. See CompanyRootRedirect on the sidecar side.
14
+ */
15
+ function buildIframeSrc(): string {
16
+ if (typeof window === "undefined") return "/_sidecar/";
17
+ const pathname = window.location.pathname;
18
+ if (getRouteType(pathname) !== "iframe" || pathname === "/dashboard") return "/_sidecar/";
19
+ const initialPath = pathname + window.location.search + window.location.hash;
20
+ return `/_sidecar/?initial-path=${encodeURIComponent(initialPath)}`;
21
+ }
22
+
23
+ export function SidecarFrame() {
24
+ // iframe loads /_sidecar/ — core API's tenant-proxy resolves the user's instance
25
+ const { setIframeRef, navigate } = useSidecarBridge();
26
+ const pathname = usePathname();
27
+ const iframeElRef = useRef<HTMLIFrameElement>(null);
28
+ const [iframeLoaded, setIframeLoaded] = useState(false);
29
+ // Stable across re-renders: computed once from the shell's initial URL so
30
+ // the iframe doesn't reload when the shell URL changes post-routeChanged.
31
+ const [iframeSrc] = useState(buildIframeSrc);
32
+
33
+ const routeType = getRouteType(pathname);
34
+ const isVisible = routeType === "iframe";
35
+
36
+ // Register iframe ref with bridge
37
+ useEffect(() => {
38
+ setIframeRef(iframeElRef.current);
39
+ return () => setIframeRef(null);
40
+ }, [setIframeRef]);
41
+
42
+ // Handle browser back/forward
43
+ useEffect(() => {
44
+ function onPopState() {
45
+ const newPath = window.location.pathname;
46
+ if (getRouteType(newPath) === "iframe") {
47
+ navigate(newPath);
48
+ }
49
+ }
50
+ window.addEventListener("popstate", onPopState);
51
+ return () => window.removeEventListener("popstate", onPopState);
52
+ }, [navigate]);
53
+
54
+ return (
55
+ <div className="relative flex-1 min-h-0" style={{ display: isVisible ? "flex" : "none" }}>
56
+ {/* Loading skeleton until sidecar posts "ready" */}
57
+ {isVisible && !iframeLoaded && (
58
+ <div className="absolute inset-0 flex flex-col gap-4 p-6">
59
+ <Skeleton className="h-8 w-64" />
60
+ <Skeleton className="h-4 w-96" />
61
+ <div className="flex gap-4 mt-4">
62
+ <Skeleton className="h-32 w-64" />
63
+ <Skeleton className="h-32 w-64" />
64
+ <Skeleton className="h-32 w-64" />
65
+ </div>
66
+ </div>
67
+ )}
68
+ <iframe
69
+ ref={iframeElRef}
70
+ src={iframeSrc}
71
+ title="Paperclip"
72
+ className="h-full w-full border-0"
73
+ onLoad={() => setIframeLoaded(true)}
74
+ allow="clipboard-write"
75
+ />
76
+ </div>
77
+ );
78
+ }
@@ -17,10 +17,7 @@ const STATUS_LABELS: Record<HealthStatus, string> = {
17
17
  unhealthy: "Down",
18
18
  };
19
19
 
20
- const BANNER_CONFIG: Record<
21
- HealthStatus,
22
- { text: string; border: string; bg: string; textColor: string }
23
- > = {
20
+ const BANNER_CONFIG: Record<HealthStatus, { text: string; border: string; bg: string; textColor: string }> = {
24
21
  healthy: {
25
22
  text: "> ALL SYSTEMS OPERATIONAL",
26
23
  border: "border-terminal/20",
@@ -96,9 +93,7 @@ export function StatusPage() {
96
93
  <div className="mx-auto max-w-2xl px-6 py-16">
97
94
  <div className="space-y-1">
98
95
  <h1 className="text-2xl font-bold tracking-tight">Platform Status</h1>
99
- <p className="text-sm text-muted-foreground">
100
- Real-time health of the {brandName()} platform.
101
- </p>
96
+ <p className="text-sm text-muted-foreground">Real-time health of the {brandName()} platform.</p>
102
97
  </div>
103
98
 
104
99
  <div className="mt-8 space-y-6">
@@ -116,9 +111,7 @@ export function StatusPage() {
116
111
  <div className="flex items-center gap-3">
117
112
  <XCircle className="size-5 shrink-0 text-red-500" />
118
113
  <div className="flex-1">
119
- <p className="text-sm font-medium text-red-500">
120
- Unable to reach the {brandName()} platform
121
- </p>
114
+ <p className="text-sm font-medium text-red-500">Unable to reach the {brandName()} platform</p>
122
115
  <p className="mt-1 text-xs text-muted-foreground">
123
116
  The health endpoint is not responding. The platform may be experiencing an outage.
124
117
  </p>
@@ -136,14 +129,7 @@ export function StatusPage() {
136
129
  {(() => {
137
130
  const cfg = BANNER_CONFIG[health.status];
138
131
  return (
139
- <div
140
- className={cn(
141
- "rounded-sm border px-4 py-2 text-sm font-mono",
142
- cfg.border,
143
- cfg.bg,
144
- cfg.textColor,
145
- )}
146
- >
132
+ <div className={cn("rounded-sm border px-4 py-2 text-sm font-mono", cfg.border, cfg.bg, cfg.textColor)}>
147
133
  {cfg.text}
148
134
  </div>
149
135
  );
@@ -160,9 +146,7 @@ export function StatusPage() {
160
146
  </div>
161
147
  <div className="flex items-center gap-3">
162
148
  {svc.latencyMs !== null && (
163
- <span className="text-xs font-mono text-muted-foreground">
164
- {svc.latencyMs}ms
165
- </span>
149
+ <span className="text-xs font-mono text-muted-foreground">{svc.latencyMs}ms</span>
166
150
  )}
167
151
  <div className="flex items-center gap-1.5">
168
152
  <StatusIcon status={svc.status} />
@@ -190,13 +174,7 @@ export function StatusPage() {
190
174
  </div>
191
175
  <div className="flex items-center gap-2">
192
176
  {lastChecked && <span>checked {lastChecked.toLocaleTimeString()}</span>}
193
- <Button
194
- variant="ghost"
195
- size="sm"
196
- className="h-6 px-2"
197
- onClick={load}
198
- disabled={refreshing}
199
- >
177
+ <Button variant="ghost" size="sm" className="h-6 px-2" onClick={load} disabled={refreshing}>
200
178
  <RefreshCw className={cn("size-3", refreshing && "animate-spin")} />
201
179
  </Button>
202
180
  </div>
@@ -9,9 +9,7 @@ function AlertDialog({ ...props }: React.ComponentProps<typeof AlertDialogPrimit
9
9
  return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
10
10
  }
11
11
 
12
- function AlertDialogTrigger({
13
- ...props
14
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
12
+ function AlertDialogTrigger({ ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
15
13
  return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
16
14
  }
17
15
 
@@ -19,15 +17,12 @@ function AlertDialogPortal({ ...props }: React.ComponentProps<typeof AlertDialog
19
17
  return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
20
18
  }
21
19
 
22
- function AlertDialogOverlay({
23
- className,
24
- ...props
25
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
20
+ function AlertDialogOverlay({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
26
21
  return (
27
22
  <AlertDialogPrimitive.Overlay
28
23
  data-slot="alert-dialog-overlay"
29
24
  className={cn(
30
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
25
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80 backdrop-blur-sm",
31
26
  className,
32
27
  )}
33
28
  {...props}
@@ -35,17 +30,14 @@ function AlertDialogOverlay({
35
30
  );
36
31
  }
37
32
 
38
- function AlertDialogContent({
39
- className,
40
- ...props
41
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
33
+ function AlertDialogContent({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
42
34
  return (
43
35
  <AlertDialogPortal>
44
36
  <AlertDialogOverlay />
45
37
  <AlertDialogPrimitive.Content
46
38
  data-slot="alert-dialog-content"
47
39
  className={cn(
48
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
40
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg border p-6 shadow-lg duration-200",
49
41
  className,
50
42
  )}
51
43
  {...props}
@@ -74,10 +66,7 @@ function AlertDialogFooter({ className, ...props }: React.ComponentProps<"div">)
74
66
  );
75
67
  }
76
68
 
77
- function AlertDialogTitle({
78
- className,
79
- ...props
80
- }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
69
+ function AlertDialogTitle({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
81
70
  return (
82
71
  <AlertDialogPrimitive.Title
83
72
  data-slot="alert-dialog-title"
@@ -100,10 +89,7 @@ function AlertDialogDescription({
100
89
  );
101
90
  }
102
91
 
103
- function AlertDialogAction({
104
- className,
105
- ...props
106
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
92
+ function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
107
93
  return (
108
94
  <AlertDialogPrimitive.Action
109
95
  data-slot="alert-dialog-action"
@@ -113,10 +99,7 @@ function AlertDialogAction({
113
99
  );
114
100
  }
115
101
 
116
- function AlertDialogCancel({
117
- className,
118
- ...props
119
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
102
+ function AlertDialogCancel({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
120
103
  return (
121
104
  <AlertDialogPrimitive.Cancel
122
105
  data-slot="alert-dialog-cancel"
@@ -13,8 +13,7 @@ const badgeVariants = cva(
13
13
  secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
14
14
  destructive:
15
15
  "bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
16
- outline:
17
- "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
16
+ outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
18
17
  ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
19
18
  link: "text-primary underline-offset-4 [a&]:hover:underline",
20
19
  terminal: "border-terminal text-terminal bg-terminal/10 [a&]:hover:bg-terminal/20",
@@ -35,12 +34,7 @@ function Badge({
35
34
  const Comp = asChild ? Slot.Root : "span";
36
35
 
37
36
  return (
38
- <Comp
39
- data-slot="badge"
40
- data-variant={variant}
41
- className={cn(badgeVariants({ variant }), className)}
42
- {...props}
43
- />
37
+ <Comp data-slot="badge" data-variant={variant} className={cn(badgeVariants({ variant }), className)} {...props} />
44
38
  );
45
39
  }
46
40
 
@@ -24,12 +24,7 @@ function Banner({
24
24
  ...props
25
25
  }: React.ComponentProps<"div"> & VariantProps<typeof bannerVariants>) {
26
26
  return (
27
- <div
28
- data-slot="banner"
29
- data-variant={variant}
30
- className={cn(bannerVariants({ variant, className }))}
31
- {...props}
32
- />
27
+ <div data-slot="banner" data-variant={variant} className={cn(bannerVariants({ variant, className }))} {...props} />
33
28
  );
34
29
  }
35
30