@kelpie/ui 0.1.0

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 (704) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +44 -0
  3. package/dist/ServiceStatus.d.ts +6 -0
  4. package/dist/ServiceStatus.d.ts.map +1 -0
  5. package/dist/ServiceStatus.js +35 -0
  6. package/dist/ServiceStatus.js.map +1 -0
  7. package/dist/api/ApiProvider.d.ts +19 -0
  8. package/dist/api/ApiProvider.d.ts.map +1 -0
  9. package/dist/api/ApiProvider.js +18 -0
  10. package/dist/api/ApiProvider.js.map +1 -0
  11. package/dist/api/client.d.ts +83 -0
  12. package/dist/api/client.d.ts.map +1 -0
  13. package/dist/api/client.js +162 -0
  14. package/dist/api/client.js.map +1 -0
  15. package/dist/api/context.d.ts +14 -0
  16. package/dist/api/context.d.ts.map +1 -0
  17. package/dist/api/context.js +20 -0
  18. package/dist/api/context.js.map +1 -0
  19. package/dist/api/errors.d.ts +9 -0
  20. package/dist/api/errors.d.ts.map +1 -0
  21. package/dist/api/errors.js +14 -0
  22. package/dist/api/errors.js.map +1 -0
  23. package/dist/api/health.d.ts +15 -0
  24. package/dist/api/health.d.ts.map +1 -0
  25. package/dist/api/health.js +22 -0
  26. package/dist/api/health.js.map +1 -0
  27. package/dist/api/json.d.ts +3 -0
  28. package/dist/api/json.d.ts.map +1 -0
  29. package/dist/api/json.js +5 -0
  30. package/dist/api/json.js.map +1 -0
  31. package/dist/api/queryClient.d.ts +17 -0
  32. package/dist/api/queryClient.d.ts.map +1 -0
  33. package/dist/api/queryClient.js +33 -0
  34. package/dist/api/queryClient.js.map +1 -0
  35. package/dist/api/resource.d.ts +110 -0
  36. package/dist/api/resource.d.ts.map +1 -0
  37. package/dist/api/resource.js +238 -0
  38. package/dist/api/resource.js.map +1 -0
  39. package/dist/api/resources/account.d.ts +49 -0
  40. package/dist/api/resources/account.d.ts.map +1 -0
  41. package/dist/api/resources/account.js +146 -0
  42. package/dist/api/resources/account.js.map +1 -0
  43. package/dist/api/resources/activities.d.ts +8 -0
  44. package/dist/api/resources/activities.d.ts.map +1 -0
  45. package/dist/api/resources/activities.js +21 -0
  46. package/dist/api/resources/activities.js.map +1 -0
  47. package/dist/api/resources/agentTasks.d.ts +31 -0
  48. package/dist/api/resources/agentTasks.d.ts.map +1 -0
  49. package/dist/api/resources/agentTasks.js +103 -0
  50. package/dist/api/resources/agentTasks.js.map +1 -0
  51. package/dist/api/resources/candidates.d.ts +17 -0
  52. package/dist/api/resources/candidates.d.ts.map +1 -0
  53. package/dist/api/resources/candidates.js +40 -0
  54. package/dist/api/resources/candidates.js.map +1 -0
  55. package/dist/api/resources/companies.d.ts +22 -0
  56. package/dist/api/resources/companies.d.ts.map +1 -0
  57. package/dist/api/resources/companies.js +36 -0
  58. package/dist/api/resources/companies.js.map +1 -0
  59. package/dist/api/resources/dashboard.d.ts +8 -0
  60. package/dist/api/resources/dashboard.d.ts.map +1 -0
  61. package/dist/api/resources/dashboard.js +27 -0
  62. package/dist/api/resources/dashboard.js.map +1 -0
  63. package/dist/api/resources/deals.d.ts +30 -0
  64. package/dist/api/resources/deals.d.ts.map +1 -0
  65. package/dist/api/resources/deals.js +38 -0
  66. package/dist/api/resources/deals.js.map +1 -0
  67. package/dist/api/resources/decisions.d.ts +13 -0
  68. package/dist/api/resources/decisions.d.ts.map +1 -0
  69. package/dist/api/resources/decisions.js +38 -0
  70. package/dist/api/resources/decisions.js.map +1 -0
  71. package/dist/api/resources/forms.d.ts +82 -0
  72. package/dist/api/resources/forms.d.ts.map +1 -0
  73. package/dist/api/resources/forms.js +129 -0
  74. package/dist/api/resources/forms.js.map +1 -0
  75. package/dist/api/resources/handbookPages.d.ts +33 -0
  76. package/dist/api/resources/handbookPages.d.ts.map +1 -0
  77. package/dist/api/resources/handbookPages.js +49 -0
  78. package/dist/api/resources/handbookPages.js.map +1 -0
  79. package/dist/api/resources/importJobs.d.ts +72 -0
  80. package/dist/api/resources/importJobs.d.ts.map +1 -0
  81. package/dist/api/resources/importJobs.js +145 -0
  82. package/dist/api/resources/importJobs.js.map +1 -0
  83. package/dist/api/resources/invites.d.ts +19 -0
  84. package/dist/api/resources/invites.d.ts.map +1 -0
  85. package/dist/api/resources/invites.js +78 -0
  86. package/dist/api/resources/invites.js.map +1 -0
  87. package/dist/api/resources/mcpTools.d.ts +8 -0
  88. package/dist/api/resources/mcpTools.d.ts.map +1 -0
  89. package/dist/api/resources/mcpTools.js +23 -0
  90. package/dist/api/resources/mcpTools.js.map +1 -0
  91. package/dist/api/resources/members.d.ts +40 -0
  92. package/dist/api/resources/members.d.ts.map +1 -0
  93. package/dist/api/resources/members.js +67 -0
  94. package/dist/api/resources/members.js.map +1 -0
  95. package/dist/api/resources/moduleSettings.d.ts +14 -0
  96. package/dist/api/resources/moduleSettings.d.ts.map +1 -0
  97. package/dist/api/resources/moduleSettings.js +43 -0
  98. package/dist/api/resources/moduleSettings.js.map +1 -0
  99. package/dist/api/resources/mutation.d.ts +18 -0
  100. package/dist/api/resources/mutation.d.ts.map +1 -0
  101. package/dist/api/resources/mutation.js +12 -0
  102. package/dist/api/resources/mutation.js.map +1 -0
  103. package/dist/api/resources/notes.d.ts +14 -0
  104. package/dist/api/resources/notes.d.ts.map +1 -0
  105. package/dist/api/resources/notes.js +39 -0
  106. package/dist/api/resources/notes.js.map +1 -0
  107. package/dist/api/resources/opportunities.d.ts +29 -0
  108. package/dist/api/resources/opportunities.d.ts.map +1 -0
  109. package/dist/api/resources/opportunities.js +38 -0
  110. package/dist/api/resources/opportunities.js.map +1 -0
  111. package/dist/api/resources/partnerships.d.ts +33 -0
  112. package/dist/api/resources/partnerships.d.ts.map +1 -0
  113. package/dist/api/resources/partnerships.js +39 -0
  114. package/dist/api/resources/partnerships.js.map +1 -0
  115. package/dist/api/resources/people.d.ts +22 -0
  116. package/dist/api/resources/people.d.ts.map +1 -0
  117. package/dist/api/resources/people.js +36 -0
  118. package/dist/api/resources/people.js.map +1 -0
  119. package/dist/api/resources/pipelineStages.d.ts +22 -0
  120. package/dist/api/resources/pipelineStages.d.ts.map +1 -0
  121. package/dist/api/resources/pipelineStages.js +61 -0
  122. package/dist/api/resources/pipelineStages.js.map +1 -0
  123. package/dist/api/resources/planItems.d.ts +31 -0
  124. package/dist/api/resources/planItems.d.ts.map +1 -0
  125. package/dist/api/resources/planItems.js +60 -0
  126. package/dist/api/resources/planItems.js.map +1 -0
  127. package/dist/api/resources/positions.d.ts +23 -0
  128. package/dist/api/resources/positions.d.ts.map +1 -0
  129. package/dist/api/resources/positions.js +31 -0
  130. package/dist/api/resources/positions.js.map +1 -0
  131. package/dist/api/resources/raises.d.ts +30 -0
  132. package/dist/api/resources/raises.d.ts.map +1 -0
  133. package/dist/api/resources/raises.js +38 -0
  134. package/dist/api/resources/raises.js.map +1 -0
  135. package/dist/api/resources/roles.d.ts +20 -0
  136. package/dist/api/resources/roles.d.ts.map +1 -0
  137. package/dist/api/resources/roles.js +31 -0
  138. package/dist/api/resources/roles.js.map +1 -0
  139. package/dist/api/resources/search.d.ts +12 -0
  140. package/dist/api/resources/search.d.ts.map +1 -0
  141. package/dist/api/resources/search.js +37 -0
  142. package/dist/api/resources/search.js.map +1 -0
  143. package/dist/api/resources/session.d.ts +58 -0
  144. package/dist/api/resources/session.d.ts.map +1 -0
  145. package/dist/api/resources/session.js +157 -0
  146. package/dist/api/resources/session.js.map +1 -0
  147. package/dist/api/resources/webhooks.d.ts +45 -0
  148. package/dist/api/resources/webhooks.d.ts.map +1 -0
  149. package/dist/api/resources/webhooks.js +106 -0
  150. package/dist/api/resources/webhooks.js.map +1 -0
  151. package/dist/api/resources/workspace.d.ts +20 -0
  152. package/dist/api/resources/workspace.d.ts.map +1 -0
  153. package/dist/api/resources/workspace.js +63 -0
  154. package/dist/api/resources/workspace.js.map +1 -0
  155. package/dist/app/KelpieApp.d.ts +18 -0
  156. package/dist/app/KelpieApp.d.ts.map +1 -0
  157. package/dist/app/KelpieApp.js +59 -0
  158. package/dist/app/KelpieApp.js.map +1 -0
  159. package/dist/app/SessionGate.d.ts +14 -0
  160. package/dist/app/SessionGate.d.ts.map +1 -0
  161. package/dist/app/SessionGate.js +33 -0
  162. package/dist/app/SessionGate.js.map +1 -0
  163. package/dist/components/ActivitiesPanel.d.ts +28 -0
  164. package/dist/components/ActivitiesPanel.d.ts.map +1 -0
  165. package/dist/components/ActivitiesPanel.js +75 -0
  166. package/dist/components/ActivitiesPanel.js.map +1 -0
  167. package/dist/components/AgentTasks.d.ts +16 -0
  168. package/dist/components/AgentTasks.d.ts.map +1 -0
  169. package/dist/components/AgentTasks.js +166 -0
  170. package/dist/components/AgentTasks.js.map +1 -0
  171. package/dist/components/Chip.d.ts +10 -0
  172. package/dist/components/Chip.d.ts.map +1 -0
  173. package/dist/components/Chip.js +21 -0
  174. package/dist/components/Chip.js.map +1 -0
  175. package/dist/components/CopyButton.d.ts +7 -0
  176. package/dist/components/CopyButton.d.ts.map +1 -0
  177. package/dist/components/CopyButton.js +30 -0
  178. package/dist/components/CopyButton.js.map +1 -0
  179. package/dist/components/DataTable.d.ts +36 -0
  180. package/dist/components/DataTable.d.ts.map +1 -0
  181. package/dist/components/DataTable.js +43 -0
  182. package/dist/components/DataTable.js.map +1 -0
  183. package/dist/components/DecisionsPanel.d.ts +14 -0
  184. package/dist/components/DecisionsPanel.d.ts.map +1 -0
  185. package/dist/components/DecisionsPanel.js +73 -0
  186. package/dist/components/DecisionsPanel.js.map +1 -0
  187. package/dist/components/DeleteRecord.d.ts +19 -0
  188. package/dist/components/DeleteRecord.d.ts.map +1 -0
  189. package/dist/components/DeleteRecord.js +22 -0
  190. package/dist/components/DeleteRecord.js.map +1 -0
  191. package/dist/components/EntitySearch.d.ts +33 -0
  192. package/dist/components/EntitySearch.d.ts.map +1 -0
  193. package/dist/components/EntitySearch.js +111 -0
  194. package/dist/components/EntitySearch.js.map +1 -0
  195. package/dist/components/ErrorBoundary.d.ts +21 -0
  196. package/dist/components/ErrorBoundary.d.ts.map +1 -0
  197. package/dist/components/ErrorBoundary.js +26 -0
  198. package/dist/components/ErrorBoundary.js.map +1 -0
  199. package/dist/components/InlineEdit.d.ts +37 -0
  200. package/dist/components/InlineEdit.d.ts.map +1 -0
  201. package/dist/components/InlineEdit.js +77 -0
  202. package/dist/components/InlineEdit.js.map +1 -0
  203. package/dist/components/KanbanBoard.d.ts +24 -0
  204. package/dist/components/KanbanBoard.d.ts.map +1 -0
  205. package/dist/components/KanbanBoard.js +92 -0
  206. package/dist/components/KanbanBoard.js.map +1 -0
  207. package/dist/components/MarkdownView.d.ts +4 -0
  208. package/dist/components/MarkdownView.d.ts.map +1 -0
  209. package/dist/components/MarkdownView.js +45 -0
  210. package/dist/components/MarkdownView.js.map +1 -0
  211. package/dist/components/NotesPanel.d.ts +17 -0
  212. package/dist/components/NotesPanel.d.ts.map +1 -0
  213. package/dist/components/NotesPanel.js +53 -0
  214. package/dist/components/NotesPanel.js.map +1 -0
  215. package/dist/components/PageHeader.d.ts +20 -0
  216. package/dist/components/PageHeader.d.ts.map +1 -0
  217. package/dist/components/PageHeader.js +15 -0
  218. package/dist/components/PageHeader.js.map +1 -0
  219. package/dist/components/PhonesField.d.ts +7 -0
  220. package/dist/components/PhonesField.d.ts.map +1 -0
  221. package/dist/components/PhonesField.js +92 -0
  222. package/dist/components/PhonesField.js.map +1 -0
  223. package/dist/components/PlanAttention.d.ts +40 -0
  224. package/dist/components/PlanAttention.d.ts.map +1 -0
  225. package/dist/components/PlanAttention.js +86 -0
  226. package/dist/components/PlanAttention.js.map +1 -0
  227. package/dist/components/PlanPanel.d.ts +18 -0
  228. package/dist/components/PlanPanel.d.ts.map +1 -0
  229. package/dist/components/PlanPanel.js +102 -0
  230. package/dist/components/PlanPanel.js.map +1 -0
  231. package/dist/components/QueryState.d.ts +24 -0
  232. package/dist/components/QueryState.d.ts.map +1 -0
  233. package/dist/components/QueryState.js +34 -0
  234. package/dist/components/QueryState.js.map +1 -0
  235. package/dist/components/RecordTabs.d.ts +16 -0
  236. package/dist/components/RecordTabs.d.ts.map +1 -0
  237. package/dist/components/RecordTabs.js +15 -0
  238. package/dist/components/RecordTabs.js.map +1 -0
  239. package/dist/components/SectionHeader.d.ts +15 -0
  240. package/dist/components/SectionHeader.d.ts.map +1 -0
  241. package/dist/components/SectionHeader.js +14 -0
  242. package/dist/components/SectionHeader.js.map +1 -0
  243. package/dist/components/SegmentedControl.d.ts +13 -0
  244. package/dist/components/SegmentedControl.d.ts.map +1 -0
  245. package/dist/components/SegmentedControl.js +14 -0
  246. package/dist/components/SegmentedControl.js.map +1 -0
  247. package/dist/components/Shell.d.ts +2 -0
  248. package/dist/components/Shell.d.ts.map +1 -0
  249. package/dist/components/Shell.js +143 -0
  250. package/dist/components/Shell.js.map +1 -0
  251. package/dist/components/SidebarField.d.ts +8 -0
  252. package/dist/components/SidebarField.d.ts.map +1 -0
  253. package/dist/components/SidebarField.js +6 -0
  254. package/dist/components/SidebarField.js.map +1 -0
  255. package/dist/components/SocialProfilesField.d.ts +8 -0
  256. package/dist/components/SocialProfilesField.d.ts.map +1 -0
  257. package/dist/components/SocialProfilesField.js +176 -0
  258. package/dist/components/SocialProfilesField.js.map +1 -0
  259. package/dist/components/StageSettings.d.ts +16 -0
  260. package/dist/components/StageSettings.d.ts.map +1 -0
  261. package/dist/components/StageSettings.js +107 -0
  262. package/dist/components/StageSettings.js.map +1 -0
  263. package/dist/components/SummaryBlock.d.ts +12 -0
  264. package/dist/components/SummaryBlock.d.ts.map +1 -0
  265. package/dist/components/SummaryBlock.js +12 -0
  266. package/dist/components/SummaryBlock.js.map +1 -0
  267. package/dist/index.d.ts +90 -0
  268. package/dist/index.d.ts.map +1 -0
  269. package/dist/index.js +55 -0
  270. package/dist/index.js.map +1 -0
  271. package/dist/lib/dates.d.ts +26 -0
  272. package/dist/lib/dates.d.ts.map +1 -0
  273. package/dist/lib/dates.js +71 -0
  274. package/dist/lib/dates.js.map +1 -0
  275. package/dist/lib/money.d.ts +7 -0
  276. package/dist/lib/money.d.ts.map +1 -0
  277. package/dist/lib/money.js +13 -0
  278. package/dist/lib/money.js.map +1 -0
  279. package/dist/lib/names.d.ts +9 -0
  280. package/dist/lib/names.d.ts.map +1 -0
  281. package/dist/lib/names.js +13 -0
  282. package/dist/lib/names.js.map +1 -0
  283. package/dist/lib/plan.d.ts +67 -0
  284. package/dist/lib/plan.d.ts.map +1 -0
  285. package/dist/lib/plan.js +96 -0
  286. package/dist/lib/plan.js.map +1 -0
  287. package/dist/lib/theme.d.ts +19 -0
  288. package/dist/lib/theme.d.ts.map +1 -0
  289. package/dist/lib/theme.js +30 -0
  290. package/dist/lib/theme.js.map +1 -0
  291. package/dist/pages/CompaniesPage.d.ts +2 -0
  292. package/dist/pages/CompaniesPage.d.ts.map +1 -0
  293. package/dist/pages/CompaniesPage.js +77 -0
  294. package/dist/pages/CompaniesPage.js.map +1 -0
  295. package/dist/pages/CompanyDetail.d.ts +2 -0
  296. package/dist/pages/CompanyDetail.d.ts.map +1 -0
  297. package/dist/pages/CompanyDetail.js +177 -0
  298. package/dist/pages/CompanyDetail.js.map +1 -0
  299. package/dist/pages/DealDetail.d.ts +2 -0
  300. package/dist/pages/DealDetail.d.ts.map +1 -0
  301. package/dist/pages/DealDetail.js +192 -0
  302. package/dist/pages/DealDetail.js.map +1 -0
  303. package/dist/pages/DealStageSettingsPage.d.ts +7 -0
  304. package/dist/pages/DealStageSettingsPage.d.ts.map +1 -0
  305. package/dist/pages/DealStageSettingsPage.js +38 -0
  306. package/dist/pages/DealStageSettingsPage.js.map +1 -0
  307. package/dist/pages/DealsPage.d.ts +2 -0
  308. package/dist/pages/DealsPage.d.ts.map +1 -0
  309. package/dist/pages/DealsPage.js +177 -0
  310. package/dist/pages/DealsPage.js.map +1 -0
  311. package/dist/pages/DecisionsPage.d.ts +2 -0
  312. package/dist/pages/DecisionsPage.d.ts.map +1 -0
  313. package/dist/pages/DecisionsPage.js +121 -0
  314. package/dist/pages/DecisionsPage.js.map +1 -0
  315. package/dist/pages/FormDetail.d.ts +2 -0
  316. package/dist/pages/FormDetail.d.ts.map +1 -0
  317. package/dist/pages/FormDetail.js +56 -0
  318. package/dist/pages/FormDetail.js.map +1 -0
  319. package/dist/pages/FormsPage.d.ts +2 -0
  320. package/dist/pages/FormsPage.d.ts.map +1 -0
  321. package/dist/pages/FormsPage.js +67 -0
  322. package/dist/pages/FormsPage.js.map +1 -0
  323. package/dist/pages/FundraisingPage.d.ts +2 -0
  324. package/dist/pages/FundraisingPage.d.ts.map +1 -0
  325. package/dist/pages/FundraisingPage.js +187 -0
  326. package/dist/pages/FundraisingPage.js.map +1 -0
  327. package/dist/pages/HiringPage.d.ts +9 -0
  328. package/dist/pages/HiringPage.d.ts.map +1 -0
  329. package/dist/pages/HiringPage.js +73 -0
  330. package/dist/pages/HiringPage.js.map +1 -0
  331. package/dist/pages/NotFoundPage.d.ts +10 -0
  332. package/dist/pages/NotFoundPage.d.ts.map +1 -0
  333. package/dist/pages/NotFoundPage.js +14 -0
  334. package/dist/pages/NotFoundPage.js.map +1 -0
  335. package/dist/pages/OpportunitiesPage.d.ts +2 -0
  336. package/dist/pages/OpportunitiesPage.d.ts.map +1 -0
  337. package/dist/pages/OpportunitiesPage.js +184 -0
  338. package/dist/pages/OpportunitiesPage.js.map +1 -0
  339. package/dist/pages/OpportunityDetail.d.ts +2 -0
  340. package/dist/pages/OpportunityDetail.d.ts.map +1 -0
  341. package/dist/pages/OpportunityDetail.js +132 -0
  342. package/dist/pages/OpportunityDetail.js.map +1 -0
  343. package/dist/pages/OpportunityStageSettingsPage.d.ts +3 -0
  344. package/dist/pages/OpportunityStageSettingsPage.d.ts.map +1 -0
  345. package/dist/pages/OpportunityStageSettingsPage.js +34 -0
  346. package/dist/pages/OpportunityStageSettingsPage.js.map +1 -0
  347. package/dist/pages/PartnershipDetail.d.ts +2 -0
  348. package/dist/pages/PartnershipDetail.d.ts.map +1 -0
  349. package/dist/pages/PartnershipDetail.js +179 -0
  350. package/dist/pages/PartnershipDetail.js.map +1 -0
  351. package/dist/pages/PartnershipStageSettingsPage.d.ts +3 -0
  352. package/dist/pages/PartnershipStageSettingsPage.d.ts.map +1 -0
  353. package/dist/pages/PartnershipStageSettingsPage.js +34 -0
  354. package/dist/pages/PartnershipStageSettingsPage.js.map +1 -0
  355. package/dist/pages/PartnershipsPage.d.ts +2 -0
  356. package/dist/pages/PartnershipsPage.d.ts.map +1 -0
  357. package/dist/pages/PartnershipsPage.js +182 -0
  358. package/dist/pages/PartnershipsPage.js.map +1 -0
  359. package/dist/pages/PeoplePage.d.ts +10 -0
  360. package/dist/pages/PeoplePage.d.ts.map +1 -0
  361. package/dist/pages/PeoplePage.js +71 -0
  362. package/dist/pages/PeoplePage.js.map +1 -0
  363. package/dist/pages/PersonDetail.d.ts +2 -0
  364. package/dist/pages/PersonDetail.d.ts.map +1 -0
  365. package/dist/pages/PersonDetail.js +193 -0
  366. package/dist/pages/PersonDetail.js.map +1 -0
  367. package/dist/pages/PlanningPage.d.ts +2 -0
  368. package/dist/pages/PlanningPage.d.ts.map +1 -0
  369. package/dist/pages/PlanningPage.js +112 -0
  370. package/dist/pages/PlanningPage.js.map +1 -0
  371. package/dist/pages/RaiseDetail.d.ts +2 -0
  372. package/dist/pages/RaiseDetail.d.ts.map +1 -0
  373. package/dist/pages/RaiseDetail.js +198 -0
  374. package/dist/pages/RaiseDetail.js.map +1 -0
  375. package/dist/pages/RaiseStageSettingsPage.d.ts +3 -0
  376. package/dist/pages/RaiseStageSettingsPage.d.ts.map +1 -0
  377. package/dist/pages/RaiseStageSettingsPage.js +34 -0
  378. package/dist/pages/RaiseStageSettingsPage.js.map +1 -0
  379. package/dist/pages/RoleDetail.d.ts +2 -0
  380. package/dist/pages/RoleDetail.d.ts.map +1 -0
  381. package/dist/pages/RoleDetail.js +177 -0
  382. package/dist/pages/RoleDetail.js.map +1 -0
  383. package/dist/pages/SearchPage.d.ts +2 -0
  384. package/dist/pages/SearchPage.d.ts.map +1 -0
  385. package/dist/pages/SearchPage.js +51 -0
  386. package/dist/pages/SearchPage.js.map +1 -0
  387. package/dist/pages/account/AccountLayout.d.ts +2 -0
  388. package/dist/pages/account/AccountLayout.d.ts.map +1 -0
  389. package/dist/pages/account/AccountLayout.js +25 -0
  390. package/dist/pages/account/AccountLayout.js.map +1 -0
  391. package/dist/pages/account/Field.d.ts +8 -0
  392. package/dist/pages/account/Field.d.ts.map +1 -0
  393. package/dist/pages/account/Field.js +6 -0
  394. package/dist/pages/account/Field.js.map +1 -0
  395. package/dist/pages/account/PreferencesPage.d.ts +2 -0
  396. package/dist/pages/account/PreferencesPage.d.ts.map +1 -0
  397. package/dist/pages/account/PreferencesPage.js +92 -0
  398. package/dist/pages/account/PreferencesPage.js.map +1 -0
  399. package/dist/pages/account/ProfilePage.d.ts +14 -0
  400. package/dist/pages/account/ProfilePage.d.ts.map +1 -0
  401. package/dist/pages/account/ProfilePage.js +71 -0
  402. package/dist/pages/account/ProfilePage.js.map +1 -0
  403. package/dist/pages/account/SecurityPage.d.ts +11 -0
  404. package/dist/pages/account/SecurityPage.d.ts.map +1 -0
  405. package/dist/pages/account/SecurityPage.js +78 -0
  406. package/dist/pages/account/SecurityPage.js.map +1 -0
  407. package/dist/pages/admin/DataPage.d.ts +3 -0
  408. package/dist/pages/admin/DataPage.d.ts.map +1 -0
  409. package/dist/pages/admin/DataPage.js +210 -0
  410. package/dist/pages/admin/DataPage.js.map +1 -0
  411. package/dist/pages/admin/McpPage.d.ts +2 -0
  412. package/dist/pages/admin/McpPage.d.ts.map +1 -0
  413. package/dist/pages/admin/McpPage.js +128 -0
  414. package/dist/pages/admin/McpPage.js.map +1 -0
  415. package/dist/pages/admin/ModulesPage.d.ts +2 -0
  416. package/dist/pages/admin/ModulesPage.d.ts.map +1 -0
  417. package/dist/pages/admin/ModulesPage.js +53 -0
  418. package/dist/pages/admin/ModulesPage.js.map +1 -0
  419. package/dist/pages/admin/TeamPage.d.ts +2 -0
  420. package/dist/pages/admin/TeamPage.d.ts.map +1 -0
  421. package/dist/pages/admin/TeamPage.js +99 -0
  422. package/dist/pages/admin/TeamPage.js.map +1 -0
  423. package/dist/pages/admin/WebhookDeliveries.d.ts +4 -0
  424. package/dist/pages/admin/WebhookDeliveries.d.ts.map +1 -0
  425. package/dist/pages/admin/WebhookDeliveries.js +88 -0
  426. package/dist/pages/admin/WebhookDeliveries.js.map +1 -0
  427. package/dist/pages/admin/WebhooksPage.d.ts +2 -0
  428. package/dist/pages/admin/WebhooksPage.d.ts.map +1 -0
  429. package/dist/pages/admin/WebhooksPage.js +152 -0
  430. package/dist/pages/admin/WebhooksPage.js.map +1 -0
  431. package/dist/pages/admin/WorkspaceSettingsPage.d.ts +2 -0
  432. package/dist/pages/admin/WorkspaceSettingsPage.d.ts.map +1 -0
  433. package/dist/pages/admin/WorkspaceSettingsPage.js +117 -0
  434. package/dist/pages/admin/WorkspaceSettingsPage.js.map +1 -0
  435. package/dist/pages/auth/AuthForm.d.ts +46 -0
  436. package/dist/pages/auth/AuthForm.d.ts.map +1 -0
  437. package/dist/pages/auth/AuthForm.js +32 -0
  438. package/dist/pages/auth/AuthForm.js.map +1 -0
  439. package/dist/pages/auth/AuthLayout.d.ts +24 -0
  440. package/dist/pages/auth/AuthLayout.d.ts.map +1 -0
  441. package/dist/pages/auth/AuthLayout.js +19 -0
  442. package/dist/pages/auth/AuthLayout.js.map +1 -0
  443. package/dist/pages/auth/ForgotPasswordPage.d.ts +13 -0
  444. package/dist/pages/auth/ForgotPasswordPage.d.ts.map +1 -0
  445. package/dist/pages/auth/ForgotPasswordPage.js +39 -0
  446. package/dist/pages/auth/ForgotPasswordPage.js.map +1 -0
  447. package/dist/pages/auth/JoinPage.d.ts +12 -0
  448. package/dist/pages/auth/JoinPage.d.ts.map +1 -0
  449. package/dist/pages/auth/JoinPage.js +43 -0
  450. package/dist/pages/auth/JoinPage.js.map +1 -0
  451. package/dist/pages/auth/ResetPasswordPage.d.ts +13 -0
  452. package/dist/pages/auth/ResetPasswordPage.d.ts.map +1 -0
  453. package/dist/pages/auth/ResetPasswordPage.js +58 -0
  454. package/dist/pages/auth/ResetPasswordPage.js.map +1 -0
  455. package/dist/pages/auth/SignInPage.d.ts +2 -0
  456. package/dist/pages/auth/SignInPage.d.ts.map +1 -0
  457. package/dist/pages/auth/SignInPage.js +38 -0
  458. package/dist/pages/auth/SignInPage.js.map +1 -0
  459. package/dist/pages/auth/SignUpPage.d.ts +13 -0
  460. package/dist/pages/auth/SignUpPage.d.ts.map +1 -0
  461. package/dist/pages/auth/SignUpPage.js +43 -0
  462. package/dist/pages/auth/SignUpPage.js.map +1 -0
  463. package/dist/pages/candidateFields.d.ts +22 -0
  464. package/dist/pages/candidateFields.d.ts.map +1 -0
  465. package/dist/pages/candidateFields.js +82 -0
  466. package/dist/pages/candidateFields.js.map +1 -0
  467. package/dist/pages/dashboard/DashboardPage.d.ts +2 -0
  468. package/dist/pages/dashboard/DashboardPage.d.ts.map +1 -0
  469. package/dist/pages/dashboard/DashboardPage.js +40 -0
  470. package/dist/pages/dashboard/DashboardPage.js.map +1 -0
  471. package/dist/pages/dashboard/attention.d.ts +41 -0
  472. package/dist/pages/dashboard/attention.d.ts.map +1 -0
  473. package/dist/pages/dashboard/attention.js +146 -0
  474. package/dist/pages/dashboard/attention.js.map +1 -0
  475. package/dist/pages/dashboard/sections.d.ts +20 -0
  476. package/dist/pages/dashboard/sections.d.ts.map +1 -0
  477. package/dist/pages/dashboard/sections.js +60 -0
  478. package/dist/pages/dashboard/sections.js.map +1 -0
  479. package/dist/pages/fields.d.ts +11 -0
  480. package/dist/pages/fields.d.ts.map +1 -0
  481. package/dist/pages/fields.js +17 -0
  482. package/dist/pages/fields.js.map +1 -0
  483. package/dist/pages/forms/EmbedPanel.d.ts +14 -0
  484. package/dist/pages/forms/EmbedPanel.d.ts.map +1 -0
  485. package/dist/pages/forms/EmbedPanel.js +19 -0
  486. package/dist/pages/forms/EmbedPanel.js.map +1 -0
  487. package/dist/pages/forms/FieldsEditor.d.ts +6 -0
  488. package/dist/pages/forms/FieldsEditor.d.ts.map +1 -0
  489. package/dist/pages/forms/FieldsEditor.js +115 -0
  490. package/dist/pages/forms/FieldsEditor.js.map +1 -0
  491. package/dist/pages/forms/FormSettings.d.ts +6 -0
  492. package/dist/pages/forms/FormSettings.d.ts.map +1 -0
  493. package/dist/pages/forms/FormSettings.js +47 -0
  494. package/dist/pages/forms/FormSettings.js.map +1 -0
  495. package/dist/pages/forms/SubmissionsTable.d.ts +8 -0
  496. package/dist/pages/forms/SubmissionsTable.d.ts.map +1 -0
  497. package/dist/pages/forms/SubmissionsTable.js +91 -0
  498. package/dist/pages/forms/SubmissionsTable.js.map +1 -0
  499. package/dist/pages/forms/fieldList.d.ts +70 -0
  500. package/dist/pages/forms/fieldList.d.ts.map +1 -0
  501. package/dist/pages/forms/fieldList.js +126 -0
  502. package/dist/pages/forms/fieldList.js.map +1 -0
  503. package/dist/pages/forms/template.d.ts +18 -0
  504. package/dist/pages/forms/template.d.ts.map +1 -0
  505. package/dist/pages/forms/template.js +34 -0
  506. package/dist/pages/forms/template.js.map +1 -0
  507. package/dist/pages/handbook/HandbookPage.d.ts +2 -0
  508. package/dist/pages/handbook/HandbookPage.d.ts.map +1 -0
  509. package/dist/pages/handbook/HandbookPage.js +197 -0
  510. package/dist/pages/handbook/HandbookPage.js.map +1 -0
  511. package/dist/pages/handbook/tree.d.ts +62 -0
  512. package/dist/pages/handbook/tree.d.ts.map +1 -0
  513. package/dist/pages/handbook/tree.js +222 -0
  514. package/dist/pages/handbook/tree.js.map +1 -0
  515. package/dist/pages/hiringDirectory.d.ts +60 -0
  516. package/dist/pages/hiringDirectory.d.ts.map +1 -0
  517. package/dist/pages/hiringDirectory.js +81 -0
  518. package/dist/pages/hiringDirectory.js.map +1 -0
  519. package/dist/pages/onboarding/HandbookStepPage.d.ts +14 -0
  520. package/dist/pages/onboarding/HandbookStepPage.d.ts.map +1 -0
  521. package/dist/pages/onboarding/HandbookStepPage.js +29 -0
  522. package/dist/pages/onboarding/HandbookStepPage.js.map +1 -0
  523. package/dist/pages/onboarding/InvitesStepPage.d.ts +2 -0
  524. package/dist/pages/onboarding/InvitesStepPage.d.ts.map +1 -0
  525. package/dist/pages/onboarding/InvitesStepPage.js +77 -0
  526. package/dist/pages/onboarding/InvitesStepPage.js.map +1 -0
  527. package/dist/pages/onboarding/WorkspaceStepPage.d.ts +2 -0
  528. package/dist/pages/onboarding/WorkspaceStepPage.d.ts.map +1 -0
  529. package/dist/pages/onboarding/WorkspaceStepPage.js +72 -0
  530. package/dist/pages/onboarding/WorkspaceStepPage.js.map +1 -0
  531. package/dist/pages/positionDirectory.d.ts +20 -0
  532. package/dist/pages/positionDirectory.d.ts.map +1 -0
  533. package/dist/pages/positionDirectory.js +58 -0
  534. package/dist/pages/positionDirectory.js.map +1 -0
  535. package/dist/registry/UiExtensionProvider.d.ts +12 -0
  536. package/dist/registry/UiExtensionProvider.d.ts.map +1 -0
  537. package/dist/registry/UiExtensionProvider.js +10 -0
  538. package/dist/registry/UiExtensionProvider.js.map +1 -0
  539. package/dist/registry/context.d.ts +31 -0
  540. package/dist/registry/context.d.ts.map +1 -0
  541. package/dist/registry/context.js +45 -0
  542. package/dist/registry/context.js.map +1 -0
  543. package/dist/registry/contributions.d.ts +71 -0
  544. package/dist/registry/contributions.d.ts.map +1 -0
  545. package/dist/registry/contributions.js +25 -0
  546. package/dist/registry/contributions.js.map +1 -0
  547. package/dist/registry/overridable.d.ts +27 -0
  548. package/dist/registry/overridable.d.ts.map +1 -0
  549. package/dist/registry/overridable.js +29 -0
  550. package/dist/registry/overridable.js.map +1 -0
  551. package/dist/registry/registry.d.ts +68 -0
  552. package/dist/registry/registry.d.ts.map +1 -0
  553. package/dist/registry/registry.js +112 -0
  554. package/dist/registry/registry.js.map +1 -0
  555. package/dist/testing/inputs.d.ts +13 -0
  556. package/dist/testing/inputs.d.ts.map +1 -0
  557. package/dist/testing/inputs.js +16 -0
  558. package/dist/testing/inputs.js.map +1 -0
  559. package/dist/testing/stubClient.d.ts +42 -0
  560. package/dist/testing/stubClient.d.ts.map +1 -0
  561. package/dist/testing/stubClient.js +29 -0
  562. package/dist/testing/stubClient.js.map +1 -0
  563. package/package.json +73 -0
  564. package/src/ServiceStatus.tsx +61 -0
  565. package/src/api/ApiProvider.tsx +40 -0
  566. package/src/api/client.ts +267 -0
  567. package/src/api/context.ts +25 -0
  568. package/src/api/errors.ts +14 -0
  569. package/src/api/health.ts +38 -0
  570. package/src/api/json.ts +4 -0
  571. package/src/api/queryClient.ts +35 -0
  572. package/src/api/resource.ts +412 -0
  573. package/src/api/resources/account.ts +220 -0
  574. package/src/api/resources/activities.ts +31 -0
  575. package/src/api/resources/agentTasks.ts +172 -0
  576. package/src/api/resources/candidates.ts +69 -0
  577. package/src/api/resources/companies.ts +72 -0
  578. package/src/api/resources/dashboard.ts +39 -0
  579. package/src/api/resources/deals.ts +82 -0
  580. package/src/api/resources/decisions.ts +60 -0
  581. package/src/api/resources/forms.ts +218 -0
  582. package/src/api/resources/handbookPages.ts +77 -0
  583. package/src/api/resources/importJobs.ts +229 -0
  584. package/src/api/resources/invites.ts +112 -0
  585. package/src/api/resources/mcpTools.ts +28 -0
  586. package/src/api/resources/members.ts +105 -0
  587. package/src/api/resources/moduleSettings.ts +67 -0
  588. package/src/api/resources/mutation.ts +31 -0
  589. package/src/api/resources/notes.ts +62 -0
  590. package/src/api/resources/opportunities.ts +84 -0
  591. package/src/api/resources/partnerships.ts +89 -0
  592. package/src/api/resources/people.ts +72 -0
  593. package/src/api/resources/pipelineStages.ts +93 -0
  594. package/src/api/resources/planItems.ts +103 -0
  595. package/src/api/resources/positions.ts +70 -0
  596. package/src/api/resources/raises.ts +82 -0
  597. package/src/api/resources/roles.ts +65 -0
  598. package/src/api/resources/search.ts +49 -0
  599. package/src/api/resources/session.ts +220 -0
  600. package/src/api/resources/webhooks.ts +157 -0
  601. package/src/api/resources/workspace.ts +81 -0
  602. package/src/app/KelpieApp.tsx +162 -0
  603. package/src/app/SessionGate.tsx +42 -0
  604. package/src/components/ActivitiesPanel.tsx +235 -0
  605. package/src/components/AgentTasks.tsx +473 -0
  606. package/src/components/Chip.tsx +36 -0
  607. package/src/components/CopyButton.tsx +48 -0
  608. package/src/components/DataTable.tsx +209 -0
  609. package/src/components/DecisionsPanel.tsx +233 -0
  610. package/src/components/DeleteRecord.tsx +73 -0
  611. package/src/components/EntitySearch.tsx +268 -0
  612. package/src/components/ErrorBoundary.tsx +58 -0
  613. package/src/components/InlineEdit.tsx +179 -0
  614. package/src/components/KanbanBoard.tsx +234 -0
  615. package/src/components/MarkdownView.tsx +73 -0
  616. package/src/components/NotesPanel.tsx +169 -0
  617. package/src/components/PageHeader.tsx +61 -0
  618. package/src/components/PhonesField.tsx +204 -0
  619. package/src/components/PlanAttention.tsx +249 -0
  620. package/src/components/PlanPanel.tsx +317 -0
  621. package/src/components/QueryState.tsx +83 -0
  622. package/src/components/RecordTabs.tsx +69 -0
  623. package/src/components/SectionHeader.tsx +63 -0
  624. package/src/components/SegmentedControl.tsx +48 -0
  625. package/src/components/Shell.tsx +300 -0
  626. package/src/components/SidebarField.tsx +18 -0
  627. package/src/components/SocialProfilesField.tsx +356 -0
  628. package/src/components/StageSettings.tsx +319 -0
  629. package/src/components/SummaryBlock.tsx +27 -0
  630. package/src/index.ts +190 -0
  631. package/src/lib/dates.ts +90 -0
  632. package/src/lib/money.ts +12 -0
  633. package/src/lib/names.ts +13 -0
  634. package/src/lib/plan.ts +147 -0
  635. package/src/lib/theme.ts +53 -0
  636. package/src/pages/CompaniesPage.tsx +143 -0
  637. package/src/pages/CompanyDetail.tsx +502 -0
  638. package/src/pages/DealDetail.tsx +512 -0
  639. package/src/pages/DealStageSettingsPage.tsx +67 -0
  640. package/src/pages/DealsPage.tsx +342 -0
  641. package/src/pages/DecisionsPage.tsx +211 -0
  642. package/src/pages/FormDetail.tsx +130 -0
  643. package/src/pages/FormsPage.tsx +151 -0
  644. package/src/pages/FundraisingPage.tsx +354 -0
  645. package/src/pages/HiringPage.tsx +169 -0
  646. package/src/pages/NotFoundPage.tsx +27 -0
  647. package/src/pages/OpportunitiesPage.tsx +349 -0
  648. package/src/pages/OpportunityDetail.tsx +337 -0
  649. package/src/pages/OpportunityStageSettingsPage.tsx +63 -0
  650. package/src/pages/PartnershipDetail.tsx +490 -0
  651. package/src/pages/PartnershipStageSettingsPage.tsx +63 -0
  652. package/src/pages/PartnershipsPage.tsx +353 -0
  653. package/src/pages/PeoplePage.tsx +145 -0
  654. package/src/pages/PersonDetail.tsx +526 -0
  655. package/src/pages/PlanningPage.tsx +318 -0
  656. package/src/pages/RaiseDetail.tsx +498 -0
  657. package/src/pages/RaiseStageSettingsPage.tsx +63 -0
  658. package/src/pages/RoleDetail.tsx +455 -0
  659. package/src/pages/SearchPage.tsx +135 -0
  660. package/src/pages/account/AccountLayout.tsx +38 -0
  661. package/src/pages/account/Field.tsx +20 -0
  662. package/src/pages/account/PreferencesPage.tsx +224 -0
  663. package/src/pages/account/ProfilePage.tsx +147 -0
  664. package/src/pages/account/SecurityPage.tsx +237 -0
  665. package/src/pages/admin/DataPage.tsx +772 -0
  666. package/src/pages/admin/McpPage.tsx +404 -0
  667. package/src/pages/admin/ModulesPage.tsx +113 -0
  668. package/src/pages/admin/TeamPage.tsx +386 -0
  669. package/src/pages/admin/WebhookDeliveries.tsx +184 -0
  670. package/src/pages/admin/WebhooksPage.tsx +443 -0
  671. package/src/pages/admin/WorkspaceSettingsPage.tsx +274 -0
  672. package/src/pages/auth/AuthForm.tsx +118 -0
  673. package/src/pages/auth/AuthLayout.tsx +74 -0
  674. package/src/pages/auth/ForgotPasswordPage.tsx +80 -0
  675. package/src/pages/auth/JoinPage.tsx +85 -0
  676. package/src/pages/auth/ResetPasswordPage.tsx +124 -0
  677. package/src/pages/auth/SignInPage.tsx +83 -0
  678. package/src/pages/auth/SignUpPage.tsx +93 -0
  679. package/src/pages/candidateFields.tsx +175 -0
  680. package/src/pages/dashboard/DashboardPage.tsx +108 -0
  681. package/src/pages/dashboard/attention.ts +206 -0
  682. package/src/pages/dashboard/sections.tsx +269 -0
  683. package/src/pages/fields.ts +21 -0
  684. package/src/pages/forms/EmbedPanel.tsx +95 -0
  685. package/src/pages/forms/FieldsEditor.tsx +412 -0
  686. package/src/pages/forms/FormSettings.tsx +159 -0
  687. package/src/pages/forms/SubmissionsTable.tsx +171 -0
  688. package/src/pages/forms/fieldList.ts +209 -0
  689. package/src/pages/forms/template.ts +37 -0
  690. package/src/pages/handbook/HandbookPage.tsx +500 -0
  691. package/src/pages/handbook/tree.ts +327 -0
  692. package/src/pages/hiringDirectory.ts +146 -0
  693. package/src/pages/onboarding/HandbookStepPage.tsx +75 -0
  694. package/src/pages/onboarding/InvitesStepPage.tsx +180 -0
  695. package/src/pages/onboarding/WorkspaceStepPage.tsx +122 -0
  696. package/src/pages/positionDirectory.ts +98 -0
  697. package/src/registry/UiExtensionProvider.tsx +20 -0
  698. package/src/registry/context.ts +67 -0
  699. package/src/registry/contributions.ts +89 -0
  700. package/src/registry/overridable.ts +62 -0
  701. package/src/registry/registry.ts +204 -0
  702. package/src/styles.css +175 -0
  703. package/src/testing/inputs.ts +18 -0
  704. package/src/testing/stubClient.ts +78 -0
