@kelpie/ui 0.7.0 → 0.9.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 (349) hide show
  1. package/dist/api/resource.d.ts +59 -6
  2. package/dist/api/resource.d.ts.map +1 -1
  3. package/dist/api/resource.js +106 -24
  4. package/dist/api/resource.js.map +1 -1
  5. package/dist/api/resources/companies.d.ts +2 -0
  6. package/dist/api/resources/companies.d.ts.map +1 -1
  7. package/dist/api/resources/companies.js +5 -1
  8. package/dist/api/resources/companies.js.map +1 -1
  9. package/dist/api/resources/consentPurposes.d.ts +13 -0
  10. package/dist/api/resources/consentPurposes.d.ts.map +1 -0
  11. package/dist/api/resources/consentPurposes.js +39 -0
  12. package/dist/api/resources/consentPurposes.js.map +1 -0
  13. package/dist/api/resources/customFields.d.ts +15 -0
  14. package/dist/api/resources/customFields.d.ts.map +1 -0
  15. package/dist/api/resources/customFields.js +41 -0
  16. package/dist/api/resources/customFields.js.map +1 -0
  17. package/dist/api/resources/decisions.d.ts +2 -0
  18. package/dist/api/resources/decisions.d.ts.map +1 -1
  19. package/dist/api/resources/decisions.js +1 -0
  20. package/dist/api/resources/decisions.js.map +1 -1
  21. package/dist/api/resources/emailDomainLinker.d.ts +16 -0
  22. package/dist/api/resources/emailDomainLinker.d.ts.map +1 -0
  23. package/dist/api/resources/emailDomainLinker.js +16 -0
  24. package/dist/api/resources/emailDomainLinker.js.map +1 -0
  25. package/dist/api/resources/enquiries.d.ts +39 -0
  26. package/dist/api/resources/enquiries.d.ts.map +1 -0
  27. package/dist/api/resources/enquiries.js +68 -0
  28. package/dist/api/resources/enquiries.js.map +1 -0
  29. package/dist/api/resources/forms.d.ts +21 -1
  30. package/dist/api/resources/forms.d.ts.map +1 -1
  31. package/dist/api/resources/forms.js +44 -17
  32. package/dist/api/resources/forms.js.map +1 -1
  33. package/dist/api/resources/handbookPages.d.ts +1 -1
  34. package/dist/api/resources/handbookPages.js +1 -1
  35. package/dist/api/resources/importJobs.d.ts +5 -0
  36. package/dist/api/resources/importJobs.d.ts.map +1 -1
  37. package/dist/api/resources/importJobs.js +3 -0
  38. package/dist/api/resources/importJobs.js.map +1 -1
  39. package/dist/api/resources/listMembers.d.ts +27 -0
  40. package/dist/api/resources/listMembers.d.ts.map +1 -0
  41. package/dist/api/resources/listMembers.js +108 -0
  42. package/dist/api/resources/listMembers.js.map +1 -0
  43. package/dist/api/resources/lists.d.ts +14 -0
  44. package/dist/api/resources/lists.d.ts.map +1 -0
  45. package/dist/api/resources/lists.js +34 -0
  46. package/dist/api/resources/lists.js.map +1 -0
  47. package/dist/api/resources/opportunities.d.ts +2 -0
  48. package/dist/api/resources/opportunities.d.ts.map +1 -1
  49. package/dist/api/resources/opportunities.js +1 -0
  50. package/dist/api/resources/opportunities.js.map +1 -1
  51. package/dist/api/resources/people.d.ts.map +1 -1
  52. package/dist/api/resources/people.js +4 -1
  53. package/dist/api/resources/people.js.map +1 -1
  54. package/dist/api/resources/roles.d.ts +2 -0
  55. package/dist/api/resources/roles.d.ts.map +1 -1
  56. package/dist/api/resources/roles.js +1 -1
  57. package/dist/api/resources/roles.js.map +1 -1
  58. package/dist/api/resources/sampleData.d.ts +17 -0
  59. package/dist/api/resources/sampleData.d.ts.map +1 -0
  60. package/dist/api/resources/sampleData.js +31 -0
  61. package/dist/api/resources/sampleData.js.map +1 -0
  62. package/dist/api/resources/webhooks.d.ts.map +1 -1
  63. package/dist/api/resources/webhooks.js +7 -22
  64. package/dist/api/resources/webhooks.js.map +1 -1
  65. package/dist/app/KelpieApp.d.ts.map +1 -1
  66. package/dist/app/KelpieApp.js +9 -1
  67. package/dist/app/KelpieApp.js.map +1 -1
  68. package/dist/components/ActivitiesPanel.d.ts.map +1 -1
  69. package/dist/components/ActivitiesPanel.js +3 -1
  70. package/dist/components/ActivitiesPanel.js.map +1 -1
  71. package/dist/components/ColumnPicker.d.ts +24 -0
  72. package/dist/components/ColumnPicker.d.ts.map +1 -0
  73. package/dist/components/ColumnPicker.js +56 -0
  74. package/dist/components/ColumnPicker.js.map +1 -0
  75. package/dist/components/CustomFieldsPanel.d.ts +23 -0
  76. package/dist/components/CustomFieldsPanel.d.ts.map +1 -0
  77. package/dist/components/CustomFieldsPanel.js +116 -0
  78. package/dist/components/CustomFieldsPanel.js.map +1 -0
  79. package/dist/components/DataTable.d.ts +16 -1
  80. package/dist/components/DataTable.d.ts.map +1 -1
  81. package/dist/components/DataTable.js +51 -10
  82. package/dist/components/DataTable.js.map +1 -1
  83. package/dist/components/DecisionsPanel.d.ts.map +1 -1
  84. package/dist/components/DecisionsPanel.js +4 -3
  85. package/dist/components/DecisionsPanel.js.map +1 -1
  86. package/dist/components/EntitySearch.d.ts.map +1 -1
  87. package/dist/components/EntitySearch.js +11 -5
  88. package/dist/components/EntitySearch.js.map +1 -1
  89. package/dist/components/FormsPanel.d.ts +18 -0
  90. package/dist/components/FormsPanel.d.ts.map +1 -0
  91. package/dist/components/FormsPanel.js +37 -0
  92. package/dist/components/FormsPanel.js.map +1 -0
  93. package/dist/components/ListsPanel.d.ts +14 -0
  94. package/dist/components/ListsPanel.d.ts.map +1 -0
  95. package/dist/components/ListsPanel.js +56 -0
  96. package/dist/components/ListsPanel.js.map +1 -0
  97. package/dist/components/NotesPanel.d.ts.map +1 -1
  98. package/dist/components/NotesPanel.js +6 -5
  99. package/dist/components/NotesPanel.js.map +1 -1
  100. package/dist/components/Paginator.d.ts +26 -0
  101. package/dist/components/Paginator.d.ts.map +1 -0
  102. package/dist/components/Paginator.js +16 -0
  103. package/dist/components/Paginator.js.map +1 -0
  104. package/dist/components/PlanAttention.d.ts +3 -2
  105. package/dist/components/PlanAttention.d.ts.map +1 -1
  106. package/dist/components/PlanAttention.js +7 -3
  107. package/dist/components/PlanAttention.js.map +1 -1
  108. package/dist/components/PlanPanel.d.ts.map +1 -1
  109. package/dist/components/PlanPanel.js +2 -1
  110. package/dist/components/PlanPanel.js.map +1 -1
  111. package/dist/components/Shell.d.ts.map +1 -1
  112. package/dist/components/Shell.js +4 -0
  113. package/dist/components/Shell.js.map +1 -1
  114. package/dist/components/useHasCustomFields.d.ts +13 -0
  115. package/dist/components/useHasCustomFields.d.ts.map +1 -0
  116. package/dist/components/useHasCustomFields.js +16 -0
  117. package/dist/components/useHasCustomFields.js.map +1 -0
  118. package/dist/index.d.ts +8 -2
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +4 -1
  121. package/dist/index.js.map +1 -1
  122. package/dist/lib/listView.d.ts +15 -0
  123. package/dist/lib/listView.d.ts.map +1 -0
  124. package/dist/lib/listView.js +66 -0
  125. package/dist/lib/listView.js.map +1 -0
  126. package/dist/lib/sort.d.ts +43 -0
  127. package/dist/lib/sort.d.ts.map +1 -0
  128. package/dist/lib/sort.js +102 -0
  129. package/dist/lib/sort.js.map +1 -0
  130. package/dist/pages/CompaniesPage.d.ts.map +1 -1
  131. package/dist/pages/CompaniesPage.js +88 -3
  132. package/dist/pages/CompaniesPage.js.map +1 -1
  133. package/dist/pages/CompanyDetail.d.ts.map +1 -1
  134. package/dist/pages/CompanyDetail.js +40 -15
  135. package/dist/pages/CompanyDetail.js.map +1 -1
  136. package/dist/pages/DealDetail.d.ts.map +1 -1
  137. package/dist/pages/DealDetail.js +20 -1
  138. package/dist/pages/DealDetail.js.map +1 -1
  139. package/dist/pages/DealsPage.d.ts.map +1 -1
  140. package/dist/pages/DealsPage.js +134 -14
  141. package/dist/pages/DealsPage.js.map +1 -1
  142. package/dist/pages/DecisionsPage.d.ts.map +1 -1
  143. package/dist/pages/DecisionsPage.js +52 -8
  144. package/dist/pages/DecisionsPage.js.map +1 -1
  145. package/dist/pages/EnquiriesPage.d.ts +2 -0
  146. package/dist/pages/EnquiriesPage.d.ts.map +1 -0
  147. package/dist/pages/EnquiriesPage.js +251 -0
  148. package/dist/pages/EnquiriesPage.js.map +1 -0
  149. package/dist/pages/EnquiryDetail.d.ts +2 -0
  150. package/dist/pages/EnquiryDetail.d.ts.map +1 -0
  151. package/dist/pages/EnquiryDetail.js +207 -0
  152. package/dist/pages/EnquiryDetail.js.map +1 -0
  153. package/dist/pages/EnquiryStageSettingsPage.d.ts +3 -0
  154. package/dist/pages/EnquiryStageSettingsPage.d.ts.map +1 -0
  155. package/dist/pages/EnquiryStageSettingsPage.js +34 -0
  156. package/dist/pages/EnquiryStageSettingsPage.js.map +1 -0
  157. package/dist/pages/FormDetail.d.ts.map +1 -1
  158. package/dist/pages/FormDetail.js +19 -1
  159. package/dist/pages/FormDetail.js.map +1 -1
  160. package/dist/pages/FormsPage.d.ts.map +1 -1
  161. package/dist/pages/FormsPage.js +53 -2
  162. package/dist/pages/FormsPage.js.map +1 -1
  163. package/dist/pages/FundraisingPage.d.ts.map +1 -1
  164. package/dist/pages/FundraisingPage.js +116 -14
  165. package/dist/pages/FundraisingPage.js.map +1 -1
  166. package/dist/pages/HiringPage.d.ts.map +1 -1
  167. package/dist/pages/HiringPage.js +27 -4
  168. package/dist/pages/HiringPage.js.map +1 -1
  169. package/dist/pages/ListDetail.d.ts +11 -0
  170. package/dist/pages/ListDetail.d.ts.map +1 -0
  171. package/dist/pages/ListDetail.js +214 -0
  172. package/dist/pages/ListDetail.js.map +1 -0
  173. package/dist/pages/ListsPage.d.ts +9 -0
  174. package/dist/pages/ListsPage.d.ts.map +1 -0
  175. package/dist/pages/ListsPage.js +125 -0
  176. package/dist/pages/ListsPage.js.map +1 -0
  177. package/dist/pages/OpportunitiesPage.d.ts.map +1 -1
  178. package/dist/pages/OpportunitiesPage.js +97 -14
  179. package/dist/pages/OpportunitiesPage.js.map +1 -1
  180. package/dist/pages/OpportunityDetail.d.ts.map +1 -1
  181. package/dist/pages/OpportunityDetail.js +64 -3
  182. package/dist/pages/OpportunityDetail.js.map +1 -1
  183. package/dist/pages/PartnershipDetail.d.ts.map +1 -1
  184. package/dist/pages/PartnershipDetail.js +19 -1
  185. package/dist/pages/PartnershipDetail.js.map +1 -1
  186. package/dist/pages/PartnershipsPage.d.ts.map +1 -1
  187. package/dist/pages/PartnershipsPage.js +111 -14
  188. package/dist/pages/PartnershipsPage.js.map +1 -1
  189. package/dist/pages/PeoplePage.d.ts.map +1 -1
  190. package/dist/pages/PeoplePage.js +119 -3
  191. package/dist/pages/PeoplePage.js.map +1 -1
  192. package/dist/pages/PersonDetail.d.ts.map +1 -1
  193. package/dist/pages/PersonDetail.js +67 -5
  194. package/dist/pages/PersonDetail.js.map +1 -1
  195. package/dist/pages/PlanningPage.d.ts.map +1 -1
  196. package/dist/pages/PlanningPage.js +88 -17
  197. package/dist/pages/PlanningPage.js.map +1 -1
  198. package/dist/pages/RaiseDetail.d.ts.map +1 -1
  199. package/dist/pages/RaiseDetail.js +13 -1
  200. package/dist/pages/RaiseDetail.js.map +1 -1
  201. package/dist/pages/RoleDetail.d.ts.map +1 -1
  202. package/dist/pages/RoleDetail.js +5 -4
  203. package/dist/pages/RoleDetail.js.map +1 -1
  204. package/dist/pages/SearchPage.d.ts.map +1 -1
  205. package/dist/pages/SearchPage.js +1 -0
  206. package/dist/pages/SearchPage.js.map +1 -1
  207. package/dist/pages/admin/DataPage.d.ts.map +1 -1
  208. package/dist/pages/admin/DataPage.js +126 -13
  209. package/dist/pages/admin/DataPage.js.map +1 -1
  210. package/dist/pages/admin/FieldsPage.d.ts +2 -0
  211. package/dist/pages/admin/FieldsPage.d.ts.map +1 -0
  212. package/dist/pages/admin/FieldsPage.js +164 -0
  213. package/dist/pages/admin/FieldsPage.js.map +1 -0
  214. package/dist/pages/admin/PrivacyPage.d.ts +9 -0
  215. package/dist/pages/admin/PrivacyPage.d.ts.map +1 -0
  216. package/dist/pages/admin/PrivacyPage.js +170 -0
  217. package/dist/pages/admin/PrivacyPage.js.map +1 -0
  218. package/dist/pages/admin/WebhookDeliveries.d.ts.map +1 -1
  219. package/dist/pages/admin/WebhookDeliveries.js +3 -2
  220. package/dist/pages/admin/WebhookDeliveries.js.map +1 -1
  221. package/dist/pages/admin/WebhooksPage.d.ts.map +1 -1
  222. package/dist/pages/admin/WebhooksPage.js +3 -2
  223. package/dist/pages/admin/WebhooksPage.js.map +1 -1
  224. package/dist/pages/admin/WorkspaceSettingsPage.d.ts.map +1 -1
  225. package/dist/pages/admin/WorkspaceSettingsPage.js +45 -2
  226. package/dist/pages/admin/WorkspaceSettingsPage.js.map +1 -1
  227. package/dist/pages/dashboard/attention.d.ts.map +1 -1
  228. package/dist/pages/dashboard/attention.js +3 -0
  229. package/dist/pages/dashboard/attention.js.map +1 -1
  230. package/dist/pages/forms/AddFieldMenu.d.ts +17 -0
  231. package/dist/pages/forms/AddFieldMenu.d.ts.map +1 -0
  232. package/dist/pages/forms/AddFieldMenu.js +43 -0
  233. package/dist/pages/forms/AddFieldMenu.js.map +1 -0
  234. package/dist/pages/forms/EmbedPanel.d.ts +4 -0
  235. package/dist/pages/forms/EmbedPanel.d.ts.map +1 -1
  236. package/dist/pages/forms/EmbedPanel.js +62 -3
  237. package/dist/pages/forms/EmbedPanel.js.map +1 -1
  238. package/dist/pages/forms/FieldsEditor.d.ts.map +1 -1
  239. package/dist/pages/forms/FieldsEditor.js +179 -36
  240. package/dist/pages/forms/FieldsEditor.js.map +1 -1
  241. package/dist/pages/forms/FormActions.d.ts +6 -0
  242. package/dist/pages/forms/FormActions.d.ts.map +1 -0
  243. package/dist/pages/forms/FormActions.js +149 -0
  244. package/dist/pages/forms/FormActions.js.map +1 -0
  245. package/dist/pages/forms/FormSettings.d.ts.map +1 -1
  246. package/dist/pages/forms/FormSettings.js +15 -19
  247. package/dist/pages/forms/FormSettings.js.map +1 -1
  248. package/dist/pages/forms/SubmissionDetail.d.ts +2 -0
  249. package/dist/pages/forms/SubmissionDetail.d.ts.map +1 -0
  250. package/dist/pages/forms/SubmissionDetail.js +76 -0
  251. package/dist/pages/forms/SubmissionDetail.js.map +1 -0
  252. package/dist/pages/forms/SubmissionsTable.d.ts.map +1 -1
  253. package/dist/pages/forms/SubmissionsTable.js +57 -8
  254. package/dist/pages/forms/SubmissionsTable.js.map +1 -1
  255. package/dist/pages/forms/fieldList.d.ts +11 -5
  256. package/dist/pages/forms/fieldList.d.ts.map +1 -1
  257. package/dist/pages/forms/fieldList.js +66 -6
  258. package/dist/pages/forms/fieldList.js.map +1 -1
  259. package/dist/pages/forms/template.d.ts +17 -0
  260. package/dist/pages/forms/template.d.ts.map +1 -1
  261. package/dist/pages/forms/template.js +93 -0
  262. package/dist/pages/forms/template.js.map +1 -1
  263. package/dist/pages/handbook/HandbookPage.js +1 -1
  264. package/dist/pages/hiringDirectory.js +2 -2
  265. package/dist/pages/onboarding/WorkspaceStepPage.d.ts.map +1 -1
  266. package/dist/pages/onboarding/WorkspaceStepPage.js +15 -2
  267. package/dist/pages/onboarding/WorkspaceStepPage.js.map +1 -1
  268. package/dist/pages/positionDirectory.js +2 -2
  269. package/package.json +2 -2
  270. package/src/api/resource.ts +155 -32
  271. package/src/api/resources/companies.ts +7 -1
  272. package/src/api/resources/consentPurposes.ts +83 -0
  273. package/src/api/resources/customFields.ts +88 -0
  274. package/src/api/resources/decisions.ts +3 -0
  275. package/src/api/resources/emailDomainLinker.ts +43 -0
  276. package/src/api/resources/enquiries.ts +118 -0
  277. package/src/api/resources/forms.ts +59 -19
  278. package/src/api/resources/handbookPages.ts +1 -1
  279. package/src/api/resources/importJobs.ts +9 -0
  280. package/src/api/resources/listMembers.ts +173 -0
  281. package/src/api/resources/lists.ts +61 -0
  282. package/src/api/resources/opportunities.ts +3 -0
  283. package/src/api/resources/people.ts +4 -1
  284. package/src/api/resources/roles.ts +3 -1
  285. package/src/api/resources/sampleData.ts +57 -0
  286. package/src/api/resources/webhooks.ts +8 -24
  287. package/src/app/KelpieApp.tsx +16 -0
  288. package/src/components/ActivitiesPanel.tsx +3 -10
  289. package/src/components/ColumnPicker.tsx +124 -0
  290. package/src/components/CustomFieldsPanel.tsx +330 -0
  291. package/src/components/DataTable.tsx +89 -10
  292. package/src/components/DecisionsPanel.tsx +4 -12
  293. package/src/components/EntitySearch.tsx +12 -5
  294. package/src/components/FormsPanel.tsx +86 -0
  295. package/src/components/ListsPanel.tsx +176 -0
  296. package/src/components/NotesPanel.tsx +6 -14
  297. package/src/components/Paginator.tsx +78 -0
  298. package/src/components/PlanAttention.tsx +20 -3
  299. package/src/components/PlanPanel.tsx +2 -10
  300. package/src/components/Shell.tsx +4 -0
  301. package/src/components/useHasCustomFields.ts +18 -0
  302. package/src/index.ts +10 -1
  303. package/src/lib/listView.ts +149 -0
  304. package/src/lib/sort.ts +143 -0
  305. package/src/pages/CompaniesPage.tsx +125 -11
  306. package/src/pages/CompanyDetail.tsx +98 -63
  307. package/src/pages/DealDetail.tsx +34 -0
  308. package/src/pages/DealsPage.tsx +178 -24
  309. package/src/pages/DecisionsPage.tsx +75 -18
  310. package/src/pages/EnquiriesPage.tsx +434 -0
  311. package/src/pages/EnquiryDetail.tsx +554 -0
  312. package/src/pages/EnquiryStageSettingsPage.tsx +63 -0
  313. package/src/pages/FormDetail.tsx +23 -1
  314. package/src/pages/FormsPage.tsx +81 -17
  315. package/src/pages/FundraisingPage.tsx +152 -24
  316. package/src/pages/HiringPage.tsx +39 -11
  317. package/src/pages/ListDetail.tsx +470 -0
  318. package/src/pages/ListsPage.tsx +281 -0
  319. package/src/pages/OpportunitiesPage.tsx +130 -24
  320. package/src/pages/OpportunityDetail.tsx +168 -2
  321. package/src/pages/PartnershipDetail.tsx +35 -0
  322. package/src/pages/PartnershipsPage.tsx +149 -24
  323. package/src/pages/PeoplePage.tsx +157 -11
  324. package/src/pages/PersonDetail.tsx +157 -6
  325. package/src/pages/PlanningPage.tsx +259 -29
  326. package/src/pages/RaiseDetail.tsx +24 -0
  327. package/src/pages/RoleDetail.tsx +21 -26
  328. package/src/pages/SearchPage.tsx +1 -0
  329. package/src/pages/admin/DataPage.tsx +324 -13
  330. package/src/pages/admin/FieldsPage.tsx +455 -0
  331. package/src/pages/admin/PrivacyPage.tsx +461 -0
  332. package/src/pages/admin/WebhookDeliveries.tsx +10 -15
  333. package/src/pages/admin/WebhooksPage.tsx +14 -19
  334. package/src/pages/admin/WorkspaceSettingsPage.tsx +134 -2
  335. package/src/pages/dashboard/attention.ts +3 -0
  336. package/src/pages/forms/AddFieldMenu.tsx +121 -0
  337. package/src/pages/forms/EmbedPanel.tsx +163 -2
  338. package/src/pages/forms/FieldsEditor.tsx +539 -165
  339. package/src/pages/forms/FormActions.tsx +552 -0
  340. package/src/pages/forms/FormSettings.tsx +29 -70
  341. package/src/pages/forms/SubmissionDetail.tsx +249 -0
  342. package/src/pages/forms/SubmissionsTable.tsx +112 -26
  343. package/src/pages/forms/fieldList.ts +68 -5
  344. package/src/pages/forms/template.ts +103 -0
  345. package/src/pages/handbook/HandbookPage.tsx +1 -1
  346. package/src/pages/hiringDirectory.ts +2 -2
  347. package/src/pages/onboarding/WorkspaceStepPage.tsx +31 -3
  348. package/src/pages/positionDirectory.ts +2 -2
  349. package/src/styles.css +3 -3
