@locusai/web 0.1.7 → 0.2.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 (346) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/next.config.js +15 -2
  3. package/package.json +26 -3
  4. package/src/app/(auth)/invite/page.tsx +109 -0
  5. package/src/app/(auth)/layout.tsx +19 -0
  6. package/src/app/(auth)/login/page.tsx +65 -0
  7. package/src/app/(auth)/onboarding/workspace/page.tsx +46 -0
  8. package/src/app/(auth)/register/page.tsx +165 -0
  9. package/src/app/(dashboard)/activity/page.tsx +7 -0
  10. package/src/app/(dashboard)/backlog/page.tsx +195 -0
  11. package/src/app/(dashboard)/board/page.tsx +141 -0
  12. package/src/app/(dashboard)/layout.tsx +32 -0
  13. package/src/app/(dashboard)/page.tsx +14 -0
  14. package/src/app/(dashboard)/settings/page.tsx +161 -0
  15. package/src/app/(dashboard)/settings/team/page.tsx +75 -0
  16. package/src/app/globals.css +259 -0
  17. package/src/app/layout.tsx +10 -20
  18. package/src/app/providers.tsx +26 -3
  19. package/src/components/AuthLayoutUI.tsx +53 -0
  20. package/src/components/BoardFilter.tsx +75 -74
  21. package/src/components/CreateModal/CreateModal.tsx +142 -0
  22. package/src/components/CreateModal/index.ts +1 -0
  23. package/src/components/Editor.tsx +279 -0
  24. package/src/components/Header.tsx +99 -12
  25. package/src/components/PageLayout.tsx +69 -0
  26. package/src/components/PropertyItem.tsx +55 -9
  27. package/src/components/Sidebar.tsx +280 -36
  28. package/src/components/SprintCreateModal.tsx +84 -0
  29. package/src/components/TaskCard.tsx +196 -78
  30. package/src/components/TaskCreateModal.tsx +181 -178
  31. package/src/components/TaskPanel.tsx +140 -692
  32. package/src/components/WorkspaceCreateModal.tsx +97 -0
  33. package/src/components/WorkspaceProtected.tsx +91 -0
  34. package/src/components/auth/InviteSteps.tsx +220 -0
  35. package/src/components/auth/LoginSteps.tsx +86 -0
  36. package/src/components/auth/RegisterSteps.tsx +371 -0
  37. package/src/components/auth/index.ts +3 -0
  38. package/src/components/backlog/BacklogList.tsx +92 -0
  39. package/src/components/backlog/BacklogSection.tsx +137 -0
  40. package/src/components/backlog/CompletedSprintItem.tsx +95 -0
  41. package/src/components/backlog/CompletedSprintsSection.tsx +77 -0
  42. package/src/components/backlog/SprintSection.tsx +155 -0
  43. package/src/components/backlog/constants.ts +26 -0
  44. package/src/components/board/BoardColumn.tsx +97 -0
  45. package/src/components/board/BoardContent.tsx +84 -0
  46. package/src/components/board/BoardEmptyState.tsx +82 -0
  47. package/src/components/board/BoardHeader.tsx +47 -0
  48. package/src/components/board/SprintMindmap.tsx +65 -0
  49. package/src/components/board/constants.ts +40 -0
  50. package/src/components/board/index.ts +5 -0
  51. package/src/components/common/ErrorState.tsx +124 -0
  52. package/src/components/common/LoadingState.tsx +83 -0
  53. package/src/components/common/index.ts +40 -0
  54. package/src/components/dashboard/ActivityFeed.tsx +77 -0
  55. package/src/components/dashboard/ActivityItem.tsx +207 -0
  56. package/src/components/dashboard/QuickActions.tsx +50 -0
  57. package/src/components/dashboard/StatCard.tsx +79 -0
  58. package/src/components/dnd/index.tsx +51 -0
  59. package/src/components/docs/DocsEditorArea.tsx +87 -0
  60. package/src/components/docs/DocsHeaderActions.tsx +121 -0
  61. package/src/components/docs/DocsSidebar.tsx +351 -0
  62. package/src/components/index.ts +7 -0
  63. package/src/components/onboarding/StepProgress.tsx +21 -0
  64. package/src/components/onboarding/index.ts +1 -0
  65. package/src/components/settings/ApiKeyConfirmationModal.tsx +81 -0
  66. package/src/components/settings/ApiKeyCreatedModal.tsx +96 -0
  67. package/src/components/settings/ApiKeysList.tsx +143 -0
  68. package/src/components/settings/ApiKeysSettings.tsx +144 -0
  69. package/src/components/settings/InviteMemberModal.tsx +106 -0
  70. package/src/components/settings/ProjectSetupGuide.tsx +147 -0
  71. package/src/components/settings/SettingItem.tsx +32 -0
  72. package/src/components/settings/SettingSection.tsx +50 -0
  73. package/src/components/settings/TeamInvitationsList.tsx +90 -0
  74. package/src/components/settings/TeamMembersList.tsx +95 -0
  75. package/src/components/settings/index.ts +8 -0
  76. package/src/components/task-panel/TaskActivity.tsx +127 -0
  77. package/src/components/task-panel/TaskChecklist.tsx +142 -0
  78. package/src/components/task-panel/TaskDescription.tsx +201 -0
  79. package/src/components/task-panel/TaskDocs.tsx +137 -0
  80. package/src/components/task-panel/TaskHeader.tsx +125 -0
  81. package/src/components/task-panel/TaskProperties.tsx +111 -0
  82. package/src/components/task-panel/index.ts +12 -0
  83. package/src/components/typography/EmptyStateText.tsx +59 -0
  84. package/src/components/typography/MetadataText.tsx +65 -0
  85. package/src/components/typography/SecondaryText.tsx +60 -0
  86. package/src/components/typography/SectionLabel.tsx +60 -0
  87. package/src/components/typography/index.ts +14 -0
  88. package/src/components/typography-scales.tsx +218 -0
  89. package/src/components/ui/Avatar.tsx +123 -0
  90. package/src/components/ui/Badge.tsx +69 -2
  91. package/src/components/ui/Button.tsx +71 -30
  92. package/src/components/ui/Checkbox.tsx +34 -0
  93. package/src/components/ui/Dropdown.tsx +67 -1
  94. package/src/components/ui/EmptyState.tsx +129 -0
  95. package/src/components/ui/Input.tsx +53 -6
  96. package/src/components/ui/Modal.tsx +45 -12
  97. package/src/components/ui/OtpInput.tsx +148 -0
  98. package/src/components/ui/Skeleton.tsx +36 -0
  99. package/src/components/ui/Spinner.tsx +112 -0
  100. package/src/components/ui/Textarea.tsx +28 -3
  101. package/src/components/ui/Toast.tsx +99 -0
  102. package/src/components/ui/Toggle.tsx +63 -0
  103. package/src/components/ui/constants.ts +108 -0
  104. package/src/components/ui/index.ts +7 -0
  105. package/src/context/AuthContext.tsx +140 -0
  106. package/src/context/index.ts +1 -0
  107. package/src/hooks/backlog/index.ts +13 -0
  108. package/src/hooks/backlog/useBacklogActions.ts +144 -0
  109. package/src/hooks/backlog/useBacklogComposite.ts +73 -0
  110. package/src/hooks/backlog/useBacklogData.ts +74 -0
  111. package/src/hooks/backlog/useBacklogDragDrop.ts +118 -0
  112. package/src/hooks/backlog/useBacklogUI.ts +74 -0
  113. package/src/hooks/index.ts +22 -0
  114. package/src/hooks/task-panel/index.ts +13 -0
  115. package/src/hooks/task-panel/useTaskActions.ts +200 -0
  116. package/src/hooks/task-panel/useTaskComputedValues.ts +30 -0
  117. package/src/hooks/task-panel/useTaskData.ts +78 -0
  118. package/src/hooks/task-panel/useTaskPanelComposite.ts +161 -0
  119. package/src/hooks/task-panel/useTaskUIState.ts +80 -0
  120. package/src/hooks/useAuthLayoutLogic.ts +43 -0
  121. package/src/hooks/useAuthenticatedUser.ts +36 -0
  122. package/src/hooks/useAuthenticatedUserWithOrg.ts +41 -0
  123. package/src/hooks/useBacklog.ts +303 -0
  124. package/src/hooks/useBoard.ts +230 -0
  125. package/src/hooks/useDashboardLayout.ts +49 -0
  126. package/src/hooks/useDocs.ts +279 -0
  127. package/src/hooks/useDocsQuery.ts +99 -0
  128. package/src/hooks/useDocsSidebarState.ts +104 -0
  129. package/src/hooks/useFormState.ts +40 -0
  130. package/src/hooks/useGlobalKeydowns.ts +52 -0
  131. package/src/hooks/useInviteForm.ts +122 -0
  132. package/src/hooks/useLoginForm.ts +84 -0
  133. package/src/hooks/useMutationWithToast.ts +56 -0
  134. package/src/hooks/useOrganizationQuery.ts +55 -0
  135. package/src/hooks/useRegisterForm.ts +216 -0
  136. package/src/hooks/useSprintsQuery.ts +38 -0
  137. package/src/hooks/useTaskDescription.ts +102 -0
  138. package/src/hooks/useTaskPanel.ts +341 -0
  139. package/src/hooks/useTasksQuery.ts +39 -0
  140. package/src/hooks/useTeamManagement.ts +92 -0
  141. package/src/hooks/useWorkspaceCreateForm.ts +70 -0
  142. package/src/hooks/useWorkspaceId.ts +29 -0
  143. package/src/lib/api-client.ts +40 -23
  144. package/src/lib/config.ts +25 -0
  145. package/src/lib/constants.ts +83 -0
  146. package/src/lib/options.ts +96 -0
  147. package/src/lib/query-keys.ts +91 -0
  148. package/src/lib/typography.ts +103 -0
  149. package/src/lib/utils.ts +4 -0
  150. package/src/lib/validation.ts +192 -0
  151. package/src/services/index.ts +7 -3
  152. package/src/services/notifications.ts +80 -0
  153. package/src/utils/env.utils.ts +15 -0
  154. package/src/views/ActivityView.tsx +123 -0
  155. package/src/views/Dashboard.tsx +126 -0
  156. package/src/views/Docs.tsx +98 -612
  157. package/tsconfig.tsbuildinfo +1 -1
  158. package/.next/BUILD_ID +0 -1
  159. package/.next/app-build-manifest.json +0 -55
  160. package/.next/app-path-routes-manifest.json +0 -8
  161. package/.next/build-manifest.json +0 -33
  162. package/.next/cache/.previewinfo +0 -1
  163. package/.next/cache/.rscinfo +0 -1
  164. package/.next/cache/.tsbuildinfo +0 -1
  165. package/.next/cache/config.json +0 -7
  166. package/.next/cache/webpack/client-production/0.pack +0 -0
  167. package/.next/cache/webpack/client-production/index.pack +0 -0
  168. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  169. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  170. package/.next/cache/webpack/server-production/0.pack +0 -0
  171. package/.next/cache/webpack/server-production/index.pack +0 -0
  172. package/.next/diagnostics/build-diagnostics.json +0 -6
  173. package/.next/diagnostics/framework.json +0 -1
  174. package/.next/export-detail.json +0 -5
  175. package/.next/export-marker.json +0 -6
  176. package/.next/images-manifest.json +0 -57
  177. package/.next/next-minimal-server.js.nft.json +0 -1
  178. package/.next/next-server.js.nft.json +0 -1
  179. package/.next/package.json +0 -1
  180. package/.next/prerender-manifest.json +0 -137
  181. package/.next/react-loadable-manifest.json +0 -32
  182. package/.next/required-server-files.json +0 -324
  183. package/.next/routes-manifest.json +0 -77
  184. package/.next/server/app/_not-found/page.js +0 -2
  185. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  186. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  187. package/.next/server/app/_not-found.html +0 -1
  188. package/.next/server/app/_not-found.meta +0 -8
  189. package/.next/server/app/_not-found.rsc +0 -21
  190. package/.next/server/app/backlog/page.js +0 -2
  191. package/.next/server/app/backlog/page.js.nft.json +0 -1
  192. package/.next/server/app/backlog/page_client-reference-manifest.js +0 -1
  193. package/.next/server/app/backlog.html +0 -1
  194. package/.next/server/app/backlog.meta +0 -7
  195. package/.next/server/app/backlog.rsc +0 -25
  196. package/.next/server/app/docs/page.js +0 -97
  197. package/.next/server/app/docs/page.js.nft.json +0 -1
  198. package/.next/server/app/docs/page_client-reference-manifest.js +0 -1
  199. package/.next/server/app/docs.html +0 -1
  200. package/.next/server/app/docs.meta +0 -7
  201. package/.next/server/app/docs.rsc +0 -26
  202. package/.next/server/app/favicon.ico/route.js +0 -1
  203. package/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  204. package/.next/server/app/favicon.ico.body +0 -0
  205. package/.next/server/app/favicon.ico.meta +0 -1
  206. package/.next/server/app/index.html +0 -1
  207. package/.next/server/app/index.meta +0 -7
  208. package/.next/server/app/index.rsc +0 -25
  209. package/.next/server/app/page.js +0 -2
  210. package/.next/server/app/page.js.nft.json +0 -1
  211. package/.next/server/app/page_client-reference-manifest.js +0 -1
  212. package/.next/server/app/settings/page.js +0 -2
  213. package/.next/server/app/settings/page.js.nft.json +0 -1
  214. package/.next/server/app/settings/page_client-reference-manifest.js +0 -1
  215. package/.next/server/app/settings.html +0 -1
  216. package/.next/server/app/settings.meta +0 -7
  217. package/.next/server/app/settings.rsc +0 -25
  218. package/.next/server/app-paths-manifest.json +0 -8
  219. package/.next/server/chunks/496.js +0 -6
  220. package/.next/server/chunks/585.js +0 -1
  221. package/.next/server/chunks/665.js +0 -1
  222. package/.next/server/chunks/699.js +0 -22
  223. package/.next/server/chunks/852.js +0 -7
  224. package/.next/server/functions-config-manifest.json +0 -4
  225. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  226. package/.next/server/middleware-build-manifest.js +0 -1
  227. package/.next/server/middleware-manifest.json +0 -6
  228. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  229. package/.next/server/next-font-manifest.js +0 -1
  230. package/.next/server/next-font-manifest.json +0 -1
  231. package/.next/server/pages/404.html +0 -1
  232. package/.next/server/pages/500.html +0 -1
  233. package/.next/server/pages/_app.js +0 -1
  234. package/.next/server/pages/_app.js.nft.json +0 -1
  235. package/.next/server/pages/_document.js +0 -1
  236. package/.next/server/pages/_document.js.nft.json +0 -1
  237. package/.next/server/pages/_error.js +0 -19
  238. package/.next/server/pages/_error.js.nft.json +0 -1
  239. package/.next/server/pages-manifest.json +0 -6
  240. package/.next/server/server-reference-manifest.js +0 -1
  241. package/.next/server/server-reference-manifest.json +0 -1
  242. package/.next/server/webpack-runtime.js +0 -1
  243. package/.next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
  244. package/.next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
  245. package/.next/static/chunks/138.b98511c56423f8bb.js +0 -1
  246. package/.next/static/chunks/146-34259952c594a3b0.js +0 -1
  247. package/.next/static/chunks/337-d3bb75304d130513.js +0 -1
  248. package/.next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
  249. package/.next/static/chunks/487-1808785ba665f784.js +0 -1
  250. package/.next/static/chunks/544.a9569941cc886e9d.js +0 -1
  251. package/.next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
  252. package/.next/static/chunks/902-d6926825a9fe8784.js +0 -1
  253. package/.next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
  254. package/.next/static/chunks/996.e0a334e6ae90900e.js +0 -1
  255. package/.next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
  256. package/.next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
  257. package/.next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
  258. package/.next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
  259. package/.next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
  260. package/.next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
  261. package/.next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
  262. package/.next/static/chunks/main-843ab130fc1be309.js +0 -1
  263. package/.next/static/chunks/main-app-123e879c5a937a00.js +0 -1
  264. package/.next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
  265. package/.next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
  266. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  267. package/.next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
  268. package/.next/static/css/13e8617b72f9d3aa.css +0 -1
  269. package/.next/static/css/8aea088cdc4338f0.css +0 -1
  270. package/.next/static/css/b301ab0424111664.css +0 -1
  271. package/.next/static/media/24c15609eaa28576-s.woff2 +0 -0
  272. package/.next/static/media/2c07349e02a7b712-s.woff2 +0 -0
  273. package/.next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
  274. package/.next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
  275. package/.next/static/media/4f77bef990aad698-s.woff2 +0 -0
  276. package/.next/static/media/627d916fd739a539-s.woff2 +0 -0
  277. package/.next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
  278. package/.next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
  279. package/.next/static/media/84602850c8fd81c3-s.woff2 +0 -0
  280. package/.next/trace +0 -46
  281. package/.next/types/app/backlog/page.ts +0 -84
  282. package/.next/types/app/docs/page.ts +0 -84
  283. package/.next/types/app/layout.ts +0 -84
  284. package/.next/types/app/page.ts +0 -84
  285. package/.next/types/app/settings/page.ts +0 -84
  286. package/.next/types/cache-life.d.ts +0 -141
  287. package/.next/types/package.json +0 -1
  288. package/next-env.d.ts +0 -5
  289. package/out/404.html +0 -1
  290. package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
  291. package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
  292. package/out/_next/static/chunks/138.b98511c56423f8bb.js +0 -1
  293. package/out/_next/static/chunks/146-34259952c594a3b0.js +0 -1
  294. package/out/_next/static/chunks/337-d3bb75304d130513.js +0 -1
  295. package/out/_next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
  296. package/out/_next/static/chunks/487-1808785ba665f784.js +0 -1
  297. package/out/_next/static/chunks/544.a9569941cc886e9d.js +0 -1
  298. package/out/_next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
  299. package/out/_next/static/chunks/902-d6926825a9fe8784.js +0 -1
  300. package/out/_next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
  301. package/out/_next/static/chunks/996.e0a334e6ae90900e.js +0 -1
  302. package/out/_next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
  303. package/out/_next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
  304. package/out/_next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
  305. package/out/_next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
  306. package/out/_next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
  307. package/out/_next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
  308. package/out/_next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
  309. package/out/_next/static/chunks/main-843ab130fc1be309.js +0 -1
  310. package/out/_next/static/chunks/main-app-123e879c5a937a00.js +0 -1
  311. package/out/_next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
  312. package/out/_next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
  313. package/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  314. package/out/_next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
  315. package/out/_next/static/css/13e8617b72f9d3aa.css +0 -1
  316. package/out/_next/static/css/8aea088cdc4338f0.css +0 -1
  317. package/out/_next/static/css/b301ab0424111664.css +0 -1
  318. package/out/_next/static/media/24c15609eaa28576-s.woff2 +0 -0
  319. package/out/_next/static/media/2c07349e02a7b712-s.woff2 +0 -0
  320. package/out/_next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
  321. package/out/_next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
  322. package/out/_next/static/media/4f77bef990aad698-s.woff2 +0 -0
  323. package/out/_next/static/media/627d916fd739a539-s.woff2 +0 -0
  324. package/out/_next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
  325. package/out/_next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
  326. package/out/_next/static/media/84602850c8fd81c3-s.woff2 +0 -0
  327. package/out/backlog.html +0 -1
  328. package/out/backlog.txt +0 -25
  329. package/out/docs.html +0 -1
  330. package/out/docs.txt +0 -26
  331. package/out/favicon.ico +0 -0
  332. package/out/index.html +0 -1
  333. package/out/index.txt +0 -25
  334. package/out/logo.png +0 -0
  335. package/out/settings.html +0 -1
  336. package/out/settings.txt +0 -25
  337. package/src/app/backlog/page.tsx +0 -19
  338. package/src/app/page.tsx +0 -16
  339. package/src/app/settings/page.tsx +0 -194
  340. package/src/hooks/useTasks.ts +0 -119
  341. package/src/services/doc.service.ts +0 -27
  342. package/src/services/sprint.service.ts +0 -24
  343. package/src/services/task.service.ts +0 -75
  344. package/src/views/Backlog.tsx +0 -691
  345. package/src/views/Board.tsx +0 -306
  346. /package/src/app/{docs → (dashboard)/docs}/page.tsx +0 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Task Properties Component