@@ -0,0 +1,157 @@
1
+ import {
2
+ createWebhookBody,
3
+ createdWebhookSchema,
4
+ rotateWebhookSecretBody,
5
+ webhookBody,
6
+ webhookDeliverySchema,
7
+ webhookSchema,
8
+ } from '@kelpie/schemas'
9
+ import type {
10
+ CreateWebhookInput,
11
+ CreatedWebhook,
12
+ RotateWebhookSecretInput,
13
+ Webhook,
14
+ WebhookDelivery,
15
+ WebhookInput,
16
+ } from '@kelpie/schemas'
17
+ import { keepPreviousData, useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'
18
+
19
+ import type { QueryParameters } from '../client.ts'
20
+ import { useApiClient } from '../context.ts'
21
+ import { toError } from '../errors.ts'
22
+ import { createResourceHooks } from '../resource.ts'
23
+ import type { MutationResult, RecordListResult, UpdateArguments } from '../resource.ts'
24
+ import { asMutationResult } from './mutation.ts'
25
+
26
+ /**
27
+ * `/v1/webhooks`: outbound event delivery.
28
+ *
29
+ * Every verb needs the admin role, reads included, so a member's list request
30
+ * answers `403` and the page renders that rather than an empty table. A webhook
31
+ * URL routinely carries its own credential in the path, which is what puts
32
+ * reading them alongside API keys.
33
+ */
34
+
35
+ const webhooks = createResourceHooks<Webhook, CreateWebhookInput, WebhookInput>({
36
+ name: 'webhooks',
37
+ path: '/webhooks',
38
+ decode: webhookSchema.parse,
39
+ createBody: createWebhookBody,
40
+ updateBody: webhookBody,
41
+ })
42
+
43
+ export interface WebhookFilters {
44
+ readonly status?: Webhook['status']
45
+ }
46
+
47
+ function webhookQuery(filters: WebhookFilters): QueryParameters {
48
+ return { status: filters.status }
49
+ }
50
+
51
+ export function useWebhooks(filters: WebhookFilters = {}): RecordListResult<Webhook> {
52
+ return webhooks.useList(webhookQuery(filters))
53
+ }
54
+
55
+ export function useUpdateWebhook(): MutationResult<UpdateArguments<WebhookInput>, Webhook> {
56
+ return webhooks.useUpdate()
57
+ }
58
+
59
+ export function useDeleteWebhook(): MutationResult<string, void> {
60
+ return webhooks.useRemove()
61
+ }
62
+
63
+ export interface WebhookDeliveryFilters {
64
+ readonly status?: WebhookDelivery['status']
65
+ }
66
+
67
+ /**
68
+ * One webhook's deliveries, newest first.
69
+ *
70
+ * Written out rather than built from `createResourceHooks`, for the reason
71
+ * `useFormSubmissions` gives: the path carries the parent id, and generalising
72
+ * the factory for a nested list would complicate every resource to shorten one.
73
+ *
74
+ * The status is part of the cache key. Without it, switching the filter would
75
+ * read the previous filter's pages out of the cache and append the new filter's
76
+ * next page to them.
77
+ */
78
+ export function useWebhookDeliveries(
79
+ webhookId: string,
80
+ filters: WebhookDeliveryFilters = {},
81
+ ): RecordListResult<WebhookDelivery> {
82
+ const client = useApiClient()
83
+ const result = useInfiniteQuery({
84
+ queryKey: ['webhooks', 'deliveries', webhookId, filters.status ?? 'all'],
85
+ queryFn: ({ pageParam }) =>
86
+ client.list(`/webhooks/${webhookId}/deliveries`, webhookDeliverySchema.parse, {
87
+ status: filters.status,
88
+ ...(pageParam === null ? {} : { cursor: pageParam }),
89
+ }),
90
+ initialPageParam: null as string | null,
91
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
92
+ placeholderData: keepPreviousData,
93
+ })
94
+
95
+ return {
96
+ records: result.data?.pages.flatMap((page) => page.items) ?? [],
97
+ isLoading: result.isPending,
98
+ error: toError(result.error),
99
+ hasMore: result.hasNextPage,
100
+ isLoadingMore: result.isFetchingNextPage,
101
+ loadMore: () => {
102
+ void result.fetchNextPage()
103
+ },
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Registers a webhook.
109
+ *
110
+ * Written out rather than taken from `createResourceHooks`, because the `201`
111
+ * is the only response that ever carries the signing secret and the shared hook
112
+ * decodes with the schema that has no such field. The secret has to survive the
113
+ * decode: it cannot be fetched again, so a page that dropped it would have
114
+ * created a webhook nobody can verify deliveries from.
115
+ */
116
+ export function useCreateWebhook(): MutationResult<CreateWebhookInput, CreatedWebhook> {
117
+ const client = useApiClient()
118
+ const queryClient = useQueryClient()
119
+ const mutation = useMutation({
120
+ mutationFn: (input: CreateWebhookInput) =>
121
+ client.post('/webhooks', createWebhookBody(input), createdWebhookSchema.parse),
122
+ onSettled: () => {
123
+ void queryClient.invalidateQueries({ queryKey: ['webhooks', 'list'] })
124
+ },
125
+ })
126
+
127
+ return asMutationResult(mutation)
128
+ }
129
+
130
+ export interface RotateSecretArguments extends RotateWebhookSecretInput {
131
+ readonly id: string
132
+ }
133
+
134
+ /**
135
+ * Replaces a webhook's signing secret.
136
+ *
137
+ * Written out for the same reason `useCreateWebhook` is: the response carries
138
+ * the new secret, which no later request can retrieve, so it has to survive a
139
+ * decode that the shared `Webhook` schema would drop.
140
+ */
141
+ export function useRotateWebhookSecret(): MutationResult<RotateSecretArguments, CreatedWebhook> {
142
+ const client = useApiClient()
143
+ const queryClient = useQueryClient()
144
+ const mutation = useMutation({
145
+ mutationFn: ({ id, ...input }: RotateSecretArguments) =>
146
+ client.post(
147
+ `/webhooks/${id}/rotate_secret`,
148
+ rotateWebhookSecretBody(input),
149
+ createdWebhookSchema.parse,
150
+ ),
151
+ onSettled: () => {
152
+ void queryClient.invalidateQueries({ queryKey: ['webhooks', 'list'] })
153
+ },
154
+ })
155
+
156
+ return asMutationResult(mutation)
157
+ }
@@ -0,0 +1,81 @@
1
+ import { updateWorkspaceBody, workspaceSchema } from '@kelpie/schemas'
2
+ import type { UpdateWorkspaceInput, Workspace } from '@kelpie/schemas'
3
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
4
+
5
+ import { useApiClient } from '../context.ts'
6
+ import { toError } from '../errors.ts'
7
+ import type { MutationResult } from '../resource.ts'
8
+ import { asMutationResult } from './mutation.ts'
9
+ import { useSession } from './session.ts'
10
+
11
+ /**
12
+ * The workspace the session is in.
13
+ *
14
+ * Not a CRM resource: there is one of them, its id comes from the session rather
15
+ * than a route, and there is no list. `createResourceHooks` would have nothing
16
+ * to configure.
17
+ */
18
+
19
+ const WORKSPACE_KEY = 'workspace'
20
+
21
+ export interface WorkspaceState {
22
+ readonly workspace: Workspace | undefined
23
+ readonly isLoading: boolean
24
+ readonly error: Error | null
25
+ }
26
+
27
+ export function useWorkspace(): WorkspaceState {
28
+ const client = useApiClient()
29
+ const { session } = useSession()
30
+ const workspaceId = session?.workspaceId ?? undefined
31
+ const result = useQuery({
32
+ queryKey: [WORKSPACE_KEY, workspaceId],
33
+ queryFn: () => client.get(`/workspaces/${workspaceId ?? ''}`, workspaceSchema.parse),
34
+ enabled: workspaceId !== undefined,
35
+ })
36
+
37
+ return {
38
+ workspace: result.data,
39
+ isLoading: result.isPending && workspaceId !== undefined,
40
+ error: toError(result.error),
41
+ }
42
+ }
43
+
44
+ export function useUpdateWorkspace(): MutationResult<UpdateWorkspaceInput, Workspace> {
45
+ const client = useApiClient()
46
+ const queryClient = useQueryClient()
47
+ const { session } = useSession()
48
+ const workspaceId = session?.workspaceId ?? ''
49
+ const mutation = useMutation({
50
+ mutationFn: (input: UpdateWorkspaceInput) =>
51
+ client.patch(`/workspaces/${workspaceId}`, updateWorkspaceBody(input), workspaceSchema.parse),
52
+ onSuccess: (workspace) => {
53
+ queryClient.setQueryData([WORKSPACE_KEY, workspaceId], workspace)
54
+ },
55
+ })
56
+
57
+ return asMutationResult(mutation)
58
+ }
59
+
60
+ /**
61
+ * Deletes the workspace, everything in it, and the caller's way back.
62
+ *
63
+ * The slug goes with the request because the API asks the caller to name what it
64
+ * is destroying. Afterwards the whole cache is dropped: every cached list
65
+ * belongs to a workspace that no longer exists.
66
+ */
67
+ export function useDeleteWorkspace(): MutationResult<{ readonly slug: string }, void> {
68
+ const client = useApiClient()
69
+ const queryClient = useQueryClient()
70
+ const { session } = useSession()
71
+ const workspaceId = session?.workspaceId ?? ''
72
+ const mutation = useMutation({
73
+ mutationFn: ({ slug }: { readonly slug: string }) =>
74
+ client.delete(`/workspaces/${workspaceId}`, { slug }),
75
+ onSuccess: () => {
76
+ queryClient.clear()
77
+ },
78
+ })
79
+
80
+ return asMutationResult(mutation)
81
+ }
@@ -0,0 +1,162 @@
1
+ import { BrowserRouter, Navigate, Route, Routes } from 'react-router'
2
+
3
+ import { ApiProvider } from '../api/ApiProvider.tsx'
4
+ import { Shell } from '../components/Shell.tsx'
5
+ import { CompaniesPage } from '../pages/CompaniesPage.tsx'
6
+ import { CompanyDetail } from '../pages/CompanyDetail.tsx'
7
+ import { DealDetail } from '../pages/DealDetail.tsx'
8
+ import { DealStageSettingsPage } from '../pages/DealStageSettingsPage.tsx'
9
+ import { DealsPage } from '../pages/DealsPage.tsx'
10
+ import { DecisionsPage } from '../pages/DecisionsPage.tsx'
11
+ import { SearchPage } from '../pages/SearchPage.tsx'
12
+ import { FormDetail } from '../pages/FormDetail.tsx'
13
+ import { FormsPage } from '../pages/FormsPage.tsx'
14
+ import { FundraisingPage } from '../pages/FundraisingPage.tsx'
15
+ import { HiringPage } from '../pages/HiringPage.tsx'
16
+ import { NotFoundPage } from '../pages/NotFoundPage.tsx'
17
+ import { OpportunitiesPage } from '../pages/OpportunitiesPage.tsx'
18
+ import { OpportunityDetail } from '../pages/OpportunityDetail.tsx'
19
+ import { OpportunityStageSettingsPage } from '../pages/OpportunityStageSettingsPage.tsx'
20
+ import { PartnershipDetail } from '../pages/PartnershipDetail.tsx'
21
+ import { PartnershipStageSettingsPage } from '../pages/PartnershipStageSettingsPage.tsx'
22
+ import { PartnershipsPage } from '../pages/PartnershipsPage.tsx'
23
+ import { PeoplePage } from '../pages/PeoplePage.tsx'
24
+ import { PersonDetail } from '../pages/PersonDetail.tsx'
25
+ import { PlanningPage } from '../pages/PlanningPage.tsx'
26
+ import { RaiseDetail } from '../pages/RaiseDetail.tsx'
27
+ import { RaiseStageSettingsPage } from '../pages/RaiseStageSettingsPage.tsx'
28
+ import { RoleDetail } from '../pages/RoleDetail.tsx'
29
+ import { AccountLayout } from '../pages/account/AccountLayout.tsx'
30
+ import { PreferencesPage } from '../pages/account/PreferencesPage.tsx'
31
+ import { ProfilePage } from '../pages/account/ProfilePage.tsx'
32
+ import { SecurityPage } from '../pages/account/SecurityPage.tsx'
33
+ import { DataPage } from '../pages/admin/DataPage.tsx'
34
+ import { McpPage } from '../pages/admin/McpPage.tsx'
35
+ import { ModulesPage } from '../pages/admin/ModulesPage.tsx'
36
+ import { TeamPage } from '../pages/admin/TeamPage.tsx'
37
+ import { WebhooksPage } from '../pages/admin/WebhooksPage.tsx'
38
+ import { WorkspaceSettingsPage } from '../pages/admin/WorkspaceSettingsPage.tsx'
39
+ import { ForgotPasswordPage } from '../pages/auth/ForgotPasswordPage.tsx'
40
+ import { JoinPage } from '../pages/auth/JoinPage.tsx'
41
+ import { ResetPasswordPage } from '../pages/auth/ResetPasswordPage.tsx'
42
+ import { SignInPage } from '../pages/auth/SignInPage.tsx'
43
+ import { SignUpPage } from '../pages/auth/SignUpPage.tsx'
44
+ import { DashboardPage } from '../pages/dashboard/DashboardPage.tsx'
45
+ import { HandbookLayout } from '../pages/handbook/HandbookPage.tsx'
46
+ import { HandbookStepPage } from '../pages/onboarding/HandbookStepPage.tsx'
47
+ import { InvitesStepPage } from '../pages/onboarding/InvitesStepPage.tsx'
48
+ import { WorkspaceStepPage } from '../pages/onboarding/WorkspaceStepPage.tsx'
49
+ import { UiExtensionProvider } from '../registry/UiExtensionProvider.tsx'
50
+ import { useModuleRoutes } from '../registry/context.ts'
51
+ import type { UiExtensions } from '../registry/registry.ts'
52
+ import { SessionGate } from './SessionGate.tsx'
53
+
54
+ /**
55
+ * The whole application: providers, router, and the route table.
56
+ *
57
+ * It lives in `@kelpie/ui` rather than in `apps/kelpie` so the cloud assembly
58
+ * gets the same application and differs only by the modules it registers. The
59
+ * assembly's job is to build the registry and render this.
60
+ *
61
+ * Routes here are the ported pages. The mockup's other routes arrive with the
62
+ * features behind them; module routes mount alongside through the registry.
63
+ */
64
+
65
+ export interface KelpieAppProps {
66
+ readonly extensions: UiExtensions
67
+ /** Origin plus base path for the API. Defaults to same-origin `/v1`. */
68
+ readonly baseUrl?: string
69
+ }
70
+
71
+ export function KelpieApp({ extensions, baseUrl }: KelpieAppProps): React.JSX.Element {
72
+ return (
73
+ <ApiProvider baseUrl={baseUrl}>
74
+ <UiExtensionProvider extensions={extensions}>
75
+ <BrowserRouter>
76
+ <AppRoutes />
77
+ </BrowserRouter>
78
+ </UiExtensionProvider>
79
+ </ApiProvider>
80
+ )
81
+ }
82
+
83
+ function AppRoutes(): React.JSX.Element {
84
+ const moduleRoutes = useModuleRoutes()
85
+
86
+ return (
87
+ <Routes>
88
+ {/* Signed out, or on the way to being signed in. Route names are the
89
+ mockup's. */}
90
+ <Route path="/login" element={<SignInPage />} />
91
+ <Route path="/signup" element={<SignUpPage />} />
92
+ <Route path="/forgot-password" element={<ForgotPasswordPage />} />
93
+ <Route path="/reset-password" element={<ResetPasswordPage />} />
94
+ {/* Outside the gate: an invitee may have no workspace yet, and this is how
95
+ they get one. Same for the first onboarding step, which is what the
96
+ gate sends an account with no workspace to. */}
97
+ <Route path="/join" element={<JoinPage />} />
98
+ <Route path="/onboarding/workspace" element={<WorkspaceStepPage />} />
99
+
100
+ <Route element={<SessionGate />}>
101
+ {/* Inside the gate and outside the Shell: both steps need the workspace
102
+ that step 1 created, and neither is a place to start navigating the
103
+ app from. */}
104
+ <Route path="/onboarding/invites" element={<InvitesStepPage />} />
105
+ <Route path="/onboarding/handbook" element={<HandbookStepPage />} />
106
+
107
+ <Route element={<Shell />}>
108
+ {/* The mockup's default route, and where the shell's wordmark goes. */}
109
+ <Route index element={<Navigate to="/dashboard" replace />} />
110
+ <Route path="dashboard" element={<DashboardPage />} />
111
+ <Route path="search" element={<SearchPage />} />
112
+ <Route path="people" element={<PeoplePage />} />
113
+ <Route path="people/:id" element={<PersonDetail />} />
114
+ <Route path="hiring" element={<HiringPage />} />
115
+ <Route path="hiring/:id" element={<RoleDetail />} />
116
+ <Route path="companies" element={<CompaniesPage />} />
117
+ <Route path="companies/:id" element={<CompanyDetail />} />
118
+ <Route path="deals" element={<DealsPage />} />
119
+ <Route path="deals/settings" element={<DealStageSettingsPage />} />
120
+ <Route path="deals/:id" element={<DealDetail />} />
121
+ <Route path="opportunities" element={<OpportunitiesPage />} />
122
+ <Route path="opportunities/settings" element={<OpportunityStageSettingsPage />} />
123
+ <Route path="opportunities/:id" element={<OpportunityDetail />} />
124
+ <Route path="fundraising" element={<FundraisingPage />} />
125
+ <Route path="fundraising/settings" element={<RaiseStageSettingsPage />} />
126
+ <Route path="fundraising/:id" element={<RaiseDetail />} />
127
+ <Route path="partnerships" element={<PartnershipsPage />} />
128
+ <Route path="partnerships/settings" element={<PartnershipStageSettingsPage />} />
129
+ <Route path="partnerships/:id" element={<PartnershipDetail />} />
130
+ <Route path="planning" element={<PlanningPage />} />
131
+ <Route path="decisions" element={<DecisionsPage />} />
132
+ <Route path="forms" element={<FormsPage />} />
133
+ <Route path="forms/:id" element={<FormDetail />} />
134
+ {/* The optional segment is the mockup's: /handbook opens the first page. */}
135
+ <Route path="handbook" element={<HandbookLayout />} />
136
+ <Route path="handbook/:pageId" element={<HandbookLayout />} />
137
+ <Route path="admin/workspace" element={<WorkspaceSettingsPage />} />
138
+ <Route path="admin/team" element={<TeamPage />} />
139
+ <Route path="admin/data" element={<DataPage />} />
140
+ <Route path="admin/mcp" element={<McpPage />} />
141
+ <Route path="admin/webhooks" element={<WebhooksPage />} />
142
+ <Route path="admin/modules" element={<ModulesPage />} />
143
+ {/* The mockup's own shape: /account opens the first tab. */}
144
+ <Route path="account" element={<AccountLayout />}>
145
+ <Route index element={<Navigate to="/account/profile" replace />} />
146
+ <Route path="profile" element={<ProfilePage />} />
147
+ <Route path="security" element={<SecurityPage />} />
148
+ <Route path="preferences" element={<PreferencesPage />} />
149
+ </Route>
150
+ {moduleRoutes.map((route) => (
151
+ <Route key={route.path} path={route.path} element={route.element} />
152
+ ))}
153
+ {/* Last so every named route above wins first. Nested here rather than
154
+ outside the gate, so a signed-out visitor is redirected to /login by
155
+ `SessionGate` before this ever renders, and a signed-in one keeps the
156
+ Shell's nav instead of landing on a bare page with no way back in. */}
157
+ <Route path="*" element={<NotFoundPage />} />
158
+ </Route>
159
+ </Route>
160
+ </Routes>
161
+ )
162
+ }
@@ -0,0 +1,42 @@
1
+ import { Navigate, Outlet } from 'react-router'
2
+
3
+ import { useSession } from '../api/resources/session.ts'
4
+ import { ErrorPanel, LoadingPanel } from '../components/QueryState.tsx'
5
+
6
+ /**
7
+ * What stands between a URL and a page that needs a workspace.
8
+ *
9
+ * Three answers, and they are not the same thing:
10
+ *
11
+ * - `401` means sign in. That is a redirect.
12
+ * - Signed in with no workspace means create one. Also a redirect, to a
13
+ * different place, because sending someone to a sign-in form they have
14
+ * already passed is a loop.
15
+ * - Anything else is the service being unreachable or broken, and redirecting
16
+ * on that would hide it behind a sign-in form that will also fail.
17
+ */
18
+ export function SessionGate(): React.JSX.Element {
19
+ const { isLoading, isSignedOut, needsWorkspace, error } = useSession()
20
+
21
+ if (isSignedOut) {
22
+ return <Navigate to="/login" replace />
23
+ }
24
+
25
+ if (error !== null) {
26
+ return (
27
+ <div className="mx-auto max-w-xl px-6 py-16">
28
+ <ErrorPanel error={error} />
29
+ </div>
30
+ )
31
+ }
32
+
33
+ if (isLoading) {
34
+ return <LoadingPanel />
35
+ }
36
+
37
+ if (needsWorkspace) {
38
+ return <Navigate to="/onboarding/workspace" replace />
39
+ }
40
+
41
+ return <Outlet />
42
+ }
@@ -0,0 +1,235 @@
1
+ import type { Activity, ActivityKind, RecordTargetType } from '@kelpie/schemas'
2
+
3
+ import { useActivities } from '../api/resources/activities.ts'
4
+ import { useMembers } from '../api/resources/members.ts'
5
+ import { formatRelativeTime, monthLabel } from '../lib/dates.ts'
6
+ import { ErrorPanel } from './QueryState.tsx'
7
+ import { SectionHeader } from './SectionHeader.tsx'
8
+
9
+ /**
10
+ * What happened to one record, newest first, grouped by month.
11
+ *
12
+ * Read-only, because the API is. Every row here was written by the service that
13
+ * made the change.
14
+ *
15
+ * The roll-up is the server's: a person's timeline already carries the deals and
16
+ * partnerships they are on, so nothing here fetches related records to merge in.
17
+ *
18
+ * A rolled-up row says which kind of record it came from and stops there. The
19
+ * mockup also names it and links to it, which needs the Deals, Opportunities and
20
+ * Partnerships endpoints. Naming a record this page cannot fetch would mean
21
+ * printing an id or inventing a label, and both are worse than the type alone.
22
+ */
23
+
24
+ export interface ActivitiesPanelProps {
25
+ readonly targetType: RecordTargetType
26
+ readonly targetId: string
27
+ }
28
+
29
+ /** Two letters per kind, as the mockup's timeline gutter shows them. */
30
+ const KIND_GLYPHS: Readonly<Record<ActivityKind, string>> = {
31
+ created: 'Cr',
32
+ updated: 'Up',
33
+ stage_changed: 'St',
34
+ note_added: 'Nt',
35
+ email: 'Em',
36
+ call: 'Ca',
37
+ meeting: 'Mt',
38
+ linked: 'Ln',
39
+ unlinked: 'Un',
40
+ }
41
+
42
+ const TARGET_TYPE_LABELS: Readonly<Record<RecordTargetType, string>> = {
43
+ person: 'Person',
44
+ company: 'Company',
45
+ deal: 'Deal',
46
+ opportunity: 'Opportunity',
47
+ partnership: 'Partnership',
48
+ raise: 'Raise',
49
+ candidate: 'Candidate',
50
+ }
51
+
52
+ interface MonthGroup {
53
+ readonly label: string
54
+ readonly items: readonly Activity[]
55
+ }
56
+
57
+ /** Consecutive runs, not a map: the list is already ordered, so a month never recurs. */
58
+ function groupByMonth(activities: readonly Activity[], now: Date): readonly MonthGroup[] {
59
+ const groups: { label: string; items: Activity[] }[] = []
60
+
61
+ for (const activity of activities) {
62
+ const label = monthLabel(activity.createdAt, now)
63
+ const last = groups.at(-1)
64
+
65
+ if (last?.label === label) {
66
+ last.items.push(activity)
67
+ } else {
68
+ groups.push({ label, items: [activity] })
69
+ }
70
+ }
71
+
72
+ return groups
73
+ }
74
+
75
+ export function ActivitiesPanel({
76
+ targetType,
77
+ targetId,
78
+ }: ActivitiesPanelProps): React.JSX.Element {
79
+ const activities = useActivities({ targetType, targetId })
80
+ const members = useMembers()
81
+ const groups = groupByMonth(activities.records, new Date())
82
+
83
+ return (
84
+ <section>
85
+ <SectionHeader title="Activity" />
86
+
87
+ {activities.error !== null && <ErrorPanel error={activities.error} />}
88
+ {activities.isLoading && <p className="text-[13px] text-ink-faint">Loading activity…</p>}
89
+
90
+ {!activities.isLoading && activities.records.length === 0 && activities.error === null && (
91
+ <p className="text-[13px] text-ink-faint">No activity yet.</p>
92
+ )}
93
+
94
+ <div className="space-y-4">
95
+ {groups.map((group) => (
96
+ <div key={group.label}>
97
+ <h3 className="mb-2 text-[12px] font-semibold text-ink">{group.label}</h3>
98
+ <ol className="overflow-hidden rounded-md border border-border">
99
+ {group.items.map((activity, index) => (
100
+ <ActivityEvent
101
+ key={activity.id}
102
+ activity={activity}
103
+ actorName={actorNameFor(activity, members.nameById)}
104
+ contextType={targetType}
105
+ contextId={targetId}
106
+ isLast={index === group.items.length - 1}
107
+ />
108
+ ))}
109
+ </ol>
110
+ </div>
111
+ ))}
112
+ </div>
113
+
114
+ {activities.hasMore && (
115
+ <button
116
+ type="button"
117
+ onClick={activities.loadMore}
118
+ disabled={activities.isLoadingMore}
119
+ className="mt-3 rounded-md border border-border px-3 py-1.5 text-[12px] font-medium text-ink-muted transition hover:border-border-strong hover:text-ink"
120
+ >
121
+ {activities.isLoadingMore ? 'Loading…' : 'Load more'}
122
+ </button>
123
+ )}
124
+ </section>
125
+ )
126
+ }
127
+
128
+ /**
129
+ * The single most recent event, for a record's Overview tab.
130
+ *
131
+ * Its own request rather than a slice of the panel's: the panel lives on a
132
+ * different tab, so on Overview there is no list to take the first row of.
133
+ */
134
+ export function LatestActivity({
135
+ targetType,
136
+ targetId,
137
+ }: ActivitiesPanelProps): React.JSX.Element {
138
+ const activities = useActivities({ targetType, targetId })
139
+ const members = useMembers()
140
+ const latest = activities.records[0]
141
+
142
+ return (
143
+ <section>
144
+ <SectionHeader title="Latest activity" />
145
+
146
+ {activities.error !== null && <ErrorPanel error={activities.error} />}
147
+ {activities.isLoading && <p className="text-[13px] text-ink-faint">Loading activity…</p>}
148
+
149
+ {!activities.isLoading && latest === undefined && activities.error === null && (
150
+ <p className="text-[13px] text-ink-faint">No activity yet.</p>
151
+ )}
152
+
153
+ {latest !== undefined && (
154
+ <ol className="overflow-hidden rounded-md border border-border">
155
+ <ActivityEvent
156
+ activity={latest}
157
+ actorName={actorNameFor(latest, members.nameById)}
158
+ contextType={targetType}
159
+ contextId={targetId}
160
+ isLast
161
+ />
162
+ </ol>
163
+ )}
164
+ </section>
165
+ )
166
+ }
167
+
168
+ /**
169
+ * Exactly one of the two actor columns is set. `actorLabel` carries the display
170
+ * name when nothing on the team did this: "Form", "Gmail", "API key".
171
+ */
172
+ function actorNameFor(activity: Activity, nameById: ReadonlyMap<string, string>): string {
173
+ if (activity.actorMemberId === null) {
174
+ return activity.actorLabel ?? 'System'
175
+ }
176
+
177
+ return nameById.get(activity.actorMemberId) ?? 'Unknown'
178
+ }
179
+
180
+ function ActivityEvent({
181
+ activity,
182
+ actorName,
183
+ contextType,
184
+ contextId,
185
+ isLast,
186
+ }: {
187
+ readonly activity: Activity
188
+ readonly actorName: string
189
+ readonly contextType: RecordTargetType
190
+ readonly contextId: string
191
+ readonly isLast: boolean
192
+ }): React.JSX.Element {
193
+ const isRolledUp = activity.targetType !== contextType || activity.targetId !== contextId
194
+
195
+ return (
196
+ <li className="flex gap-2 border-b border-border px-4 py-3 last:border-0">
197
+ <div className="relative flex w-5 shrink-0 justify-center">
198
+ {!isLast && (
199
+ <span
200
+ aria-hidden
201
+ className="absolute top-5 bottom-[-12px] left-1/2 w-px -translate-x-1/2 bg-border"
202
+ />
203
+ )}
204
+ <div
205
+ className="relative z-10 flex h-5 w-5 items-center justify-center rounded border border-border bg-surface text-[9px] font-semibold tracking-wide text-ink-muted uppercase"
206
+ title={activity.kind}
207
+ >
208
+ {KIND_GLYPHS[activity.kind]}
209
+ </div>
210
+ </div>
211
+ <div className="min-w-0 flex-1">
212
+ <div className="flex items-baseline justify-between gap-3">
213
+ <p className="min-w-0 text-[12px] leading-snug text-ink">
214
+ <span className="font-semibold">{actorName}</span>{' '}
215
+ <span className="text-ink-muted">{activity.action}</span>
216
+ </p>
217
+ <time
218
+ dateTime={activity.createdAt.toISOString()}
219
+ className="shrink-0 text-[11px] text-ink-faint"
220
+ >
221
+ {formatRelativeTime(activity.createdAt)}
222
+ </time>
223
+ </div>
224
+ {isRolledUp && (
225
+ <p className="text-[11px] leading-snug text-ink-faint">
226
+ on <span className="text-ink-muted">{TARGET_TYPE_LABELS[activity.targetType]}</span>
227
+ </p>
228
+ )}
229
+ {activity.detail !== null && (
230
+ <p className="text-[11px] leading-snug text-ink-faint">{activity.detail}</p>
231
+ )}
232
+ </div>
233
+ </li>
234
+ )
235
+ }