@@ -31,4 +31,97 @@ export const NEW_SELECT_OPTIONS = [
31
31
  { key: 'option_a', value: 'Option A', valueType: 'string' },
32
32
  { key: 'option_b', value: 'Option B', valueType: 'string' },
33
33
  ];
34
+ /**
35
+ * One ready-made field per CRM mapping target, in the target enum's order.
36
+ *
37
+ * "Add field" offers these so adding the company field is one click, not
38
+ * add-then-configure. Only one field may carry a CRM target, so the menu shows
39
+ * each preset only while its target is free — `unusedCrmPresets` in
40
+ * `fieldList.ts` does that filtering.
41
+ */
42
+ export const CRM_FIELD_PRESETS = [
43
+ { label: 'Name', type: 'text', required: false, mapTo: 'person.name', placeholder: 'Your name' },
44
+ // The other way to ask for a name. A form takes one box or this pair; the
45
+ // menu hides whichever is already mapped, so both are offered and neither
46
+ // ends up used twice.
47
+ {
48
+ label: 'First name',
49
+ type: 'text',
50
+ required: false,
51
+ mapTo: 'person.first_name',
52
+ placeholder: 'First name',
53
+ },
54
+ {
55
+ label: 'Last name',
56
+ type: 'text',
57
+ required: false,
58
+ mapTo: 'person.last_name',
59
+ placeholder: 'Last name',
60
+ },
61
+ {
62
+ label: 'Email',
63
+ type: 'email',
64
+ required: true,
65
+ mapTo: 'person.email',
66
+ placeholder: 'you@company.com',
67
+ },
68
+ { label: 'Company', type: 'text', required: false, mapTo: 'company.name', placeholder: 'Company name' },
69
+ {
70
+ label: 'Company website',
71
+ type: 'text',
72
+ required: false,
73
+ mapTo: 'company.domain',
74
+ placeholder: 'company.com',
75
+ },
76
+ { label: 'Job title', type: 'text', required: false, mapTo: 'position.title', placeholder: 'Your role' },
77
+ { label: 'Enquiry name', type: 'text', required: false, mapTo: 'enquiry.name', placeholder: null },
78
+ { label: 'Deal name', type: 'text', required: false, mapTo: 'deal.name', placeholder: null },
79
+ { label: 'Opportunity name', type: 'text', required: false, mapTo: 'opportunity.name', placeholder: null },
80
+ { label: 'Partnership name', type: 'text', required: false, mapTo: 'partnership.name', placeholder: null },
81
+ ];
82
+ /** The submission-only fields "Add field" always offers; they may repeat freely. */
83
+ export const SUBMISSION_FIELD_PRESETS = [
84
+ { menuLabel: 'Text', field: NEW_FIELD },
85
+ {
86
+ menuLabel: 'Text area',
87
+ field: { label: 'Message', type: 'textarea', required: false, mapTo: 'submission', placeholder: null },
88
+ },
89
+ {
90
+ menuLabel: 'Select',
91
+ field: {
92
+ label: 'New select',
93
+ type: 'select',
94
+ required: false,
95
+ mapTo: 'submission',
96
+ placeholder: null,
97
+ options: NEW_SELECT_OPTIONS,
98
+ },
99
+ },
100
+ {
101
+ menuLabel: 'Consent',
102
+ field: {
103
+ label: 'Consent',
104
+ type: 'consent',
105
+ required: false,
106
+ mapTo: 'person.consent',
107
+ placeholder: null,
108
+ statement: 'Please tell us how we can contact you.',
109
+ consentPurposeIds: [],
110
+ consentPurposeLabels: {},
111
+ },
112
+ },
113
+ {
114
+ menuLabel: 'Notice',
115
+ field: {
116
+ label: 'Privacy notice',
117
+ type: 'notice',
118
+ required: false,
119
+ mapTo: 'person.consent',
120
+ placeholder: null,
121
+ statement: 'By submitting this form you agree to us storing your information and using it to contact you about your enquiry.',
122
+ consentPurposeIds: [],
123
+ consentPurposeLabels: {},
124
+ },
125
+ },
126
+ ];
34
127
  //# sourceMappingURL=template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/pages/forms/template.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA8B;IAC5D,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE;IAC/F;QACE,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,iBAAiB;KAC/B;IACD,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE;IACtF,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE;IACvF,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE;CAC7F,CAAA;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,SAAS,GAAmB;IACvC,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,KAAK;IACf,KAAK,EAAE,YAAY;IACnB,WAAW,EAAE,IAAI;CAClB,CAAA;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAiB,EAAE;IACpE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAiB,EAAE;CACrE,CAAA"}
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../src/pages/forms/template.ts"],"names":[],"mappings":"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"}
@@ -129,7 +129,7 @@ export function HandbookLayout() {
129
129
  void addPage(item.id);
130
130
  }, onDelete: () => {
131
131
  void removePage(item.page);
132
- } }, item.id))) }) }), _jsx(DragOverlay, { dropAnimation: null, children: dragging === undefined ? null : (_jsx("div", { className: "rounded-md border border-accent bg-surface-raised px-2.5 py-1.5 text-[13px] font-medium text-ink", style: { marginLeft: (liveDepth ?? dragging.depth) * INDENT }, children: dragging.page.title })) })] }), flat.length === 0 && (_jsx("p", { className: "px-2 py-6 text-center text-[12px] text-ink-faint", children: "No pages yet." })), pages.hasMore && (_jsx("p", { className: "px-2 py-3 text-center text-[11px] text-ink-faint", children: "This handbook has more pages than one request returns, so the tree below is incomplete." }))] })] }), _jsx("div", { className: "min-w-0 flex-1", children: active === undefined ? (_jsx("div", { className: "flex h-full items-center justify-center text-[13px] text-ink-faint", children: "No handbook pages yet." })) : (_jsx(HandbookEditor, { page: active, authorName: active.updatedBy === null ? undefined : members.nameById.get(active.updatedBy), isSaving: updatePage.isPending, error: updatePage.error ?? deletePage.error, onSave: (changes) => {
132
+ } }, item.id))) }) }), _jsx(DragOverlay, { dropAnimation: null, children: dragging === undefined ? null : (_jsx("div", { className: "rounded-md border border-accent bg-surface-raised px-2.5 py-1.5 text-[13px] font-medium text-ink", style: { marginLeft: (liveDepth ?? dragging.depth) * INDENT }, children: dragging.page.title })) })] }), flat.length === 0 && (_jsx("p", { className: "px-2 py-6 text-center text-[12px] text-ink-faint", children: "No pages yet." })), pages.hasNext && (_jsx("p", { className: "px-2 py-3 text-center text-[11px] text-ink-faint", children: "This handbook has more pages than one request returns, so the tree below is incomplete." }))] })] }), _jsx("div", { className: "min-w-0 flex-1", children: active === undefined ? (_jsx("div", { className: "flex h-full items-center justify-center text-[13px] text-ink-faint", children: "No handbook pages yet." })) : (_jsx(HandbookEditor, { page: active, authorName: active.updatedBy === null ? undefined : members.nameById.get(active.updatedBy), isSaving: updatePage.isPending, error: updatePage.error ?? deletePage.error, onSave: (changes) => {
133
133
  updatePage.run({ id: active.id, changes });
134
134
  }, onAddChild: () => {
135
135
  void addPage(active.id);
@@ -25,7 +25,7 @@ export function useRoleCandidateCounts(roleIds) {
25
25
  return {
26
26
  countFor: (roleId) => countByRole.get(roleId) ?? 0,
27
27
  isLoading: candidates.isLoading,
28
- isComplete: !candidates.hasMore,
28
+ isComplete: !candidates.hasNext,
29
29
  };
30
30
  }
31
31
  /**
@@ -51,7 +51,7 @@ export function useCandidateNotes(candidateIds) {
51
51
  return {
52
52
  noteFor: (candidateId) => newestByCandidate.get(candidateId),
53
53
  isLoading: notes.isLoading,
54
- isComplete: !notes.hasMore,
54
+ isComplete: !notes.hasNext,
55
55
  };
56
56
  }
57
57
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceStepPage.d.ts","sourceRoot":"","sources":["../../../src/pages/onboarding/WorkspaceStepPage.tsx"],"names":[],"mappings":"AA8CA,wBAAgB,iBAAiB,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CA2ErD"}
1
+ {"version":3,"file":"WorkspaceStepPage.d.ts","sourceRoot":"","sources":["../../../src/pages/onboarding/WorkspaceStepPage.tsx"],"names":[],"mappings":"AA+CA,wBAAgB,iBAAiB,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAsGrD"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import { Link, Navigate, useNavigate } from 'react-router';
4
+ import { useInstallSampleData } from '../../api/resources/sampleData.js';
4
5
  import { useCreateWorkspace, useSession } from '../../api/resources/session.js';
5
6
  import { ErrorPanel } from '../../components/QueryState.js';
6
7
  import { SubmitButton, TextField } from '../auth/AuthForm.js';
@@ -43,10 +44,12 @@ export function WorkspaceStepPage() {
43
44
  const navigate = useNavigate();
44
45
  const { isSignedOut } = useSession();
45
46
  const createWorkspace = useCreateWorkspace();
47
+ const installSampleData = useInstallSampleData();
46
48
  const [name, setName] = useState('');
47
49
  const [slug, setSlug] = useState('');
48
50
  const [slugEdited, setSlugEdited] = useState(false);
49
51
  const [timezone] = useState(browserTimezone);
52
+ const [seedSample, setSeedSample] = useState(false);
50
53
  function changeName(value) {
51
54
  setName(value);
52
55
  if (!slugEdited) {
@@ -61,12 +64,22 @@ export function WorkspaceStepPage() {
61
64
  event.preventDefault();
62
65
  createWorkspace
63
66
  .runAsync({ name: name.trim(), slug: slug.trim(), timezone })
64
- .then(() => navigate('/onboarding/invites', { replace: true }))
67
+ .then(async (workspace) => {
68
+ if (seedSample) {
69
+ // A refusal here does not block the wizard: the workspace itself is
70
+ // already created, and the invites step is what comes next either
71
+ // way. The error stays on screen so the reader sees what failed.
72
+ await installSampleData
73
+ .runAsync({ workspaceId: workspace.id })
74
+ .catch(() => undefined);
75
+ }
76
+ navigate('/onboarding/invites', { replace: true });
77
+ })
65
78
  .catch(() => undefined);
66
79
  }
67
80
  if (isSignedOut) {
68
81
  return _jsx(Navigate, { to: "/login", replace: true });
69
82
  }
70
- return (_jsx(AuthLayout, { step: 1, title: "Create your workspace", description: "A workspace is your company brain \u2014 CRM records, handbook, and team.", footer: _jsx(Link, { to: "/login", className: "font-medium text-accent hover:underline", children: "Sign in as somebody else" }), children: _jsxs("form", { onSubmit: submit, className: "mt-5 space-y-3", children: [_jsx(TextField, { label: "Workspace name", value: name, onChange: changeName, placeholder: "Acme Labs", autoComplete: "organization", required: true }), _jsx(TextField, { label: "Slug", value: slug, onChange: changeSlug, hint: "Lowercase letters, digits, and hyphens. It appears in URLs.", mono: true, required: true }), _jsxs("p", { className: "text-[11px] text-ink-faint", children: ["Timezone: ", timezone, ". Change it later in Admin \u2192 Workspace."] }), createWorkspace.error !== null && _jsx(ErrorPanel, { error: createWorkspace.error }), _jsx(SubmitButton, { label: "Continue", pendingLabel: "Creating\u2026", isPending: createWorkspace.isPending })] }) }));
83
+ return (_jsx(AuthLayout, { step: 1, title: "Create your workspace", description: "A workspace is your company brain \u2014 CRM records, handbook, and team.", footer: _jsx(Link, { to: "/login", className: "font-medium text-accent hover:underline", children: "Sign in as somebody else" }), children: _jsxs("form", { onSubmit: submit, className: "mt-5 space-y-3", children: [_jsx(TextField, { label: "Workspace name", value: name, onChange: changeName, placeholder: "Acme Labs", autoComplete: "organization", required: true }), _jsx(TextField, { label: "Slug", value: slug, onChange: changeSlug, hint: "Lowercase letters, digits, and hyphens. It appears in URLs.", mono: true, required: true }), _jsxs("p", { className: "text-[11px] text-ink-faint", children: ["Timezone: ", timezone, ". Change it later in Admin \u2192 Workspace."] }), _jsxs("label", { className: "flex items-start gap-2 text-[12px] text-ink", children: [_jsx("input", { type: "checkbox", checked: seedSample, onChange: (event) => setSeedSample(event.target.checked), className: "mt-0.5 h-4 w-4 rounded border-border text-accent focus:ring-accent" }), _jsx("span", { children: "Install sample data \u2014 a small set of companies, people, deals, enquiries, opportunities, fundraising, partnerships, and hiring so the workspace has something to look at. You can delete it later." })] }), createWorkspace.error !== null && _jsx(ErrorPanel, { error: createWorkspace.error }), installSampleData.error !== null && _jsx(ErrorPanel, { error: installSampleData.error }), _jsx(SubmitButton, { label: "Continue", pendingLabel: installSampleData.isPending ? 'Installing sample data…' : 'Creating…', isPending: createWorkspace.isPending || installSampleData.isPending })] }) }));
71
84
  }
72
85
  //# sourceMappingURL=WorkspaceStepPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceStepPage.js","sourceRoot":"","sources":["../../../src/pages/onboarding/WorkspaceStepPage.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkspaceStepPage.js","sourceRoot":"","sources":["../../../src/pages/onboarding/WorkspaceStepPage.tsx"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@ export function usePeopleDirectory(personIds) {
37
37
  .map((held) => companyNameById.get(held.companyId))
38
38
  .filter((name) => name !== undefined),
39
39
  isLoading: positions.isLoading || companies.isLoading,
40
- isComplete: !positions.hasMore && !companies.hasMore,
40
+ isComplete: !positions.hasNext && !companies.hasNext,
41
41
  };
42
42
  }
43
43
  export function useCompanyHeadcounts(companyIds) {
@@ -52,7 +52,7 @@ export function useCompanyHeadcounts(companyIds) {
52
52
  return {
53
53
  countFor: (companyId) => countByCompany.get(companyId) ?? 0,
54
54
  isLoading: positions.isLoading,
55
- isComplete: !positions.hasMore,
55
+ isComplete: !positions.hasNext,
56
56
  };
57
57
  }
58
58
  //# sourceMappingURL=positionDirectory.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kelpie/ui",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "React UI for Kelpie: components, pages, API client, and the extension registry an assembly composes modules through.",
5
5
  "keywords": [
6
6
  "kelpie",
@@ -48,7 +48,7 @@
48
48
  "@dnd-kit/core": "^6.3.1",
49
49
  "@dnd-kit/sortable": "^10.0.0",
50
50
  "@dnd-kit/utilities": "^3.2.2",
51
- "@kelpie/schemas": "^0.7.0",
51
+ "@kelpie/schemas": "^0.9.0",
52
52
  "@tanstack/react-query": "^5.101.4",
53
53
  "react-markdown": "^10.1.0",
54
54
  "react-router": "^8.3.0",
@@ -6,6 +6,7 @@ import {
6
6
  useQueryClient,
7
7
  } from '@tanstack/react-query'
8
8
  import type { InfiniteData, QueryClient } from '@tanstack/react-query'
9
+ import { useEffect, useState } from 'react'
9
10
 
10
11
  import { ApiError } from './client.ts'
11
12
  import type { Decoder, Page, QueryParameters } from './client.ts'
@@ -25,14 +26,44 @@ import { toError } from './errors.ts'
25
26
  * and leaves the cache library replaceable without touching a page.
26
27
  */
27
28
 
28
- /** A list, one page at a time. Nothing is truncated in silence: `hasMore` says so. */
29
- export interface RecordListResult<TRecord> {
29
+ /**
30
+ * The default page size when a caller does not name one via `query.limit`.
31
+ * Matches the `/v1` default from `api.md`.
32
+ */
33
+ export const DEFAULT_PAGE_SIZE = 50
34
+
35
+ /**
36
+ * The pagination controls a list surface renders. Split out from
37
+ * `RecordListResult` so the `Paginator` component can accept just this subset
38
+ * and stay generic in the record type.
39
+ */
40
+ export interface Paged {
41
+ /** Zero-based index of the page currently on screen. */
42
+ readonly pageIndex: number
43
+ /** Number of records the API returns per page, from `?limit=`. */
44
+ readonly pageSize: number
45
+ readonly hasPrev: boolean
46
+ readonly hasNext: boolean
47
+ /** True while fetching a not-yet-cached page. Prev on a cached page is instant. */
48
+ readonly isChangingPage: boolean
49
+ readonly prevPage: () => void
50
+ readonly nextPage: () => void
51
+ /**
52
+ * Changes the API `?limit=` and returns the reader to page 1. The API caps
53
+ * `?limit=` at 200 (`api.md`); a larger value is coerced by the server, not
54
+ * refused by this hook.
55
+ */
56
+ readonly setPageSize: (size: number) => void
57
+ }
58
+
59
+ /**
60
+ * A list, one page at a time. Records are the current page only, not the
61
+ * accumulation across pages a `Load more` reader would give.
62
+ */
63
+ export interface RecordListResult<TRecord> extends Paged {
30
64
  readonly records: readonly TRecord[]
31
65
  readonly isLoading: boolean
32
66
  readonly error: Error | null
33
- readonly hasMore: boolean
34
- readonly isLoadingMore: boolean
35
- readonly loadMore: () => void
36
67
  }
37
68
 
38
69
  export interface RecordResult<TRecord> {
@@ -184,6 +215,114 @@ function removeRecordEverywhere<TRecord extends { readonly id: string }>(
184
215
  )
185
216
  }
186
217
 
218
+ export interface PagedListInput<TRecord> {
219
+ /**
220
+ * The React Query cache key for this list, without `?limit=`. `usePagedList`
221
+ * appends the current page size so the cache splits by size — swapping page
222
+ * sizes has to fetch, or the cursors from one size would page a list saved
223
+ * under another.
224
+ */
225
+ readonly queryKey: readonly unknown[]
226
+ readonly path: string
227
+ readonly decode: Decoder<TRecord>
228
+ /** Query parameters other than `limit` and `cursor`. `usePagedList` sends both itself. */
229
+ readonly query: QueryParameters
230
+ readonly enabled?: boolean
231
+ }
232
+
233
+ /**
234
+ * The paged reader every list hook uses: `createResourceHooks`'s `useList`,
235
+ * and the three custom collections whose paths carry a parent id
236
+ * (`useFormSubmissions`, `useListMembers`, `useWebhookDeliveries`).
237
+ *
238
+ * The API is cursor-only (`api.md`), so pages are fetched forward. Already
239
+ * fetched pages stay cached in `useInfiniteQuery`, and `pageIndex` selects
240
+ * which one is on screen — so going back to a visited page is instant and
241
+ * going forward past the fetched set kicks off exactly one new request.
242
+ */
243
+ export function usePagedList<TRecord>(input: PagedListInput<TRecord>): RecordListResult<TRecord> {
244
+ const client = useApiClient()
245
+ const enabled = input.enabled ?? true
246
+ const requestedLimit = input.query.limit
247
+ const initialPageSize =
248
+ typeof requestedLimit === 'number' && Number.isFinite(requestedLimit) && requestedLimit > 0
249
+ ? requestedLimit
250
+ : DEFAULT_PAGE_SIZE
251
+ const [pageSize, setPageSize] = useState<number>(initialPageSize)
252
+ const [pageIndex, setPageIndex] = useState<number>(0)
253
+
254
+ const queryKey = [...input.queryKey, { limit: pageSize }] as const
255
+ const queryKeySignature = JSON.stringify(queryKey)
256
+
257
+ // A filter or sort change lands as a fresh `useInfiniteQuery`, so the page
258
+ // number the user was on no longer makes sense. Effect over signature keeps
259
+ // this cheap: same key, no re-render.
260
+ useEffect(() => {
261
+ setPageIndex(0)
262
+ }, [queryKeySignature])
263
+
264
+ const result = useInfiniteQuery({
265
+ queryKey,
266
+ queryFn: ({ pageParam }) =>
267
+ client.list(input.path, input.decode, {
268
+ ...input.query,
269
+ limit: pageSize,
270
+ ...(pageParam === null ? {} : { cursor: pageParam }),
271
+ }),
272
+ initialPageParam: null as string | null,
273
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
274
+ // Without this a keystroke in the filter box blanks the table while the
275
+ // next query runs, which reads as "no results" for as long as it takes.
276
+ placeholderData: keepPreviousData,
277
+ enabled,
278
+ })
279
+
280
+ const pages = result.data?.pages ?? []
281
+ // A shrinking cache — a delete followed by a refetch — can leave the index
282
+ // past the last page. Clamp so a stale index never renders a blank table.
283
+ const safeIndex = pages.length === 0 ? 0 : Math.min(pageIndex, pages.length - 1)
284
+ const currentPage = pages[safeIndex]
285
+ const hasCachedNext = safeIndex + 1 < pages.length
286
+ const hasNext = hasCachedNext || result.hasNextPage
287
+ const hasPrev = safeIndex > 0
288
+
289
+ return {
290
+ records: currentPage?.items ?? [],
291
+ // A disabled query stays pending forever, which is not the same as loading.
292
+ isLoading: result.isPending && enabled,
293
+ error: toError(result.error),
294
+ pageIndex: safeIndex,
295
+ pageSize,
296
+ hasPrev,
297
+ hasNext,
298
+ isChangingPage: result.isFetchingNextPage,
299
+ prevPage: () => {
300
+ setPageIndex((current) => Math.max(0, current - 1))
301
+ },
302
+ nextPage: () => {
303
+ if (hasCachedNext) {
304
+ setPageIndex((current) => current + 1)
305
+ return
306
+ }
307
+
308
+ if (!result.hasNextPage) {
309
+ return
310
+ }
311
+
312
+ void result.fetchNextPage().then((r) => {
313
+ if (r.error === null) {
314
+ setPageIndex((current) => current + 1)
315
+ }
316
+ })
317
+ },
318
+ // Query key includes `limit`, so the effect above resets `pageIndex` to 0
319
+ // once React sees the new key.
320
+ setPageSize: (size) => {
321
+ setPageSize(size)
322
+ },
323
+ }
324
+ }
325
+
187
326
  /**
188
327
  * The read half: `useList` and `useRecord`, and nothing that writes.
189
328
  *
@@ -197,34 +336,13 @@ export function createReadOnlyResourceHooks<TRecord>(
197
336
  const keys = keysFor(definition.name)
198
337
 
199
338
  function useList(query: QueryParameters = {}, options: ListOptions = {}): RecordListResult<TRecord> {
200
- const client = useApiClient()
201
- const enabled = options.enabled ?? true
202
- const result = useInfiniteQuery({
339
+ return usePagedList<TRecord>({
203
340
  queryKey: keys.list(query),
204
- queryFn: ({ pageParam }) =>
205
- client.list(definition.path, definition.decode, {
206
- ...query,
207
- ...(pageParam === null ? {} : { cursor: pageParam }),
208
- }),
209
- initialPageParam: null as string | null,
210
- getNextPageParam: (lastPage) => lastPage.nextCursor,
211
- // Without this a keystroke in the filter box blanks the table while the
212
- // next query runs, which reads as "no results" for as long as it takes.
213
- placeholderData: keepPreviousData,
214
- enabled,
341
+ path: definition.path,
342
+ decode: definition.decode,
343
+ query,
344
+ enabled: options.enabled ?? true,
215
345
  })
216
-
217
- return {
218
- records: result.data?.pages.flatMap((page) => page.items) ?? [],
219
- // A disabled query stays pending forever, which is not the same as loading.
220
- isLoading: result.isPending && enabled,
221
- error: toError(result.error),
222
- hasMore: result.hasNextPage,
223
- isLoadingMore: result.isFetchingNextPage,
224
- loadMore: () => {
225
- void result.fetchNextPage()
226
- },
227
- }
228
346
  }
229
347
 
230
348
  function useRecord(id: string | undefined): RecordResult<TRecord> {
@@ -249,7 +367,12 @@ export function createReadOnlyResourceHooks<TRecord>(
249
367
  export function createResourceHooks<
250
368
  TRecord extends { readonly id: string },
251
369
  TCreateInput,
252
- TUpdateInput extends Partial<TRecord>,
370
+ // The constraint is deliberately looser than `Partial<TRecord>`. A merge-patch
371
+ // field (a record whose value type includes `null` to clear a key) does not
372
+ // fit `Partial<TRecord>` when the record's own value type is non-null, and
373
+ // that shape reaches the record for real (custom-fields, and any later
374
+ // module that carries one). `mergeDefined` needs no more than an object here.
375
+ TUpdateInput extends object,
253
376
  >(
254
377
  definition: ResourceDefinition<TRecord, TCreateInput, TUpdateInput>,
255
378
  ): ResourceHooks<TRecord, TCreateInput, TUpdateInput> {
@@ -25,7 +25,10 @@ const companies = createResourceHooks<Company, CreateCompanyInput, CompanyInput>
25
25
  updateBody: companyBody,
26
26
  // Every write here emits an activity server-side, in the same transaction, so
27
27
  // a timeline rendered on this record is stale the moment the write lands.
28
- alsoInvalidates: ['activities'],
28
+ // Creating or renaming a domain may also auto-link Positions to workspace
29
+ // people whose email is at it, which changes position lists and the
30
+ // `?company_id=` people list that names the far side of each new row.
31
+ alsoInvalidates: ['activities', 'positions', 'people'],
29
32
  })
30
33
 
31
34
  /** The documented filters on `GET /v1/companies`. */
@@ -34,6 +37,8 @@ export interface CompanyFilters {
34
37
  readonly term?: string | undefined
35
38
  /** Companies where any of these people holds a position. Repeats on the wire. */
36
39
  readonly personIds?: readonly string[] | undefined
40
+ /** true = only the workspace's own companies; false = only the rest. */
41
+ readonly isOwn?: boolean | undefined
37
42
  readonly limit?: number | undefined
38
43
  /** `field` ascending, `-field` descending. Only `name`, `created_at`, `updated_at` are sortable. */
39
44
  readonly sort?: string | undefined
@@ -43,6 +48,7 @@ function companyQuery(filters: CompanyFilters): QueryParameters {
43
48
  return {
44
49
  q: filters.term,
45
50
  person_id: filters.personIds,
51
+ is_own: filters.isOwn === undefined ? undefined : String(filters.isOwn),
46
52
  limit: filters.limit,
47
53
  sort: filters.sort,
48
54
  }
@@ -0,0 +1,83 @@
1
+ import {
2
+ consentPurposeBody,
3
+ consentPurposeSchema,
4
+ createConsentPurposeBody,
5
+ } from '@kelpie/schemas'
6
+ import type {
7
+ ConsentPurpose,
8
+ ConsentPurposeInput,
9
+ CreateConsentPurposeInput,
10
+ } from '@kelpie/schemas'
11
+
12
+ import type { QueryParameters } from '../client.ts'
13
+ import { createResourceHooks } from '../resource.ts'
14
+ import type {
15
+ ListOptions,
16
+ MutationResult,
17
+ RecordListResult,
18
+ RecordResult,
19
+ UpdateArguments,
20
+ } from '../resource.ts'
21
+
22
+ /**
23
+ * `/v1/consent_purposes`. Workspace-defined consent purposes.
24
+ *
25
+ * Every capture site — form consent fields, lists, imports, the manual
26
+ * override on a Person — names one of these. Reads are open to any member;
27
+ * writes need the admin role, enforced server-side.
28
+ */
29
+
30
+ const consentPurposes = createResourceHooks<
31
+ ConsentPurpose,
32
+ CreateConsentPurposeInput,
33
+ ConsentPurposeInput
34
+ >({
35
+ name: 'consent_purposes',
36
+ path: '/consent_purposes',
37
+ decode: consentPurposeSchema.parse,
38
+ createBody: createConsentPurposeBody,
39
+ updateBody: consentPurposeBody,
40
+ })
41
+
42
+ export interface ConsentPurposeFilters {
43
+ readonly term?: string | undefined
44
+ readonly limit?: number | undefined
45
+ readonly sort?: string | undefined
46
+ }
47
+
48
+ function consentPurposeQuery(filters: ConsentPurposeFilters): QueryParameters {
49
+ return {
50
+ q: filters.term,
51
+ limit: filters.limit,
52
+ sort: filters.sort,
53
+ }
54
+ }
55
+
56
+ export function useConsentPurposes(
57
+ filters: ConsentPurposeFilters = {},
58
+ options: ListOptions = {},
59
+ ): RecordListResult<ConsentPurpose> {
60
+ return consentPurposes.useList(consentPurposeQuery(filters), options)
61
+ }
62
+
63
+ export function useConsentPurpose(id: string | undefined): RecordResult<ConsentPurpose> {
64
+ return consentPurposes.useRecord(id)
65
+ }
66
+
67
+ export function useCreateConsentPurpose(): MutationResult<
68
+ CreateConsentPurposeInput,
69
+ ConsentPurpose
70
+ > {
71
+ return consentPurposes.useCreate()
72
+ }
73
+
74
+ export function useUpdateConsentPurpose(): MutationResult<
75
+ UpdateArguments<ConsentPurposeInput>,
76
+ ConsentPurpose
77
+ > {
78
+ return consentPurposes.useUpdate()
79
+ }
80
+
81
+ export function useDeleteConsentPurpose(): MutationResult<string, void> {
82
+ return consentPurposes.useRemove()
83
+ }