3
+ *
4
+ * Displays and allows editing of task metadata like status, priority, assignee, etc.
5
+ *
6
+ * @example
7
+ * <TaskProperties task={task} onUpdate={handleUpdate} />
8
+ */
9
+
10
+ "use client";
11
+
12
+ import {
13
+ AssigneeRole,
14
+ type Task,
15
+ TaskPriority,
16
+ TaskStatus,
17
+ } from "@locusai/shared";
18
+ import { format } from "date-fns";
19
+ import { PropertyItem, SectionLabel } from "@/components";
20
+
21
+ interface TaskPropertiesProps {
22
+ /** Task to display */
23
+ task: Task;
24
+ /** Whether a mutation is loading */
25
+ isLoading?: boolean;
26
+ /** Callback when task properties are updated */
27
+ onUpdate: (updates: Partial<Task>) => void;
28
+ }
29
+
30
+ /**
31
+ * Task Properties Component
32
+ *
33
+ * Features:
34
+ * - Editable status dropdown
35
+ * - Assignee role selection
36
+ * - Priority level
37
+ * - Due date picker
38
+ * - Operator/assignee field
39
+ *
40
+ * @component
41
+ */
42
+ export function TaskProperties({
43
+ task,
44
+ isLoading = false,
45
+ onUpdate,
46
+ }: TaskPropertiesProps) {
47
+ const formatDate = (date: string | number | Date) => {
48
+ return format(new Date(date), "MMM d, yyyy");
49
+ };
50
+
51
+ return (
52
+ <div className="mb-10">
53
+ <SectionLabel as="h4" className="mb-6 pb-2 border-b border-border/40">
54
+ Mission Specs
55
+ </SectionLabel>
56
+ <div className="space-y-3">
57
+ <PropertyItem
58
+ label="State"
59
+ value={task.status}
60
+ onEdit={(newValue: string) =>
61
+ onUpdate({ status: newValue as TaskStatus })
62
+ }
63
+ options={Object.values(TaskStatus)}
64
+ type="dropdown"
65
+ disabled={isLoading}
66
+ />
67
+ <PropertyItem
68
+ label="Role"
69
+ value={task.assigneeRole || "Unassigned"}
70
+ onEdit={(newValue: string) =>
71
+ onUpdate({
72
+ assigneeRole: newValue as AssigneeRole,
73
+ })
74
+ }
75
+ options={Object.values(AssigneeRole)}
76
+ type="dropdown"
77
+ disabled={isLoading}
78
+ />
79
+ <PropertyItem
80
+ label="Priority"
81
+ value={task.priority || TaskPriority.MEDIUM}
82
+ onEdit={(newValue: string) =>
83
+ onUpdate({ priority: newValue as TaskPriority })
84
+ }
85
+ options={Object.values(TaskPriority)}
86
+ type="dropdown"
87
+ disabled={isLoading}
88
+ />
89
+ <PropertyItem
90
+ label="Deadline"
91
+ value={task.dueDate ? formatDate(task.dueDate) : "Undetermined"}
92
+ onEdit={(newValue: string) =>
93
+ onUpdate({ dueDate: newValue ? new Date(newValue) : null })
94
+ }
95
+ type="date"
96
+ disabled={isLoading}
97
+ />
98
+ <PropertyItem
99
+ label="Operator"
100
+ value={task.assignedTo || "Available"}
101
+ onEdit={(newValue: string) =>
102
+ onUpdate({ assignedTo: newValue || null })
103
+ }
104
+ type="text"
105
+ disabled={isLoading}
106
+ placeholder="Enter operator name or ID"
107
+ />
108
+ </div>
109
+ </div>
110
+ );
111
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Task Panel Components
3
+ *
4
+ * Modular components for the task detail panel.
5
+ */
6
+
7
+ export * from "./TaskActivity";
8
+ export * from "./TaskChecklist";
9
+ export * from "./TaskDescription";
10
+ export * from "./TaskDocs";
11
+ export * from "./TaskHeader";
12
+ export * from "./TaskProperties";
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Empty State Text Component
3
+ *
4
+ * Displays text for empty states with proper styling and visibility.
5
+ * Replaces scattered custom empty state typography throughout UI.
6
+ *
7
+ * Usage: Replace inline `text-[9px] font-black uppercase tracking-[0.2em] opacity-30`
8
+ *
9
+ * @example
10
+ * <EmptyStateText>No items found</EmptyStateText>
11
+ * <EmptyStateText icon={<Box />}>Empty workspace</EmptyStateText>
12
+ */
13
+
14
+ "use client";
15
+
16
+ import React from "react";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ interface EmptyStateTextProps {
20
+ /** Text content */
21
+ children: React.ReactNode;
22
+ /** Optional icon to display */
23
+ icon?: React.ReactNode;
24
+ /** Optional className override */
25
+ className?: string;
26
+ }
27
+
28
+ /**
29
+ * Standardized empty state text component
30
+ *
31
+ * Features:
32
+ * - Proper contrast for empty states
33
+ * - Icon support
34
+ * - Readable but secondary appearance
35
+ * - Consistent spacing
36
+ * - Replaces scattered custom opacity patterns
37
+ *
38
+ * @component
39
+ */
40
+ export function EmptyStateText({
41
+ children,
42
+ icon,
43
+ className,
44
+ }: EmptyStateTextProps) {
45
+ return (
46
+ <div
47
+ className={cn(
48
+ "flex flex-col items-center justify-center",
49
+ "text-[9px] font-black uppercase tracking-[0.2em]",
50
+ "text-foreground/40",
51
+ "gap-2",
52
+ className
53
+ )}
54
+ >
55
+ {icon && <div className="text-foreground/30">{icon}</div>}
56
+ {children}
57
+ </div>
58
+ );
59
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Metadata Text Component
3
+ *
4
+ * Displays metadata, IDs, timestamps, or other secondary information.
5
+ * Replaces custom inline typography for technical info throughout UI.
6
+ *
7
+ * Usage: Replace inline `text-[8px] font-bold uppercase tracking-widest text-muted-foreground/50`
8
+ *
9
+ * @example
10
+ * <MetadataText>ID: abc-123</MetadataText>
11
+ * <MetadataText>Updated 2 hours ago</MetadataText>
12
+ */
13
+
14
+ "use client";
15
+
16
+ import React from "react";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ interface MetadataTextProps {
20
+ /** Metadata content */
21
+ children: React.ReactNode;
22
+ /** Size variant */
23
+ size?: "xs" | "sm";
24
+ /** Optional className override */
25
+ className?: string;
26
+ /** HTML element (default: div) */
27
+ as?: "div" | "span" | "p";
28
+ }
29
+
30
+ /**
31
+ * Standardized metadata text component
32
+ *
33
+ * Features:
34
+ * - Smaller text for secondary metadata
35
+ * - Readable yet de-emphasized (60% opacity)
36
+ * - Wide letter spacing for technical info
37
+ * - Uppercase styling
38
+ * - Replaces scattered custom metadata classes
39
+ *
40
+ * @component
41
+ */
42
+ export function MetadataText({
43
+ children,
44
+ size = "xs",
45
+ className,
46
+ as: Component = "div",
47
+ }: MetadataTextProps) {
48
+ const sizeClasses = {
49
+ xs: "text-[8px]",
50
+ sm: "text-[9px]",
51
+ };
52
+
53
+ return (
54
+ <Component
55
+ className={cn(
56
+ sizeClasses[size],
57
+ "font-bold uppercase tracking-widest",
58
+ "text-foreground/60",
59
+ className
60
+ )}
61
+ >
62
+ {children}
63
+ </Component>
64
+ );
65
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Secondary Text Component
3
+ *
4
+ * Displays secondary or helper text with standardized styling.
5
+ * Replaces custom inline opacity classes like `text-muted-foreground/50` or `text-foreground/60`
6
+ *
7
+ * Usage: Replace inline text-[9px] text-muted-foreground/60
8
+ *
9
+ * @example
10
+ * <SecondaryText>Last updated 2 hours ago</SecondaryText>
11
+ * <SecondaryText size="sm">Optional description</SecondaryText>
12
+ */
13
+
14
+ "use client";
15
+
16
+ import React from "react";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ interface SecondaryTextProps {
20
+ /** Text content */
21
+ children: React.ReactNode;
22
+ /** Text size variant */
23
+ size?: "xs" | "sm";
24
+ /** Optional className override */
25
+ className?: string;
26
+ /** HTML element (default: div) */
27
+ as?: "div" | "p" | "span" | "label";
28
+ }
29
+
30
+ /**
31
+ * Standardized secondary text component
32
+ *
33
+ * Features:
34
+ * - Readable secondary text (60-65% opacity)
35
+ * - Multiple size options
36
+ * - Replaces scattered custom opacity classes
37
+ * - Consistent spacing
38
+ * - Fully customizable
39
+ *
40
+ * @component
41
+ */
42
+ export function SecondaryText({
43
+ children,
44
+ size = "xs",
45
+ className,
46
+ as: Component = "div",
47
+ }: SecondaryTextProps) {
48
+ const sizeClasses = {
49
+ xs: "text-[9px] font-medium",
50
+ sm: "text-xs font-medium",
51
+ };
52
+
53
+ return (
54
+ <Component
55
+ className={cn(sizeClasses[size], "text-foreground/60", className)}
56
+ >
57
+ {children}
58
+ </Component>
59
+ );
60
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Section Label Component
3
+ *
4
+ * Displays a section header or label with standardized styling.
5
+ * Replaces custom inline typography for section titles throughout the UI.
6
+ *
7
+ * Usage: Replace inline text-[10px] font-black uppercase tracking-[0.2em]
8
+ *
9
+ * @example
10
+ * <SectionLabel>Settings</SectionLabel>
11
+ * <SectionLabel icon={<Gear />}>Advanced</SectionLabel>
12
+ */
13
+
14
+ "use client";
15
+
16
+ import React from "react";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ interface SectionLabelProps {
20
+ /** Label text content */
21
+ children: React.ReactNode;
22
+ /** Optional icon to display before text */
23
+ icon?: React.ReactNode;
24
+ /** Optional className override */
25
+ className?: string;
26
+ /** Label HTML element (default: div) */
27
+ as?: "div" | "h3" | "h4" | "label" | "span";
28
+ }
29
+
30
+ /**
31
+ * Standardized section label component
32
+ *
33
+ * Features:
34
+ * - Consistent typography for section headers
35
+ * - Optional icon support
36
+ * - Readable secondary text (60% opacity)
37
+ * - Proper spacing and tracking
38
+ * - Fully customizable via className prop
39
+ *
40
+ * @component
41
+ */
42
+ export function SectionLabel({
43
+ children,
44
+ icon,
45
+ className,
46
+ as: Component = "div",
47
+ }: SectionLabelProps) {
48
+ return (
49
+ <Component
50
+ className={cn(
51
+ "text-[10px] font-black uppercase tracking-[0.2em] text-foreground/60",
52
+ "flex items-center gap-2",
53
+ className
54
+ )}
55
+ >
56
+ {icon}
57
+ {children}
58
+ </Component>
59
+ );
60
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Typography Components Barrel Export
3
+ *
4
+ * Centralized exports for all standardized typography components.
5
+ * Use these components instead of custom inline typography classes.
6
+ *
7
+ * @example
8
+ * import { SectionLabel, SecondaryText, EmptyStateText, MetadataText } from "@/components/typography";
9
+ */
10
+
11
+ export { EmptyStateText } from "./EmptyStateText";
12
+ export { MetadataText } from "./MetadataText";
13
+ export { SecondaryText } from "./SecondaryText";
14
+ export { SectionLabel } from "./SectionLabel";
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Typography Components
3
+ *
4
+ * Reusable components that apply consistent typography styles and scales.
5
+ * All typography variants are defined in `@/lib/typography` for centralized consistency.
6
+ *
7
+ * Readability Standards:
8
+ * - Primary text: text-foreground (100% opacity)
9
+ * - Secondary text: text-foreground/60-70% (improved from text-muted-foreground)
10
+ * - Labels: text-foreground/60% with uppercase
11
+ * - Disabled states: text-muted-foreground
12
+ *
13
+ * Features:
14
+ * - Semantic HTML heading tags (h1-h6)
15
+ * - Consistent spacing and tracking
16
+ * - Responsive text sizes
17
+ * - Built-in accessibility
18
+ * - Easy className overrides with cn()
19
+ *
20
+ * @example
21
+ * <Heading variant="h1">Page Title</Heading>
22
+ * <Body variant="body">Regular text</Body>
23
+ * <Label required>Field Label</Label>
24
+ */
25
+
26
+ "use client";
27
+
28
+ import { getTypographyClass } from "@/lib/typography";
29
+ import { cn } from "@/lib/utils";
30
+
31
+ interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
32
+ /** Heading level and size variant */
33
+ variant?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
34
+ }
35
+
36
+ /**
37
+ * Heading Component
38
+ *
39
+ * Renders semantic heading tags with consistent typography.
40
+ * Maps variant prop to appropriate heading level.
41
+ *
42
+ * @component
43
+ */
44
+ export function Heading({
45
+ variant = "h2",
46
+ className,
47
+ children,
48
+ ...props
49
+ }: HeadingProps) {
50
+ const headingLevel = variant as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
51
+
52
+ switch (headingLevel) {
53
+ case "h1":
54
+ return (
55
+ <h1 className={cn(getTypographyClass("h1"), className)} {...props}>
56
+ {children}
57
+ </h1>
58
+ );
59
+ case "h2":
60
+ return (
61
+ <h2 className={cn(getTypographyClass("h2"), className)} {...props}>
62
+ {children}
63
+ </h2>
64
+ );
65
+ case "h3":
66
+ return (
67
+ <h3 className={cn(getTypographyClass("h3"), className)} {...props}>
68
+ {children}
69
+ </h3>
70
+ );
71
+ case "h4":
72
+ return (
73
+ <h4 className={cn(getTypographyClass("h4"), className)} {...props}>
74
+ {children}
75
+ </h4>
76
+ );
77
+ case "h5":
78
+ return (
79
+ <h5 className={cn(getTypographyClass("h5"), className)} {...props}>
80
+ {children}
81
+ </h5>
82
+ );
83
+ case "h6":
84
+ return (
85
+ <h6 className={cn(getTypographyClass("h6"), className)} {...props}>
86
+ {children}
87
+ </h6>
88
+ );
89
+ }
90
+ }
91
+
92
+ interface BodyProps extends React.HTMLAttributes<HTMLParagraphElement> {
93
+ /** Body text size variant */
94
+ variant?: "bodyLg" | "body" | "bodySm";
95
+ }
96
+
97
+ /**
98
+ * Body Component
99
+ *
100
+ * Renders paragraph text with consistent typography.
101
+ * Supports multiple size variants for flexible content layout.
102
+ *
103
+ * @component
104
+ */
105
+ export function Body({
106
+ variant = "body",
107
+ className,
108
+ children,
109
+ ...props
110
+ }: BodyProps) {
111
+ return (
112
+ <p className={cn(getTypographyClass(variant), className)} {...props}>
113
+ {children}
114
+ </p>
115
+ );
116
+ }
117
+
118
+ interface LabelProps extends React.HTMLAttributes<HTMLLabelElement> {
119
+ /** Whether field is required (shows red asterisk) */
120
+ required?: boolean;
121
+ /** Label size variant */
122
+ variant?: "label" | "caption" | "captionSm";
123
+ }
124
+
125
+ /**
126
+ * Label Component
127
+ *
128
+ * Renders form label with optional required indicator.
129
+ * Supports multiple size variants for form layouts.
130
+ * Includes accessibility features for form associations.
131
+ *
132
+ * @component
133
+ */
134
+ export function Label({
135
+ variant = "label",
136
+ required,
137
+ className,
138
+ children,
139
+ ...props
140
+ }: LabelProps) {
141
+ return (
142
+ <label className={cn(getTypographyClass(variant), className)} {...props}>
143
+ {children}
144
+ {required && <span className="text-destructive ml-0.5">*</span>}
145
+ </label>
146
+ );
147
+ }
148
+
149
+ interface CaptionProps extends React.HTMLAttributes<HTMLDivElement> {
150
+ /** Caption size variant */
151
+ variant?: "caption" | "captionSm";
152
+ }
153
+
154
+ /**
155
+ * Caption Component
156
+ *
157
+ * Renders smaller supplementary text for captions and helper text.
158
+ * Provides improved readability with text-foreground/60-65%.
159
+ *
160
+ * @component
161
+ */
162
+ export function Caption({
163
+ variant = "caption",
164
+ className,
165
+ children,
166
+ ...props
167
+ }: CaptionProps) {
168
+ return (
169
+ <div className={cn(getTypographyClass(variant), className)} {...props}>
170
+ {children}
171
+ </div>
172
+ );
173
+ }
174
+
175
+ interface CodeProps extends React.HTMLAttributes<HTMLElement> {
176
+ /** Code variant (inline or block) */
177
+ variant?: "code" | "codeBlock";
178
+ /** Whether to render as code block (pre tag) */
179
+ block?: boolean;
180
+ }
181
+
182
+ /**
183
+ * Code Component
184
+ *
185
+ * Renders inline code or code blocks with monospace font.
186
+ * Supports both <code> and <pre> tags for different contexts.
187
+ *
188
+ * @component
189
+ */
190
+ export function Code({
191
+ variant,
192
+ block,
193
+ className,
194
+ children,
195
+ ...props
196
+ }: CodeProps) {
197
+ const v = block ? "codeBlock" : variant || "code";
198
+
199
+ if (block) {
200
+ return (
201
+ <pre
202
+ className={cn(getTypographyClass(v), className)}
203
+ {...(props as React.HTMLAttributes<HTMLPreElement>)}
204
+ >
205
+ {children}
206
+ </pre>
207
+ );
208
+ }
209
+
210
+ return (
211
+ <code
212
+ className={cn(getTypographyClass(v), className)}
213
+ {...(props as React.HTMLAttributes<HTMLElement>)}
214
+ >
215
+ {children}
216
+ </code>
217
+ );
218
+ }