@aglyn/plugins-crm 1.0.0-beta.220 → 1.0.0-beta.222

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 (514) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-record-picker.d.ts +15 -0
  34. package/src/lib/components/crm-record-picker.js +16 -10
  35. package/src/lib/components/crm-record-picker.js.map +1 -1
  36. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  37. package/src/lib/components/crm-transfer-buttons.js +167 -0
  38. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  39. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  40. package/src/lib/components/deal-contact-roles-card.js +368 -0
  41. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  42. package/src/lib/components/deal-detail-page.d.ts +3 -2
  43. package/src/lib/components/deal-detail-page.js +25 -6
  44. package/src/lib/components/deal-detail-page.js.map +1 -1
  45. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  46. package/src/lib/components/deal-edit-drawer.js +219 -10
  47. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  48. package/src/lib/components/deal-properties-card.d.ts +7 -0
  49. package/src/lib/components/deal-properties-card.js +34 -3
  50. package/src/lib/components/deal-properties-card.js.map +1 -1
  51. package/src/lib/components/deal-stage-card.d.ts +4 -0
  52. package/src/lib/components/deal-stage-card.js +10 -2
  53. package/src/lib/components/deal-stage-card.js.map +1 -1
  54. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  55. package/src/lib/components/deals-bulk-bar.js +7 -20
  56. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  57. package/src/lib/components/deals-section.d.ts +3 -3
  58. package/src/lib/components/deals-section.js +123 -63
  59. package/src/lib/components/deals-section.js.map +1 -1
  60. package/src/lib/components/fields-section.js +31 -17
  61. package/src/lib/components/fields-section.js.map +1 -1
  62. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  63. package/src/lib/components/lead-convert-dialog.js +23 -1
  64. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  65. package/src/lib/components/lead-detail-page.js +8 -2
  66. package/src/lib/components/lead-detail-page.js.map +1 -1
  67. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  68. package/src/lib/components/lead-profile-fields.js +386 -0
  69. package/src/lib/components/lead-profile-fields.js.map +1 -0
  70. package/src/lib/components/lead-properties-card.d.ts +2 -1
  71. package/src/lib/components/lead-properties-card.js +85 -176
  72. package/src/lib/components/lead-properties-card.js.map +1 -1
  73. package/src/lib/components/lead-source-select.d.ts +4 -23
  74. package/src/lib/components/lead-source-select.js +9 -73
  75. package/src/lib/components/lead-source-select.js.map +1 -1
  76. package/src/lib/components/lead-status-chip.d.ts +9 -3
  77. package/src/lib/components/lead-status-chip.js +8 -4
  78. package/src/lib/components/lead-status-chip.js.map +1 -1
  79. package/src/lib/components/lead-status-options.d.ts +20 -0
  80. package/src/lib/components/lead-status-options.js +51 -0
  81. package/src/lib/components/lead-status-options.js.map +1 -0
  82. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  83. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  84. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  85. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  86. package/src/lib/components/leads-bulk-bar.js +29 -29
  87. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  88. package/src/lib/components/leads-section.js +120 -68
  89. package/src/lib/components/leads-section.js.map +1 -1
  90. package/src/lib/components/linked-deals-card.d.ts +4 -0
  91. package/src/lib/components/linked-deals-card.js +47 -3
  92. package/src/lib/components/linked-deals-card.js.map +1 -1
  93. package/src/lib/components/log-activity-dialog.js +43 -3
  94. package/src/lib/components/log-activity-dialog.js.map +1 -1
  95. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  96. package/src/lib/components/new-contact-drawer.js +108 -6
  97. package/src/lib/components/new-contact-drawer.js.map +1 -1
  98. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  99. package/src/lib/components/new-lead-drawer.js +88 -121
  100. package/src/lib/components/new-lead-drawer.js.map +1 -1
  101. package/src/lib/components/picklist-select.d.ts +36 -0
  102. package/src/lib/components/picklist-select.js +114 -0
  103. package/src/lib/components/picklist-select.js.map +1 -0
  104. package/src/lib/components/picklist-values-card.d.ts +34 -0
  105. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  106. package/src/lib/components/picklist-values-card.js.map +1 -0
  107. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  108. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  109. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  110. package/src/lib/components/pipelines-dialog.js +15 -6
  111. package/src/lib/components/pipelines-dialog.js.map +1 -1
  112. package/src/lib/components/recent-activity-feed.js +20 -5
  113. package/src/lib/components/recent-activity-feed.js.map +1 -1
  114. package/src/lib/components/recipes-card.js +4 -2
  115. package/src/lib/components/recipes-card.js.map +1 -1
  116. package/src/lib/components/record-tasks-card.js +15 -8
  117. package/src/lib/components/record-tasks-card.js.map +1 -1
  118. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  119. package/src/lib/components/reports/forecast-card.js +101 -3
  120. package/src/lib/components/reports/forecast-card.js.map +1 -1
  121. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  122. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  123. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  124. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  125. package/src/lib/components/reports/lead-source-card.js +318 -0
  126. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  127. package/src/lib/components/reports/report-export.js +1 -1
  128. package/src/lib/components/reports/report-export.js.map +1 -1
  129. package/src/lib/components/reports-section.js +8 -0
  130. package/src/lib/components/reports-section.js.map +1 -1
  131. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  132. package/src/lib/components/sharing-rule-drawer.js +108 -19
  133. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  134. package/src/lib/components/sharing-rules-card.js +11 -3
  135. package/src/lib/components/sharing-rules-card.js.map +1 -1
  136. package/src/lib/components/task-cells.d.ts +9 -1
  137. package/src/lib/components/task-cells.js +9 -4
  138. package/src/lib/components/task-cells.js.map +1 -1
  139. package/src/lib/components/task-edit-drawer.js +111 -43
  140. package/src/lib/components/task-edit-drawer.js.map +1 -1
  141. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  142. package/src/lib/components/tasks-bulk-bar.js +7 -20
  143. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  144. package/src/lib/components/tasks-calendar.d.ts +3 -0
  145. package/src/lib/components/tasks-calendar.js +8 -1
  146. package/src/lib/components/tasks-calendar.js.map +1 -1
  147. package/src/lib/components/tasks-section.d.ts +3 -3
  148. package/src/lib/components/tasks-section.js +58 -43
  149. package/src/lib/components/tasks-section.js.map +1 -1
  150. package/src/lib/constants/api-routes.d.ts +2 -9
  151. package/src/lib/constants/api-routes.js +1 -7
  152. package/src/lib/constants/api-routes.js.map +1 -1
  153. package/src/lib/constants/bundle-common.d.ts +6 -0
  154. package/src/lib/constants/bundle-common.js +11 -0
  155. package/src/lib/constants/bundle-common.js.map +1 -1
  156. package/src/lib/constants/company-filters.d.ts +14 -0
  157. package/src/lib/constants/company-filters.js +51 -1
  158. package/src/lib/constants/company-filters.js.map +1 -1
  159. package/src/lib/constants/contact-filters.d.ts +2 -0
  160. package/src/lib/constants/contact-filters.js +18 -1
  161. package/src/lib/constants/contact-filters.js.map +1 -1
  162. package/src/lib/constants/deal-filters.d.ts +22 -1
  163. package/src/lib/constants/deal-filters.js +67 -4
  164. package/src/lib/constants/deal-filters.js.map +1 -1
  165. package/src/lib/declarations.console-server.d.ts +3 -0
  166. package/src/lib/declarations.console-server.js +35 -0
  167. package/src/lib/declarations.console-server.js.map +1 -1
  168. package/src/lib/declarations.d.ts +26 -0
  169. package/src/lib/declarations.js +35 -0
  170. package/src/lib/declarations.js.map +1 -0
  171. package/src/lib/declarations.server.d.ts +11 -0
  172. package/src/lib/declarations.server.js +92 -1
  173. package/src/lib/declarations.server.js.map +1 -1
  174. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  175. package/src/lib/hooks/use-company-picklists.js +55 -0
  176. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  177. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  178. package/src/lib/hooks/use-crm-picklist.js +53 -0
  179. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  180. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  181. package/src/lib/hooks/use-crm-record-names.js +45 -19
  182. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  183. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  184. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  185. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  186. package/src/lib/hooks/use-deals.d.ts +14 -0
  187. package/src/lib/hooks/use-deals.js +29 -0
  188. package/src/lib/hooks/use-deals.js.map +1 -1
  189. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  190. package/src/lib/hooks/use-lead-picklists.js +46 -0
  191. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  192. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  193. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  194. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  195. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  196. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  197. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  198. package/src/lib/model/companies.d.ts +32 -3
  199. package/src/lib/model/companies.js +133 -16
  200. package/src/lib/model/companies.js.map +1 -1
  201. package/src/lib/model/contact-merge.d.ts +27 -3
  202. package/src/lib/model/contact-merge.js +81 -7
  203. package/src/lib/model/contact-merge.js.map +1 -1
  204. package/src/lib/model/contact-record.d.ts +17 -0
  205. package/src/lib/model/contact-record.js +15 -1
  206. package/src/lib/model/contact-record.js.map +1 -1
  207. package/src/lib/model/contact-update.d.ts +31 -2
  208. package/src/lib/model/contact-update.js +14 -0
  209. package/src/lib/model/contact-update.js.map +1 -1
  210. package/src/lib/model/crm-list-query.d.ts +5 -0
  211. package/src/lib/model/crm-list-query.js +8 -0
  212. package/src/lib/model/crm-list-query.js.map +1 -1
  213. package/src/lib/model/crm-recipes.d.ts +40 -0
  214. package/src/lib/model/crm-recipes.js +244 -0
  215. package/src/lib/model/crm-recipes.js.map +1 -0
  216. package/src/lib/model/crm-record-counts.d.ts +36 -0
  217. package/src/lib/model/crm-record-counts.js +54 -0
  218. package/src/lib/model/crm-record-counts.js.map +1 -0
  219. package/src/lib/model/crm-record-lists.d.ts +23 -0
  220. package/src/lib/model/crm-record-lists.js +161 -0
  221. package/src/lib/model/crm-record-lists.js.map +1 -0
  222. package/src/lib/model/crm-reports.d.ts +73 -3
  223. package/src/lib/model/crm-reports.js +120 -1
  224. package/src/lib/model/crm-reports.js.map +1 -1
  225. package/src/lib/model/crm-sharing.d.ts +21 -3
  226. package/src/lib/model/crm-sharing.js +27 -6
  227. package/src/lib/model/crm-sharing.js.map +1 -1
  228. package/src/lib/model/deal-board-model.d.ts +8 -2
  229. package/src/lib/model/deal-board-model.js +15 -2
  230. package/src/lib/model/deal-board-model.js.map +1 -1
  231. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  232. package/src/lib/model/deal-contact-roles.js +73 -0
  233. package/src/lib/model/deal-contact-roles.js.map +1 -0
  234. package/src/lib/model/deal-form-model.d.ts +56 -0
  235. package/src/lib/model/deal-form-model.js +79 -7
  236. package/src/lib/model/deal-form-model.js.map +1 -1
  237. package/src/lib/model/download-text-file.d.ts +23 -0
  238. package/src/lib/model/download-text-file.js +34 -0
  239. package/src/lib/model/download-text-file.js.map +1 -0
  240. package/src/lib/model/lead-filters.d.ts +36 -2
  241. package/src/lib/model/lead-filters.js +123 -2
  242. package/src/lib/model/lead-filters.js.map +1 -1
  243. package/src/lib/model/lead-source-direction.d.ts +38 -0
  244. package/src/lib/model/lead-source-direction.js +52 -0
  245. package/src/lib/model/lead-source-direction.js.map +1 -0
  246. package/src/lib/model/picklist-values.d.ts +119 -0
  247. package/src/lib/model/picklist-values.js +256 -0
  248. package/src/lib/model/picklist-values.js.map +1 -0
  249. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  250. package/src/lib/model/record-facts-disclosed.js +281 -0
  251. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  252. package/src/lib/model/record-facts.d.ts +215 -34
  253. package/src/lib/model/record-facts.js +307 -128
  254. package/src/lib/model/record-facts.js.map +1 -1
  255. package/src/lib/model/task-picklists.d.ts +52 -0
  256. package/src/lib/model/task-picklists.js +83 -0
  257. package/src/lib/model/task-picklists.js.map +1 -0
  258. package/src/lib/model/task-routes.d.ts +13 -0
  259. package/src/lib/model/task-routes.js +23 -4
  260. package/src/lib/model/task-routes.js.map +1 -1
  261. package/src/lib/plan-entitlements.js +6 -4
  262. package/src/lib/plan-entitlements.js.map +1 -1
  263. package/src/lib/plugin.js +17 -0
  264. package/src/lib/plugin.js.map +1 -1
  265. package/src/lib/server/api-v1/contacts.js +220 -14
  266. package/src/lib/server/api-v1/contacts.js.map +1 -1
  267. package/src/lib/server/api-v1/crm-activities.js +14 -1
  268. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  269. package/src/lib/server/api-v1/crm-companies.js +123 -14
  270. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  271. package/src/lib/server/api-v1/crm-deals.js +291 -26
  272. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  273. package/src/lib/server/api-v1/crm-leads.js +144 -38
  274. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  275. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  276. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  277. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  278. package/src/lib/server/api-v1/crm-tasks.js +75 -33
  279. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  280. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  281. package/src/lib/server/api-v1/openapi.js +171 -16
  282. package/src/lib/server/api-v1/openapi.js.map +1 -1
  283. package/src/lib/server/assign-contact-owner.d.ts +162 -0
  284. package/src/lib/server/assign-contact-owner.js +340 -0
  285. package/src/lib/server/assign-contact-owner.js.map +1 -0
  286. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  287. package/src/lib/server/associate-company-by-domain.js +153 -0
  288. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  289. package/src/lib/server/automation-steps.d.ts +139 -0
  290. package/src/lib/server/automation-steps.js +472 -0
  291. package/src/lib/server/automation-steps.js.map +1 -0
  292. package/src/lib/server/capture-contact.js +69 -22
  293. package/src/lib/server/capture-contact.js.map +1 -1
  294. package/src/lib/server/capture-host-contact.d.ts +104 -0
  295. package/src/lib/server/capture-host-contact.js +151 -0
  296. package/src/lib/server/capture-host-contact.js.map +1 -0
  297. package/src/lib/server/company-children.d.ts +25 -0
  298. package/src/lib/server/company-children.js +42 -0
  299. package/src/lib/server/company-children.js.map +1 -0
  300. package/src/lib/server/company-delete.d.ts +18 -0
  301. package/src/lib/server/company-delete.js +44 -21
  302. package/src/lib/server/company-delete.js.map +1 -1
  303. package/src/lib/server/contact-email-history.js +21 -19
  304. package/src/lib/server/contact-email-history.js.map +1 -1
  305. package/src/lib/server/contact-remove.js +27 -2
  306. package/src/lib/server/contact-remove.js.map +1 -1
  307. package/src/lib/server/contact-reports-to.d.ts +61 -0
  308. package/src/lib/server/contact-reports-to.js +114 -0
  309. package/src/lib/server/contact-reports-to.js.map +1 -0
  310. package/src/lib/server/contact-update.d.ts +42 -1
  311. package/src/lib/server/contact-update.js +204 -23
  312. package/src/lib/server/contact-update.js.map +1 -1
  313. package/src/lib/server/convert-host-lead.d.ts +46 -1
  314. package/src/lib/server/convert-host-lead.js +173 -15
  315. package/src/lib/server/convert-host-lead.js.map +1 -1
  316. package/src/lib/server/convert-open-lead.js +12 -5
  317. package/src/lib/server/convert-open-lead.js.map +1 -1
  318. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  319. package/src/lib/server/crm-record-indexes.js +78 -0
  320. package/src/lib/server/crm-record-indexes.js.map +1 -0
  321. package/src/lib/server/crm-sharing.d.ts +9 -1
  322. package/src/lib/server/crm-sharing.js +23 -3
  323. package/src/lib/server/crm-sharing.js.map +1 -1
  324. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  325. package/src/lib/server/deal-contact-roles.js +89 -0
  326. package/src/lib/server/deal-contact-roles.js.map +1 -0
  327. package/src/lib/server/lead-convert.d.ts +5 -0
  328. package/src/lib/server/lead-convert.js +19 -3
  329. package/src/lib/server/lead-convert.js.map +1 -1
  330. package/src/lib/server/lead-create.d.ts +17 -2
  331. package/src/lib/server/lead-create.js +46 -14
  332. package/src/lib/server/lead-create.js.map +1 -1
  333. package/src/lib/server/lead-nurturing.d.ts +6 -0
  334. package/src/lib/server/lead-nurturing.js +57 -20
  335. package/src/lib/server/lead-nurturing.js.map +1 -1
  336. package/src/lib/server/lead-picklists.d.ts +35 -0
  337. package/src/lib/server/lead-picklists.js +52 -0
  338. package/src/lib/server/lead-picklists.js.map +1 -0
  339. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  340. package/src/lib/server/lead-source-picklist.js +6 -33
  341. package/src/lib/server/lead-source-picklist.js.map +1 -1
  342. package/src/lib/server/merge-contacts.js +22 -4
  343. package/src/lib/server/merge-contacts.js.map +1 -1
  344. package/src/lib/server/person-eraser.d.ts +53 -0
  345. package/src/lib/server/person-eraser.js +149 -0
  346. package/src/lib/server/person-eraser.js.map +1 -0
  347. package/src/lib/server/person-records.d.ts +69 -0
  348. package/src/lib/server/person-records.js +317 -0
  349. package/src/lib/server/person-records.js.map +1 -0
  350. package/src/lib/server/person-refund.d.ts +97 -0
  351. package/src/lib/server/person-refund.js +221 -0
  352. package/src/lib/server/person-refund.js.map +1 -0
  353. package/src/lib/server/picklist-values.d.ts +21 -0
  354. package/src/lib/server/picklist-values.js +308 -0
  355. package/src/lib/server/picklist-values.js.map +1 -0
  356. package/src/lib/server/read-picklist.d.ts +44 -0
  357. package/src/lib/server/read-picklist.js +65 -0
  358. package/src/lib/server/read-picklist.js.map +1 -0
  359. package/src/lib/server/recipe-routes.js +15 -7
  360. package/src/lib/server/recipe-routes.js.map +1 -1
  361. package/src/lib/server/record-email-state.js +7 -1
  362. package/src/lib/server/record-email-state.js.map +1 -1
  363. package/src/lib/server/record-facts.d.ts +3 -0
  364. package/src/lib/server/record-facts.js +233 -31
  365. package/src/lib/server/record-facts.js.map +1 -1
  366. package/src/lib/server/record-origin.d.ts +27 -0
  367. package/src/lib/server/record-origin.js +104 -0
  368. package/src/lib/server/record-origin.js.map +1 -0
  369. package/src/lib/server/record-timeline.js +15 -2
  370. package/src/lib/server/record-timeline.js.map +1 -1
  371. package/src/lib/server/suite-gate.js +4 -3
  372. package/src/lib/server/suite-gate.js.map +1 -1
  373. package/src/lib/server/task-routes.js +30 -16
  374. package/src/lib/server/task-routes.js.map +1 -1
  375. package/src/lib/server-deal-stage.d.ts +5 -1
  376. package/src/lib/server-deal-stage.js +10 -5
  377. package/src/lib/server-deal-stage.js.map +1 -1
  378. package/src/lib/server.d.ts +8 -3
  379. package/src/lib/server.js +47 -43
  380. package/src/lib/server.js.map +1 -1
  381. package/src/lib/testing/memory-firestore.d.ts +55 -0
  382. package/src/lib/testing/memory-firestore.js +335 -0
  383. package/src/lib/testing/memory-firestore.js.map +1 -0
  384. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  385. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  386. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  387. package/src/lib/transfer/activities.d.ts +30 -0
  388. package/src/lib/transfer/activities.js +132 -0
  389. package/src/lib/transfer/activities.js.map +1 -0
  390. package/src/lib/transfer/aliases.d.ts +22 -0
  391. package/src/lib/transfer/aliases.js +1342 -0
  392. package/src/lib/transfer/aliases.js.map +1 -0
  393. package/src/lib/transfer/common.d.ts +222 -0
  394. package/src/lib/transfer/common.js +832 -0
  395. package/src/lib/transfer/common.js.map +1 -0
  396. package/src/lib/transfer/companies.d.ts +43 -0
  397. package/src/lib/transfer/companies.js +549 -0
  398. package/src/lib/transfer/companies.js.map +1 -0
  399. package/src/lib/transfer/contacts.d.ts +31 -0
  400. package/src/lib/transfer/contacts.js +727 -0
  401. package/src/lib/transfer/contacts.js.map +1 -0
  402. package/src/lib/transfer/deals.d.ts +66 -0
  403. package/src/lib/transfer/deals.js +698 -0
  404. package/src/lib/transfer/deals.js.map +1 -0
  405. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  406. package/src/lib/transfer/email-templates-package.js +76 -0
  407. package/src/lib/transfer/email-templates-package.js.map +1 -0
  408. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  409. package/src/lib/transfer/email-templates-package.server.js +176 -0
  410. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  411. package/src/lib/transfer/fields.d.ts +102 -0
  412. package/src/lib/transfer/fields.js +1755 -0
  413. package/src/lib/transfer/fields.js.map +1 -0
  414. package/src/lib/transfer/leads.d.ts +30 -0
  415. package/src/lib/transfer/leads.js +582 -0
  416. package/src/lib/transfer/leads.js.map +1 -0
  417. package/src/lib/transfer/pipelines.d.ts +21 -0
  418. package/src/lib/transfer/pipelines.js +172 -0
  419. package/src/lib/transfer/pipelines.js.map +1 -0
  420. package/src/lib/transfer/register.d.ts +47 -0
  421. package/src/lib/transfer/register.js +277 -0
  422. package/src/lib/transfer/register.js.map +1 -0
  423. package/src/lib/transfer/tasks.d.ts +30 -0
  424. package/src/lib/transfer/tasks.js +418 -0
  425. package/src/lib/transfer/tasks.js.map +1 -0
  426. package/src/lib/transfer/ui.d.ts +20 -0
  427. package/src/lib/transfer/ui.js +42 -0
  428. package/src/lib/transfer/ui.js.map +1 -0
  429. package/src/lib/components/company-import-drawer.d.ts +0 -42
  430. package/src/lib/components/company-import-drawer.js +0 -99
  431. package/src/lib/components/company-import-drawer.js.map +0 -1
  432. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  433. package/src/lib/components/contact-import-drawer.js +0 -149
  434. package/src/lib/components/contact-import-drawer.js.map +0 -1
  435. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  436. package/src/lib/components/crm-export-all-button.js +0 -98
  437. package/src/lib/components/crm-export-all-button.js.map +0 -1
  438. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  439. package/src/lib/components/csv-import-drawer.js +0 -757
  440. package/src/lib/components/csv-import-drawer.js.map +0 -1
  441. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  442. package/src/lib/components/deal-import-drawer.js +0 -83
  443. package/src/lib/components/deal-import-drawer.js.map +0 -1
  444. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  445. package/src/lib/components/lead-import-drawer.js +0 -118
  446. package/src/lib/components/lead-import-drawer.js.map +0 -1
  447. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  448. package/src/lib/components/lead-source-values-card.js.map +0 -1
  449. package/src/lib/components/task-import-drawer.d.ts +0 -24
  450. package/src/lib/components/task-import-drawer.js +0 -82
  451. package/src/lib/components/task-import-drawer.js.map +0 -1
  452. package/src/lib/model/companies-csv.d.ts +0 -36
  453. package/src/lib/model/companies-csv.js +0 -38
  454. package/src/lib/model/companies-csv.js.map +0 -1
  455. package/src/lib/model/contacts-csv.d.ts +0 -54
  456. package/src/lib/model/contacts-csv.js +0 -67
  457. package/src/lib/model/contacts-csv.js.map +0 -1
  458. package/src/lib/model/crm-company-import.d.ts +0 -154
  459. package/src/lib/model/crm-company-import.js +0 -331
  460. package/src/lib/model/crm-company-import.js.map +0 -1
  461. package/src/lib/model/crm-csv.d.ts +0 -239
  462. package/src/lib/model/crm-csv.js +0 -467
  463. package/src/lib/model/crm-csv.js.map +0 -1
  464. package/src/lib/model/crm-deal-import.d.ts +0 -112
  465. package/src/lib/model/crm-deal-import.js +0 -263
  466. package/src/lib/model/crm-deal-import.js.map +0 -1
  467. package/src/lib/model/crm-import.d.ts +0 -250
  468. package/src/lib/model/crm-import.js +0 -467
  469. package/src/lib/model/crm-import.js.map +0 -1
  470. package/src/lib/model/crm-lead-import.d.ts +0 -138
  471. package/src/lib/model/crm-lead-import.js +0 -446
  472. package/src/lib/model/crm-lead-import.js.map +0 -1
  473. package/src/lib/model/crm-task-import.d.ts +0 -94
  474. package/src/lib/model/crm-task-import.js +0 -275
  475. package/src/lib/model/crm-task-import.js.map +0 -1
  476. package/src/lib/model/deals-csv.d.ts +0 -32
  477. package/src/lib/model/deals-csv.js +0 -36
  478. package/src/lib/model/deals-csv.js.map +0 -1
  479. package/src/lib/model/import-column-shapes.d.ts +0 -36
  480. package/src/lib/model/import-column-shapes.js +0 -76
  481. package/src/lib/model/import-column-shapes.js.map +0 -1
  482. package/src/lib/model/lead-source-values.d.ts +0 -82
  483. package/src/lib/model/lead-source-values.js +0 -149
  484. package/src/lib/model/lead-source-values.js.map +0 -1
  485. package/src/lib/model/leads-csv.d.ts +0 -40
  486. package/src/lib/model/leads-csv.js +0 -40
  487. package/src/lib/model/leads-csv.js.map +0 -1
  488. package/src/lib/model/tasks-csv.d.ts +0 -28
  489. package/src/lib/model/tasks-csv.js +0 -28
  490. package/src/lib/model/tasks-csv.js.map +0 -1
  491. package/src/lib/server/companies-import.d.ts +0 -57
  492. package/src/lib/server/companies-import.js +0 -242
  493. package/src/lib/server/companies-import.js.map +0 -1
  494. package/src/lib/server/contacts-import.d.ts +0 -109
  495. package/src/lib/server/contacts-import.js +0 -393
  496. package/src/lib/server/contacts-import.js.map +0 -1
  497. package/src/lib/server/deals-import.d.ts +0 -76
  498. package/src/lib/server/deals-import.js +0 -248
  499. package/src/lib/server/deals-import.js.map +0 -1
  500. package/src/lib/server/export-route.d.ts +0 -60
  501. package/src/lib/server/export-route.js +0 -447
  502. package/src/lib/server/export-route.js.map +0 -1
  503. package/src/lib/server/import-context.d.ts +0 -87
  504. package/src/lib/server/import-context.js +0 -182
  505. package/src/lib/server/import-context.js.map +0 -1
  506. package/src/lib/server/lead-source-values.d.ts +0 -50
  507. package/src/lib/server/lead-source-values.js +0 -191
  508. package/src/lib/server/lead-source-values.js.map +0 -1
  509. package/src/lib/server/leads-import.d.ts +0 -84
  510. package/src/lib/server/leads-import.js +0 -367
  511. package/src/lib/server/leads-import.js.map +0 -1
  512. package/src/lib/server/tasks-import.d.ts +0 -54
  513. package/src/lib/server/tasks-import.js +0 -160
  514. package/src/lib/server/tasks-import.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-picklist.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n CRM_COLLECTIONS,\n type CrmPicklist,\n type CrmPicklistDefinition,\n type CrmPicklistId,\n crmPicklistDefinition,\n effectiveCrmPicklist,\n normalizeCrmPicklist,\n} from '@aglyn/aglyn'\nimport { useFirestore, useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport { doc } from 'firebase/firestore'\nimport { useMemo } from 'react'\n\nexport interface CrmPicklistResult {\n /** The field the list belongs to — its standard values, groups and targets. */\n definition: CrmPicklistDefinition\n /** The list every picker offers — the org's own values with every standard value. */\n picklist: CrmPicklist\n /** The org has written its own list; false while it reads the standard values alone. */\n stored: boolean\n /** The server has answered, so the list is the org's and not a placeholder. */\n ready: boolean\n /** The document has not been confirmed by the server — `writeGuardedBySeed`'s input. */\n fromCache: boolean\n}\n\n/**\n * An org's values for one of the CRM's standard picklists (AGL-3510), for\n * every surface that offers or manages them: a record's select, a create\n * drawer, a list's filter and the Fields page.\n *\n * One document listen, shared by the Firestore SDK across every mount that\n * asks for the same org and picklist, so a page with the list and a drawer\n * open pays for it once. `orgId` null issues no read and answers the\n * standard values, unready.\n */\nexport function useCrmPicklist(\n id: CrmPicklistId,\n orgId: string | null | undefined,\n): CrmPicklistResult {\n const firestore = useFirestore()\n const { data, status, fromCache } = useFirestoreDoc<Record<string, unknown>>(\n () => (orgId ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.picklists, id) : null),\n [firestore, orgId, id],\n )\n return useMemo(\n () => ({\n definition: crmPicklistDefinition(id) as CrmPicklistDefinition,\n picklist: effectiveCrmPicklist(id, data),\n stored: normalizeCrmPicklist(data) !== null,\n ready: Boolean(orgId) && status !== 'loading',\n fromCache,\n }),\n [id, data, orgId, status, fromCache],\n )\n}\n\nexport default useCrmPicklist\n"],"names":["CRM_COLLECTIONS","crmPicklistDefinition","effectiveCrmPicklist","normalizeCrmPicklist","useFirestore","useFirestoreDoc","doc","useMemo","useCrmPicklist","id","orgId","firestore","data","status","fromCache","picklists","definition","picklist","stored","ready","Boolean"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SACEA,eAAe,EAIfC,qBAAqB,EACrBC,oBAAoB,EACpBC,oBAAoB,QACf,eAAc;AACrB,SAASC,YAAY,EAAEC,eAAe,QAAQ,iCAAgC;AAC9E,SAASC,GAAG,QAAQ,qBAAoB;AACxC,SAASC,OAAO,QAAQ,QAAO;AAe/B;;;;;;;;;CASC,GACD,OAAO,SAASC,eACdC,EAAiB,EACjBC,KAAgC;IAEhC,MAAMC,YAAYP;IAClB,MAAM,EAAEQ,IAAI,EAAEC,MAAM,EAAEC,SAAS,EAAE,GAAGT,gBAClC,IAAOK,QAAQJ,IAAIK,WAAW,QAAQD,OAAOV,gBAAgBe,SAAS,EAAEN,MAAM,MAC9E;QAACE;QAAWD;QAAOD;KAAG;IAExB,OAAOF,QACL,IAAO,CAAA;YACLS,YAAYf,sBAAsBQ;YAClCQ,UAAUf,qBAAqBO,IAAIG;YACnCM,QAAQf,qBAAqBS,UAAU;YACvCO,OAAOC,QAAQV,UAAUG,WAAW;YACpCC;QACF,CAAA,GACA;QAACL;QAAIG;QAAMF;QAAOG;QAAQC;KAAU;AAExC;AAEA,eAAeN,eAAc"}
@@ -14,6 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
+ import { type Firestore } from 'firebase/firestore';
17
18
  export type CrmRecordKind = 'contact' | 'company' | 'deal';
18
19
  /** The collection each kind of record lives in, under `orgs/{orgId}/`. */
19
20
  export declare const CRM_RECORD_COLLECTIONS: Record<CrmRecordKind, string>;
@@ -28,6 +29,21 @@ export declare const CRM_RECORD_COLLECTIONS: Record<CrmRecordKind, string>;
28
29
  export declare function crmRecordName(kind: CrmRecordKind, data: Record<string, unknown> | undefined, groupId: string): string;
29
30
  /** Test seam: forget everything, so a spec's fixtures are what get read. */
30
31
  export declare function resetCrmRecordNameCache(): void;
32
+ /**
33
+ * The names of `records`, read now — for a one-off like a file export,
34
+ * which needs every name at once rather than a listener's re-render
35
+ * (AGL-3521). Shares {@link useCrmRecordNames}' cache, and answers the same
36
+ * lookup: `undefined` for a record that could not be named.
37
+ */
38
+ export declare function readCrmRecordNames(firestore: Firestore, options: {
39
+ orgId: string;
40
+ groupId: string | null;
41
+ org?: Record<string, unknown> | null;
42
+ records: ReadonlyArray<{
43
+ kind: CrmRecordKind;
44
+ id: string;
45
+ }>;
46
+ }): Promise<(kind: CrmRecordKind, id: string) => string | undefined>;
31
47
  /**
32
48
  * The names of the records a list of tasks points at, resolved once each.
33
49
  *
@@ -62,6 +62,45 @@ const cacheKey = (orgId, kind, id)=>`${orgId}/${CRM_RECORD_COLLECTIONS[kind]}/${
62
62
  nameCache.clear();
63
63
  pending.clear();
64
64
  }
65
+ /**
66
+ * The reads that fill the cache for `records` not already in it — each
67
+ * record read once however many callers ask at the same time.
68
+ */ function startNameReads(firestore, orgId, groupId, org, records) {
69
+ const reads = [];
70
+ for (const { kind, id } of records){
71
+ if (!id) continue;
72
+ const key = cacheKey(orgId, kind, id);
73
+ if (nameCache.has(key)) continue;
74
+ let read = pending.get(key);
75
+ if (!read) {
76
+ read = getDoc(doc(firestore, 'orgs', orgId, CRM_RECORD_COLLECTIONS[kind], id)).then((snapshot)=>{
77
+ const data = snapshot.exists() ? snapshot.data() : undefined;
78
+ nameCache.set(key, data ? crmRecordName(kind, data, groupId != null ? groupId : contactPrimaryGroup(data, org).groupId) : null);
79
+ }).catch(()=>{
80
+ // A refused or failed read is not cached: the cell keeps showing
81
+ // the id, and the next mount tries again.
82
+ }).finally(()=>{
83
+ pending.delete(key);
84
+ });
85
+ pending.set(key, read);
86
+ }
87
+ reads.push(read);
88
+ }
89
+ return reads;
90
+ }
91
+ /**
92
+ * The names of `records`, read now — for a one-off like a file export,
93
+ * which needs every name at once rather than a listener's re-render
94
+ * (AGL-3521). Shares {@link useCrmRecordNames}' cache, and answers the same
95
+ * lookup: `undefined` for a record that could not be named.
96
+ */ export async function readCrmRecordNames(firestore, options) {
97
+ const { orgId, groupId, org, records } = options;
98
+ await Promise.all(startNameReads(firestore, orgId, groupId, org, records));
99
+ return (kind, id)=>{
100
+ var _nameCache_get;
101
+ return (_nameCache_get = nameCache.get(cacheKey(orgId, kind, id))) != null ? _nameCache_get : undefined;
102
+ };
103
+ }
65
104
  /**
66
105
  * The names of the records a list of tasks points at, resolved once each.
67
106
  *
@@ -81,26 +120,13 @@ const cacheKey = (orgId, kind, id)=>`${orgId}/${CRM_RECORD_COLLECTIONS[kind]}/${
81
120
  useEffect(()=>{
82
121
  if (!orgId || !wanted) return;
83
122
  let active = true;
84
- const reads = [];
85
- for (const entry of wanted.split('\n')){
123
+ const reads = startNameReads(firestore, orgId, groupId, org, wanted.split('\n').map((entry)=>{
86
124
  const [kind, id] = entry.split(':');
87
- const key = cacheKey(orgId, kind, id);
88
- if (nameCache.has(key)) continue;
89
- let read = pending.get(key);
90
- if (!read) {
91
- read = getDoc(doc(firestore, 'orgs', orgId, CRM_RECORD_COLLECTIONS[kind], id)).then((snapshot)=>{
92
- const data = snapshot.exists() ? snapshot.data() : undefined;
93
- nameCache.set(key, data ? crmRecordName(kind, data, groupId != null ? groupId : contactPrimaryGroup(data, org).groupId) : null);
94
- }).catch(()=>{
95
- // A refused or failed read is not cached: the cell keeps showing
96
- // the id, and the next mount tries again.
97
- }).finally(()=>{
98
- pending.delete(key);
99
- });
100
- pending.set(key, read);
101
- }
102
- reads.push(read);
103
- }
125
+ return {
126
+ kind,
127
+ id
128
+ };
129
+ }));
104
130
  if (!reads.length) return;
105
131
  void Promise.all(reads).then(()=>{
106
132
  if (active) setResolved((count)=>count + 1);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-record-names.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { contactDisplayName, CRM_COLLECTIONS } from '@aglyn/aglyn'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport { doc, getDoc } from 'firebase/firestore'\nimport { useCallback, useEffect, useState } from 'react'\nimport { contactPrimaryGroup } from '../model/contact-record'\n\nexport type CrmRecordKind = 'contact' | 'company' | 'deal'\n\n/** The collection each kind of record lives in, under `orgs/{orgId}/`. */\nexport const CRM_RECORD_COLLECTIONS: Record<CrmRecordKind, string> = {\n contact: 'contacts',\n company: CRM_COLLECTIONS.companies,\n deal: CRM_COLLECTIONS.deals,\n}\n\n/**\n * What a record is CALLED, from its document.\n *\n * A contact's name is read through the viewing group's facet, the way the\n * people list reads it, so one business renaming a person does not change\n * what an unrelated business's task list shows; the email stands in for a\n * contact nobody has named. A company has a name and a deal a title.\n */\nexport function crmRecordName(\n kind: CrmRecordKind,\n data: Record<string, unknown> | undefined,\n groupId: string,\n): string {\n if (!data) return ''\n switch (kind) {\n case 'contact':\n return contactDisplayName(data, groupId) || String(data['email'] ?? '')\n case 'company':\n return String(data['name'] ?? '')\n case 'deal':\n return String(data['title'] ?? '')\n }\n}\n\n/**\n * Names already read, keyed by `orgId/collection/id`, shared by every\n * mount for the life of the page.\n *\n * A task list names the same handful of records over and over — five tasks\n * about one deal are five rows and one name — and a person moves between the\n * tasks section, a contact's page and the dashboard without the records\n * changing underneath them. `null` records a document that does not exist,\n * so a task pointing at a deleted record costs one read rather than one per\n * render. A rename is picked up on the next page load, which is the right\n * staleness for a label beside a link to the record itself.\n */\nconst nameCache = new Map<string, string | null>()\nconst pending = new Map<string, Promise<void>>()\n\nconst cacheKey = (orgId: string, kind: CrmRecordKind, id: string) =>\n `${orgId}/${CRM_RECORD_COLLECTIONS[kind]}/${id}`\n\n/** Test seam: forget everything, so a spec's fixtures are what get read. */\nexport function resetCrmRecordNameCache(): void {\n nameCache.clear()\n pending.clear()\n}\n\n/**\n * The names of the records a list of tasks points at, resolved once each.\n *\n * Returns a lookup rather than a map so the caller does not have to know the\n * cache's key shape. An unresolved record answers `undefined` — the cell\n * renders the link with the id until the name lands, which is one render\n * later on a warm cache and one round trip on a cold one.\n */\nexport function useCrmRecordNames(options: {\n orgId: string | null | undefined\n /**\n * The viewing group a contact is named through, or `null` at the\n * organization level (AGL-2630), where each contact is named through its\n * own primary holder, resolved from {@link org}.\n */\n groupId: string | null\n org?: Record<string, unknown> | null\n records: ReadonlyArray<{ kind: CrmRecordKind; id: string }>\n}): (kind: CrmRecordKind, id: string) => string | undefined {\n const { orgId, groupId, org, records } = options\n const firestore = useFirestore()\n // A counter rather than a copy of the cache: the cache is the source of\n // truth and this only exists to re-render when it grows.\n const [, setResolved] = useState(0)\n\n // The pairs as one string, so the effect runs when the SET changes and not\n // when the caller builds a new array of the same pairs on every render.\n const wanted = records\n .map((record) => `${record.kind}:${record.id}`)\n .filter((entry, index, all) => all.indexOf(entry) === index)\n .sort()\n .join('\\n')\n\n useEffect(() => {\n if (!orgId || !wanted) return\n let active = true\n const reads: Promise<void>[] = []\n for (const entry of wanted.split('\\n')) {\n const [kind, id] = entry.split(':') as [CrmRecordKind, string]\n const key = cacheKey(orgId, kind, id)\n if (nameCache.has(key)) continue\n let read = pending.get(key)\n if (!read) {\n read = getDoc(\n doc(firestore, 'orgs', orgId, CRM_RECORD_COLLECTIONS[kind], id),\n )\n .then((snapshot) => {\n const data = snapshot.exists()\n ? (snapshot.data() as Record<string, unknown>)\n : undefined\n nameCache.set(\n key,\n data\n ? crmRecordName(\n kind,\n data,\n groupId ?? contactPrimaryGroup(data, org).groupId,\n )\n : null,\n )\n })\n .catch(() => {\n // A refused or failed read is not cached: the cell keeps showing\n // the id, and the next mount tries again.\n })\n .finally(() => {\n pending.delete(key)\n })\n pending.set(key, read)\n }\n reads.push(read)\n }\n if (!reads.length) return\n void Promise.all(reads).then(() => {\n if (active) setResolved((count) => count + 1)\n })\n return () => {\n active = false\n }\n }, [firestore, orgId, groupId, wanted])\n\n return useCallback(\n (kind: CrmRecordKind, id: string) => {\n if (!orgId) return undefined\n const hit = nameCache.get(cacheKey(orgId, kind, id))\n return hit === null ? undefined : hit\n },\n [orgId],\n )\n}\n"],"names":["contactDisplayName","CRM_COLLECTIONS","useFirestore","doc","getDoc","useCallback","useEffect","useState","contactPrimaryGroup","CRM_RECORD_COLLECTIONS","contact","company","companies","deal","deals","crmRecordName","kind","data","groupId","String","nameCache","Map","pending","cacheKey","orgId","id","resetCrmRecordNameCache","clear","useCrmRecordNames","options","org","records","firestore","setResolved","wanted","map","record","filter","entry","index","all","indexOf","sort","join","active","reads","split","key","has","read","get","then","snapshot","exists","undefined","set","catch","finally","delete","push","length","Promise","count","hit"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-record-names.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { contactDisplayName, CRM_COLLECTIONS } from '@aglyn/aglyn'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport { doc, type Firestore, getDoc } from 'firebase/firestore'\nimport { useCallback, useEffect, useState } from 'react'\nimport { contactPrimaryGroup } from '../model/contact-record'\n\nexport type CrmRecordKind = 'contact' | 'company' | 'deal'\n\n/** The collection each kind of record lives in, under `orgs/{orgId}/`. */\nexport const CRM_RECORD_COLLECTIONS: Record<CrmRecordKind, string> = {\n contact: 'contacts',\n company: CRM_COLLECTIONS.companies,\n deal: CRM_COLLECTIONS.deals,\n}\n\n/**\n * What a record is CALLED, from its document.\n *\n * A contact's name is read through the viewing group's facet, the way the\n * people list reads it, so one business renaming a person does not change\n * what an unrelated business's task list shows; the email stands in for a\n * contact nobody has named. A company has a name and a deal a title.\n */\nexport function crmRecordName(\n kind: CrmRecordKind,\n data: Record<string, unknown> | undefined,\n groupId: string,\n): string {\n if (!data) return ''\n switch (kind) {\n case 'contact':\n return contactDisplayName(data, groupId) || String(data['email'] ?? '')\n case 'company':\n return String(data['name'] ?? '')\n case 'deal':\n return String(data['title'] ?? '')\n }\n}\n\n/**\n * Names already read, keyed by `orgId/collection/id`, shared by every\n * mount for the life of the page.\n *\n * A task list names the same handful of records over and over — five tasks\n * about one deal are five rows and one name — and a person moves between the\n * tasks section, a contact's page and the dashboard without the records\n * changing underneath them. `null` records a document that does not exist,\n * so a task pointing at a deleted record costs one read rather than one per\n * render. A rename is picked up on the next page load, which is the right\n * staleness for a label beside a link to the record itself.\n */\nconst nameCache = new Map<string, string | null>()\nconst pending = new Map<string, Promise<void>>()\n\nconst cacheKey = (orgId: string, kind: CrmRecordKind, id: string) =>\n `${orgId}/${CRM_RECORD_COLLECTIONS[kind]}/${id}`\n\n/** Test seam: forget everything, so a spec's fixtures are what get read. */\nexport function resetCrmRecordNameCache(): void {\n nameCache.clear()\n pending.clear()\n}\n\n/**\n * The reads that fill the cache for `records` not already in it — each\n * record read once however many callers ask at the same time.\n */\nfunction startNameReads(\n firestore: Firestore,\n orgId: string,\n groupId: string | null,\n org: Record<string, unknown> | null | undefined,\n records: ReadonlyArray<{ kind: CrmRecordKind; id: string }>,\n): Promise<void>[] {\n const reads: Promise<void>[] = []\n for (const { kind, id } of records) {\n if (!id) continue\n const key = cacheKey(orgId, kind, id)\n if (nameCache.has(key)) continue\n let read = pending.get(key)\n if (!read) {\n read = getDoc(doc(firestore, 'orgs', orgId, CRM_RECORD_COLLECTIONS[kind], id))\n .then((snapshot) => {\n const data = snapshot.exists() ? (snapshot.data() as Record<string, unknown>) : undefined\n nameCache.set(\n key,\n data ? crmRecordName(kind, data, groupId ?? contactPrimaryGroup(data, org).groupId) : null,\n )\n })\n .catch(() => {\n // A refused or failed read is not cached: the cell keeps showing\n // the id, and the next mount tries again.\n })\n .finally(() => {\n pending.delete(key)\n })\n pending.set(key, read)\n }\n reads.push(read)\n }\n return reads\n}\n\n/**\n * The names of `records`, read now — for a one-off like a file export,\n * which needs every name at once rather than a listener's re-render\n * (AGL-3521). Shares {@link useCrmRecordNames}' cache, and answers the same\n * lookup: `undefined` for a record that could not be named.\n */\nexport async function readCrmRecordNames(\n firestore: Firestore,\n options: {\n orgId: string\n groupId: string | null\n org?: Record<string, unknown> | null\n records: ReadonlyArray<{ kind: CrmRecordKind; id: string }>\n },\n): Promise<(kind: CrmRecordKind, id: string) => string | undefined> {\n const { orgId, groupId, org, records } = options\n await Promise.all(startNameReads(firestore, orgId, groupId, org, records))\n return (kind, id) => nameCache.get(cacheKey(orgId, kind, id)) ?? undefined\n}\n\n/**\n * The names of the records a list of tasks points at, resolved once each.\n *\n * Returns a lookup rather than a map so the caller does not have to know the\n * cache's key shape. An unresolved record answers `undefined` — the cell\n * renders the link with the id until the name lands, which is one render\n * later on a warm cache and one round trip on a cold one.\n */\nexport function useCrmRecordNames(options: {\n orgId: string | null | undefined\n /**\n * The viewing group a contact is named through, or `null` at the\n * organization level (AGL-2630), where each contact is named through its\n * own primary holder, resolved from {@link org}.\n */\n groupId: string | null\n org?: Record<string, unknown> | null\n records: ReadonlyArray<{ kind: CrmRecordKind; id: string }>\n}): (kind: CrmRecordKind, id: string) => string | undefined {\n const { orgId, groupId, org, records } = options\n const firestore = useFirestore()\n // A counter rather than a copy of the cache: the cache is the source of\n // truth and this only exists to re-render when it grows.\n const [, setResolved] = useState(0)\n\n // The pairs as one string, so the effect runs when the SET changes and not\n // when the caller builds a new array of the same pairs on every render.\n const wanted = records\n .map((record) => `${record.kind}:${record.id}`)\n .filter((entry, index, all) => all.indexOf(entry) === index)\n .sort()\n .join('\\n')\n\n useEffect(() => {\n if (!orgId || !wanted) return\n let active = true\n const reads = startNameReads(\n firestore,\n orgId,\n groupId,\n org,\n wanted.split('\\n').map((entry) => {\n const [kind, id] = entry.split(':') as [CrmRecordKind, string]\n return { kind, id }\n }),\n )\n if (!reads.length) return\n void Promise.all(reads).then(() => {\n if (active) setResolved((count) => count + 1)\n })\n return () => {\n active = false\n }\n }, [firestore, orgId, groupId, wanted])\n\n return useCallback(\n (kind: CrmRecordKind, id: string) => {\n if (!orgId) return undefined\n const hit = nameCache.get(cacheKey(orgId, kind, id))\n return hit === null ? undefined : hit\n },\n [orgId],\n )\n}\n"],"names":["contactDisplayName","CRM_COLLECTIONS","useFirestore","doc","getDoc","useCallback","useEffect","useState","contactPrimaryGroup","CRM_RECORD_COLLECTIONS","contact","company","companies","deal","deals","crmRecordName","kind","data","groupId","String","nameCache","Map","pending","cacheKey","orgId","id","resetCrmRecordNameCache","clear","startNameReads","firestore","org","records","reads","key","has","read","get","then","snapshot","exists","undefined","set","catch","finally","delete","push","readCrmRecordNames","options","Promise","all","useCrmRecordNames","setResolved","wanted","map","record","filter","entry","index","indexOf","sort","join","active","split","length","count","hit"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type CrmTaskPicklists } from '@aglyn/aglyn';
2
+ /**
3
+ * An org's Status, Priority and Type lists for tasks (AGL-3517), for every
4
+ * surface that shows or writes a task's labels. Three document listens,
5
+ * shared by the Firestore SDK with every other mount asking for the same
6
+ * lists; `orgId` null reads nothing and answers the standard values.
7
+ */
8
+ export declare function useCrmTaskPicklists(orgId: string | null | undefined): CrmTaskPicklists & {
9
+ ready: boolean;
10
+ };
11
+ export default useCrmTaskPicklists;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { CRM_TASK_PICKLIST_IDS } from "@aglyn/aglyn";
18
+ import { useMemo } from "react";
19
+ import { useCrmPicklist } from "./use-crm-picklist.js";
20
+ /**
21
+ * An org's Status, Priority and Type lists for tasks (AGL-3517), for every
22
+ * surface that shows or writes a task's labels. Three document listens,
23
+ * shared by the Firestore SDK with every other mount asking for the same
24
+ * lists; `orgId` null reads nothing and answers the standard values.
25
+ */ export function useCrmTaskPicklists(orgId) {
26
+ const status = useCrmPicklist(CRM_TASK_PICKLIST_IDS.status, orgId);
27
+ const priority = useCrmPicklist(CRM_TASK_PICKLIST_IDS.priority, orgId);
28
+ const type = useCrmPicklist(CRM_TASK_PICKLIST_IDS.type, orgId);
29
+ return useMemo(()=>({
30
+ status: status.picklist,
31
+ priority: priority.picklist,
32
+ type: type.picklist,
33
+ ready: status.ready && priority.ready && type.ready
34
+ }), [
35
+ status.picklist,
36
+ status.ready,
37
+ priority.picklist,
38
+ priority.ready,
39
+ type.picklist,
40
+ type.ready
41
+ ]);
42
+ }
43
+ export default useCrmTaskPicklists;
44
+
45
+ //# sourceMappingURL=use-crm-task-picklists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-crm-task-picklists.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CRM_TASK_PICKLIST_IDS, type CrmTaskPicklists } from '@aglyn/aglyn'\nimport { useMemo } from 'react'\nimport { useCrmPicklist } from './use-crm-picklist'\n\n/**\n * An org's Status, Priority and Type lists for tasks (AGL-3517), for every\n * surface that shows or writes a task's labels. Three document listens,\n * shared by the Firestore SDK with every other mount asking for the same\n * lists; `orgId` null reads nothing and answers the standard values.\n */\nexport function useCrmTaskPicklists(orgId: string | null | undefined): CrmTaskPicklists & {\n ready: boolean\n} {\n const status = useCrmPicklist(CRM_TASK_PICKLIST_IDS.status, orgId)\n const priority = useCrmPicklist(CRM_TASK_PICKLIST_IDS.priority, orgId)\n const type = useCrmPicklist(CRM_TASK_PICKLIST_IDS.type, orgId)\n return useMemo(\n () => ({\n status: status.picklist,\n priority: priority.picklist,\n type: type.picklist,\n ready: status.ready && priority.ready && type.ready,\n }),\n [status.picklist, status.ready, priority.picklist, priority.ready, type.picklist, type.ready],\n )\n}\n\nexport default useCrmTaskPicklists\n"],"names":["CRM_TASK_PICKLIST_IDS","useMemo","useCrmPicklist","useCrmTaskPicklists","orgId","status","priority","type","picklist","ready"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,qBAAqB,QAA+B,eAAc;AAC3E,SAASC,OAAO,QAAQ,QAAO;AAC/B,SAASC,cAAc,QAAQ,wBAAoB;AAEnD;;;;;CAKC,GACD,OAAO,SAASC,oBAAoBC,KAAgC;IAGlE,MAAMC,SAASH,eAAeF,sBAAsBK,MAAM,EAAED;IAC5D,MAAME,WAAWJ,eAAeF,sBAAsBM,QAAQ,EAAEF;IAChE,MAAMG,OAAOL,eAAeF,sBAAsBO,IAAI,EAAEH;IACxD,OAAOH,QACL,IAAO,CAAA;YACLI,QAAQA,OAAOG,QAAQ;YACvBF,UAAUA,SAASE,QAAQ;YAC3BD,MAAMA,KAAKC,QAAQ;YACnBC,OAAOJ,OAAOI,KAAK,IAAIH,SAASG,KAAK,IAAIF,KAAKE,KAAK;QACrD,CAAA,GACA;QAACJ,OAAOG,QAAQ;QAAEH,OAAOI,KAAK;QAAEH,SAASE,QAAQ;QAAEF,SAASG,KAAK;QAAEF,KAAKC,QAAQ;QAAED,KAAKE,KAAK;KAAC;AAEjG;AAEA,eAAeN,oBAAmB"}
@@ -32,5 +32,19 @@ export declare function useLinkedDeals(orgId: string | null, readTokens: readonl
32
32
  } | {
33
33
  companyId: string;
34
34
  }): import("@aglyn/tenant-feature-instance").UseFirestoreCollectionResult<DealDoc>;
35
+ /**
36
+ * The deals a contact is on in ANY role (AGL-3521), for the contact's page
37
+ * beside the deals that name them as `contactId`.
38
+ *
39
+ * At the organization level, `contactRoleContactIds array-contains`. Under
40
+ * a site the scope and the contact are one clause —
41
+ * `scopedContactRoleContactIds array-contains-any` over `token~contactId`
42
+ * — because a query holds one array clause and the scope clause is one;
43
+ * that is a query the rules prove only for an org-wide member
44
+ * (`foldsScope`). A member whose reach is some sites asks nothing here, and
45
+ * reads the deals that name the contact as their Primary.
46
+ * `(contactRoleContactIds | scopedContactRoleContactIds, updatedAt DESC)`.
47
+ */
48
+ export declare function useContactRoleDeals(orgId: string | null, readTokens: readonly string[] | null, foldsScope: boolean, contactId: string | null): import("@aglyn/tenant-feature-instance").UseFirestoreCollectionResult<DealDoc>;
35
49
  /** One deal, live. `undefined` while loading, and after a delete. */
36
50
  export declare function useDeal(orgId: string | null, dealId: string): import("@aglyn/tenant-feature-instance").UseFirestoreDocResult<DealDoc>;
@@ -15,6 +15,7 @@
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
17
  import { CRM_COLLECTIONS } from "@aglyn/aglyn";
18
+ import { SCOPED_SEARCH_JOIN } from "@aglyn/aglyn/app-utils/name-search";
18
19
  import { useFirestore, useFirestoreCollection, useFirestoreDoc } from "@aglyn/tenant-feature-instance";
19
20
  import { collection, doc, limit, orderBy, query, where } from "firebase/firestore";
20
21
  import { crmScopeListable, crmVisibleToClause } from "./use-crm-scope.js";
@@ -66,6 +67,34 @@ import { crmScopeListable, crmVisibleToClause } from "./use-crm-scope.js";
66
67
  idField: '$id'
67
68
  });
68
69
  }
70
+ /**
71
+ * The deals a contact is on in ANY role (AGL-3521), for the contact's page
72
+ * beside the deals that name them as `contactId`.
73
+ *
74
+ * At the organization level, `contactRoleContactIds array-contains`. Under
75
+ * a site the scope and the contact are one clause —
76
+ * `scopedContactRoleContactIds array-contains-any` over `token~contactId`
77
+ * — because a query holds one array clause and the scope clause is one;
78
+ * that is a query the rules prove only for an org-wide member
79
+ * (`foldsScope`). A member whose reach is some sites asks nothing here, and
80
+ * reads the deals that name the contact as their Primary.
81
+ * `(contactRoleContactIds | scopedContactRoleContactIds, updatedAt DESC)`.
82
+ */ export function useContactRoleDeals(orgId, readTokens, foldsScope, contactId) {
83
+ const firestore = useFirestore();
84
+ const scoped = readTokens ? readTokens.slice(0, 30).map((token)=>`${token}${SCOPED_SEARCH_JOIN}${contactId}`) : null;
85
+ const key = scoped ? scoped.join('\n') : '';
86
+ return useFirestoreCollection(()=>orgId && contactId && (readTokens === null || foldsScope && (scoped == null ? void 0 : scoped.length)) ? query(collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals), scoped ? where('scopedContactRoleContactIds', 'array-contains-any', scoped) : where('contactRoleContactIds', 'array-contains', contactId), orderBy('updatedAt', 'desc'), limit(LINKED_DEALS_LIMIT)) : null, // `key` stands for `scoped`, whose array is rebuilt on every render.
87
+ [
88
+ firestore,
89
+ orgId,
90
+ key,
91
+ foldsScope,
92
+ contactId,
93
+ readTokens === null
94
+ ], {
95
+ idField: '$id'
96
+ });
97
+ }
69
98
  /** One deal, live. `undefined` while loading, and after a delete. */ export function useDeal(orgId, dealId) {
70
99
  const firestore = useFirestore();
71
100
  return useFirestoreDoc(()=>orgId && dealId ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals, dealId) : null, [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-deals.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CRM_COLLECTIONS, type CrmDealStatus } from '@aglyn/aglyn'\nimport {\n useFirestore,\n useFirestoreCollection,\n useFirestoreDoc,\n} from '@aglyn/tenant-feature-instance'\nimport {\n collection,\n doc,\n limit,\n orderBy,\n query,\n where,\n} from 'firebase/firestore'\nimport type { DealDoc } from '../model/deal-board-model'\nimport { crmScopeListable, crmVisibleToClause } from './use-crm-scope'\n\n/**\n * The most open cards one pipeline draws. A board past this is a board\n * nobody reads column by column; the table is paged by its query\n * (`DEAL_LIST_DECLARATION`) and reaches the rest.\n */\nexport const BOARD_OPEN_LIMIT = 500\n\n/** Closed deals shown per closed column when it is expanded. */\nexport const BOARD_CLOSED_LIMIT = 50\n\n/** Deals listed on a contact's or a company's page. */\nexport const LINKED_DEALS_LIMIT = 25\n\n/**\n * The deals of one status in one pipeline, newest activity first (AGL-2598).\n *\n * Every query here carries the viewer's scope tokens and an `orderBy`, and\n * each shape sits on an index the foundation declared:\n * `(visibleTo, pipelineId, status, updatedAt DESC)`. Passing `null` for the\n * pipeline or an EMPTY token list issues nothing, which is how a column\n * stays quiet until the pipeline has loaded and a collapsed Won column\n * costs no read. A `null` token list is the ORGANIZATION level (AGL-2630):\n * the clause is dropped and the query rides the `(pipelineId, status,\n * updatedAt DESC)` twin of that index.\n */\nexport function useDealsByStatus(\n orgId: string | null,\n readTokens: readonly string[] | null,\n pipelineId: string | null,\n status: CrmDealStatus,\n max: number,\n) {\n const firestore = useFirestore()\n return useFirestoreCollection<DealDoc>(\n () =>\n orgId && pipelineId && crmScopeListable(readTokens)\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals),\n ...crmVisibleToClause(readTokens),\n where('pipelineId', '==', pipelineId),\n where('status', '==', status),\n orderBy('updatedAt', 'desc'),\n limit(max),\n )\n : null,\n [firestore, orgId, readTokens, pipelineId, status, max],\n { idField: '$id' },\n )\n}\n\n/**\n * The deals that name one contact or one company, for the card on that\n * record's page. `(visibleTo, contactId|companyId, updatedAt DESC)`.\n */\nexport function useLinkedDeals(\n orgId: string | null,\n readTokens: readonly string[] | null,\n link: { contactId: string } | { companyId: string },\n) {\n const firestore = useFirestore()\n const field = 'contactId' in link ? 'contactId' : 'companyId'\n const id = 'contactId' in link ? link.contactId : link.companyId\n return useFirestoreCollection<DealDoc>(\n () =>\n orgId && id && crmScopeListable(readTokens)\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals),\n ...crmVisibleToClause(readTokens),\n where(field, '==', id),\n orderBy('updatedAt', 'desc'),\n limit(LINKED_DEALS_LIMIT),\n )\n : null,\n [firestore, orgId, readTokens, field, id],\n { idField: '$id' },\n )\n}\n\n/** One deal, live. `undefined` while loading, and after a delete. */\nexport function useDeal(orgId: string | null, dealId: string) {\n const firestore = useFirestore()\n return useFirestoreDoc<DealDoc>(\n () =>\n orgId && dealId\n ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals, dealId)\n : null,\n [firestore, orgId, dealId],\n { idField: '$id' },\n )\n}\n"],"names":["CRM_COLLECTIONS","useFirestore","useFirestoreCollection","useFirestoreDoc","collection","doc","limit","orderBy","query","where","crmScopeListable","crmVisibleToClause","BOARD_OPEN_LIMIT","BOARD_CLOSED_LIMIT","LINKED_DEALS_LIMIT","useDealsByStatus","orgId","readTokens","pipelineId","status","max","firestore","deals","idField","useLinkedDeals","link","field","id","contactId","companyId","useDeal","dealId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,eAAe,QAA4B,eAAc;AAClE,SACEC,YAAY,EACZC,sBAAsB,EACtBC,eAAe,QACV,iCAAgC;AACvC,SACEC,UAAU,EACVC,GAAG,EACHC,KAAK,EACLC,OAAO,EACPC,KAAK,EACLC,KAAK,QACA,qBAAoB;AAE3B,SAASC,gBAAgB,EAAEC,kBAAkB,QAAQ,qBAAiB;AAEtE;;;;CAIC,GACD,OAAO,MAAMC,mBAAmB,IAAG;AAEnC,8DAA8D,GAC9D,OAAO,MAAMC,qBAAqB,GAAE;AAEpC,qDAAqD,GACrD,OAAO,MAAMC,qBAAqB,GAAE;AAEpC;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,iBACdC,KAAoB,EACpBC,UAAoC,EACpCC,UAAyB,EACzBC,MAAqB,EACrBC,GAAW;IAEX,MAAMC,YAAYpB;IAClB,OAAOC,uBACL,IACEc,SAASE,cAAcR,iBAAiBO,cACpCT,MACEJ,WAAWiB,WAAW,QAAQL,OAAOhB,gBAAgBsB,KAAK,MACvDX,mBAAmBM,aACtBR,MAAM,cAAc,MAAMS,aAC1BT,MAAM,UAAU,MAAMU,SACtBZ,QAAQ,aAAa,SACrBD,MAAMc,QAER,MACN;QAACC;QAAWL;QAAOC;QAAYC;QAAYC;QAAQC;KAAI,EACvD;QAAEG,SAAS;IAAM;AAErB;AAEA;;;CAGC,GACD,OAAO,SAASC,eACdR,KAAoB,EACpBC,UAAoC,EACpCQ,IAAmD;IAEnD,MAAMJ,YAAYpB;IAClB,MAAMyB,QAAQ,eAAeD,OAAO,cAAc;IAClD,MAAME,KAAK,eAAeF,OAAOA,KAAKG,SAAS,GAAGH,KAAKI,SAAS;IAChE,OAAO3B,uBACL,IACEc,SAASW,MAAMjB,iBAAiBO,cAC5BT,MACEJ,WAAWiB,WAAW,QAAQL,OAAOhB,gBAAgBsB,KAAK,MACvDX,mBAAmBM,aACtBR,MAAMiB,OAAO,MAAMC,KACnBpB,QAAQ,aAAa,SACrBD,MAAMQ,uBAER,MACN;QAACO;QAAWL;QAAOC;QAAYS;QAAOC;KAAG,EACzC;QAAEJ,SAAS;IAAM;AAErB;AAEA,mEAAmE,GACnE,OAAO,SAASO,QAAQd,KAAoB,EAAEe,MAAc;IAC1D,MAAMV,YAAYpB;IAClB,OAAOE,gBACL,IACEa,SAASe,SACL1B,IAAIgB,WAAW,QAAQL,OAAOhB,gBAAgBsB,KAAK,EAAES,UACrD,MACN;QAACV;QAAWL;QAAOe;KAAO,EAC1B;QAAER,SAAS;IAAM;AAErB"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-deals.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CRM_COLLECTIONS, type CrmDealStatus } from '@aglyn/aglyn'\nimport { SCOPED_SEARCH_JOIN } from '@aglyn/aglyn/app-utils/name-search'\nimport {\n useFirestore,\n useFirestoreCollection,\n useFirestoreDoc,\n} from '@aglyn/tenant-feature-instance'\nimport {\n collection,\n doc,\n limit,\n orderBy,\n query,\n where,\n} from 'firebase/firestore'\nimport type { DealDoc } from '../model/deal-board-model'\nimport { crmScopeListable, crmVisibleToClause } from './use-crm-scope'\n\n/**\n * The most open cards one pipeline draws. A board past this is a board\n * nobody reads column by column; the table is paged by its query\n * (`DEAL_LIST_DECLARATION`) and reaches the rest.\n */\nexport const BOARD_OPEN_LIMIT = 500\n\n/** Closed deals shown per closed column when it is expanded. */\nexport const BOARD_CLOSED_LIMIT = 50\n\n/** Deals listed on a contact's or a company's page. */\nexport const LINKED_DEALS_LIMIT = 25\n\n/**\n * The deals of one status in one pipeline, newest activity first (AGL-2598).\n *\n * Every query here carries the viewer's scope tokens and an `orderBy`, and\n * each shape sits on an index the foundation declared:\n * `(visibleTo, pipelineId, status, updatedAt DESC)`. Passing `null` for the\n * pipeline or an EMPTY token list issues nothing, which is how a column\n * stays quiet until the pipeline has loaded and a collapsed Won column\n * costs no read. A `null` token list is the ORGANIZATION level (AGL-2630):\n * the clause is dropped and the query rides the `(pipelineId, status,\n * updatedAt DESC)` twin of that index.\n */\nexport function useDealsByStatus(\n orgId: string | null,\n readTokens: readonly string[] | null,\n pipelineId: string | null,\n status: CrmDealStatus,\n max: number,\n) {\n const firestore = useFirestore()\n return useFirestoreCollection<DealDoc>(\n () =>\n orgId && pipelineId && crmScopeListable(readTokens)\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals),\n ...crmVisibleToClause(readTokens),\n where('pipelineId', '==', pipelineId),\n where('status', '==', status),\n orderBy('updatedAt', 'desc'),\n limit(max),\n )\n : null,\n [firestore, orgId, readTokens, pipelineId, status, max],\n { idField: '$id' },\n )\n}\n\n/**\n * The deals that name one contact or one company, for the card on that\n * record's page. `(visibleTo, contactId|companyId, updatedAt DESC)`.\n */\nexport function useLinkedDeals(\n orgId: string | null,\n readTokens: readonly string[] | null,\n link: { contactId: string } | { companyId: string },\n) {\n const firestore = useFirestore()\n const field = 'contactId' in link ? 'contactId' : 'companyId'\n const id = 'contactId' in link ? link.contactId : link.companyId\n return useFirestoreCollection<DealDoc>(\n () =>\n orgId && id && crmScopeListable(readTokens)\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals),\n ...crmVisibleToClause(readTokens),\n where(field, '==', id),\n orderBy('updatedAt', 'desc'),\n limit(LINKED_DEALS_LIMIT),\n )\n : null,\n [firestore, orgId, readTokens, field, id],\n { idField: '$id' },\n )\n}\n\n/**\n * The deals a contact is on in ANY role (AGL-3521), for the contact's page\n * beside the deals that name them as `contactId`.\n *\n * At the organization level, `contactRoleContactIds array-contains`. Under\n * a site the scope and the contact are one clause —\n * `scopedContactRoleContactIds array-contains-any` over `token~contactId`\n * — because a query holds one array clause and the scope clause is one;\n * that is a query the rules prove only for an org-wide member\n * (`foldsScope`). A member whose reach is some sites asks nothing here, and\n * reads the deals that name the contact as their Primary.\n * `(contactRoleContactIds | scopedContactRoleContactIds, updatedAt DESC)`.\n */\nexport function useContactRoleDeals(\n orgId: string | null,\n readTokens: readonly string[] | null,\n foldsScope: boolean,\n contactId: string | null,\n) {\n const firestore = useFirestore()\n const scoped = readTokens\n ? readTokens.slice(0, 30).map((token) => `${token}${SCOPED_SEARCH_JOIN}${contactId}`)\n : null\n const key = scoped ? scoped.join('\\n') : ''\n return useFirestoreCollection<DealDoc>(\n () =>\n orgId && contactId && (readTokens === null || (foldsScope && scoped?.length))\n ? query(\n collection(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals),\n scoped\n ? where('scopedContactRoleContactIds', 'array-contains-any', scoped)\n : where('contactRoleContactIds', 'array-contains', contactId),\n orderBy('updatedAt', 'desc'),\n limit(LINKED_DEALS_LIMIT),\n )\n : null,\n // `key` stands for `scoped`, whose array is rebuilt on every render.\n [firestore, orgId, key, foldsScope, contactId, readTokens === null],\n { idField: '$id' },\n )\n}\n\n/** One deal, live. `undefined` while loading, and after a delete. */\nexport function useDeal(orgId: string | null, dealId: string) {\n const firestore = useFirestore()\n return useFirestoreDoc<DealDoc>(\n () =>\n orgId && dealId\n ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals, dealId)\n : null,\n [firestore, orgId, dealId],\n { idField: '$id' },\n )\n}\n"],"names":["CRM_COLLECTIONS","SCOPED_SEARCH_JOIN","useFirestore","useFirestoreCollection","useFirestoreDoc","collection","doc","limit","orderBy","query","where","crmScopeListable","crmVisibleToClause","BOARD_OPEN_LIMIT","BOARD_CLOSED_LIMIT","LINKED_DEALS_LIMIT","useDealsByStatus","orgId","readTokens","pipelineId","status","max","firestore","deals","idField","useLinkedDeals","link","field","id","contactId","companyId","useContactRoleDeals","foldsScope","scoped","slice","map","token","key","join","length","useDeal","dealId"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CrmPicklist, CrmPicklistId } from '@aglyn/aglyn';
2
+ export interface LeadPicklistsResult {
3
+ /** Each list a lead field beside the lead source holds a value of, by picklist id. */
4
+ lists: Readonly<Partial<Record<CrmPicklistId, CrmPicklist>>>;
5
+ /** Every list has answered from the server. */
6
+ ready: boolean;
7
+ }
8
+ /**
9
+ * The org's lists behind a lead's Salutation, Industry and Rating
10
+ * (AGL-3513) — the contact's and the company's own lists, one document
11
+ * listen each, shared with every other mount asking for the same list.
12
+ */
13
+ export declare function useLeadPicklists(orgId: string | null | undefined): LeadPicklistsResult;
14
+ export default useLeadPicklists;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { useMemo } from "react";
18
+ import { useCrmPicklist } from "./use-crm-picklist.js";
19
+ /**
20
+ * The org's lists behind a lead's Salutation, Industry and Rating
21
+ * (AGL-3513) — the contact's and the company's own lists, one document
22
+ * listen each, shared with every other mount asking for the same list.
23
+ */ export function useLeadPicklists(orgId) {
24
+ const salutation = useCrmPicklist('salutation', orgId);
25
+ const industry = useCrmPicklist('industry', orgId);
26
+ const rating = useCrmPicklist('rating', orgId);
27
+ return useMemo(()=>({
28
+ lists: {
29
+ salutation: salutation.picklist,
30
+ industry: industry.picklist,
31
+ rating: rating.picklist
32
+ },
33
+ ready: [
34
+ salutation,
35
+ industry,
36
+ rating
37
+ ].every((list)=>list.ready)
38
+ }), [
39
+ salutation,
40
+ industry,
41
+ rating
42
+ ]);
43
+ }
44
+ export default useLeadPicklists;
45
+
46
+ //# sourceMappingURL=use-lead-picklists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-lead-picklists.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport type { CrmPicklist, CrmPicklistId } from '@aglyn/aglyn'\nimport { useMemo } from 'react'\nimport { useCrmPicklist } from './use-crm-picklist'\n\nexport interface LeadPicklistsResult {\n /** Each list a lead field beside the lead source holds a value of, by picklist id. */\n lists: Readonly<Partial<Record<CrmPicklistId, CrmPicklist>>>\n /** Every list has answered from the server. */\n ready: boolean\n}\n\n/**\n * The org's lists behind a lead's Salutation, Industry and Rating\n * (AGL-3513) — the contact's and the company's own lists, one document\n * listen each, shared with every other mount asking for the same list.\n */\nexport function useLeadPicklists(orgId: string | null | undefined): LeadPicklistsResult {\n const salutation = useCrmPicklist('salutation', orgId)\n const industry = useCrmPicklist('industry', orgId)\n const rating = useCrmPicklist('rating', orgId)\n return useMemo(\n () => ({\n lists: {\n salutation: salutation.picklist,\n industry: industry.picklist,\n rating: rating.picklist,\n },\n ready: [salutation, industry, rating].every((list) => list.ready),\n }),\n [salutation, industry, rating],\n )\n}\n\nexport default useLeadPicklists\n"],"names":["useMemo","useCrmPicklist","useLeadPicklists","orgId","salutation","industry","rating","lists","picklist","ready","every","list"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAGA,SAASA,OAAO,QAAQ,QAAO;AAC/B,SAASC,cAAc,QAAQ,wBAAoB;AASnD;;;;CAIC,GACD,OAAO,SAASC,iBAAiBC,KAAgC;IAC/D,MAAMC,aAAaH,eAAe,cAAcE;IAChD,MAAME,WAAWJ,eAAe,YAAYE;IAC5C,MAAMG,SAASL,eAAe,UAAUE;IACxC,OAAOH,QACL,IAAO,CAAA;YACLO,OAAO;gBACLH,YAAYA,WAAWI,QAAQ;gBAC/BH,UAAUA,SAASG,QAAQ;gBAC3BF,QAAQA,OAAOE,QAAQ;YACzB;YACAC,OAAO;gBAACL;gBAAYC;gBAAUC;aAAO,CAACI,KAAK,CAAC,CAACC,OAASA,KAAKF,KAAK;QAClE,CAAA,GACA;QAACL;QAAYC;QAAUC;KAAO;AAElC;AAEA,eAAeJ,iBAAgB"}
@@ -1,23 +1,9 @@
1
- import { type CrmPicklist } from '@aglyn/aglyn';
2
- export interface LeadSourcePicklistResult {
3
- /** The list every picker offers — the org's own, or the starter set. */
4
- picklist: CrmPicklist;
5
- /** The org has written its own list; false while it reads the starter set. */
6
- stored: boolean;
7
- /** The server has answered, so the list is the org's and not a placeholder. */
8
- ready: boolean;
9
- /** The document has not been confirmed by the server — `writeGuardedBySeed`'s input. */
10
- fromCache: boolean;
11
- }
1
+ import { type CrmPicklistResult } from './use-crm-picklist';
2
+ export type LeadSourcePicklistResult = Omit<CrmPicklistResult, 'definition'>;
12
3
  /**
13
- * The org's lead source values (AGL-3298), for every surface that offers
14
- * or manages them: the lead page's select, the New lead drawer, the
15
- * contact's card, the leads list's filter and the Fields page.
16
- *
17
- * One document listen, shared by the Firestore SDK across every mount that
18
- * asks for the same org, so a page with the list and a drawer open pays
19
- * for it once. `orgId` null issues no read and answers the starter set,
20
- * unready.
4
+ * The org's lead source values (AGL-3298) — {@link useCrmPicklist} for the
5
+ * lead source: the lead page's select, the New lead drawer, the contact's
6
+ * card, the leads list's filter and the import drawer.
21
7
  */
22
8
  export declare function useLeadSourcePicklist(orgId: string | null | undefined): LeadSourcePicklistResult;
23
9
  export default useLeadSourcePicklist;
@@ -14,34 +14,24 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
- import { CRM_COLLECTIONS, CRM_LEAD_SOURCE_PICKLIST, effectiveCrmLeadSourcePicklist, normalizeCrmPicklist } from "@aglyn/aglyn";
18
- import { useFirestore, useFirestoreDoc } from "@aglyn/tenant-feature-instance";
19
- import { doc } from "firebase/firestore";
17
+ import { CRM_LEAD_SOURCE_PICKLIST } from "@aglyn/aglyn";
20
18
  import { useMemo } from "react";
19
+ import { useCrmPicklist } from "./use-crm-picklist.js";
21
20
  /**
22
- * The org's lead source values (AGL-3298), for every surface that offers
23
- * or manages them: the lead page's select, the New lead drawer, the
24
- * contact's card, the leads list's filter and the Fields page.
25
- *
26
- * One document listen, shared by the Firestore SDK across every mount that
27
- * asks for the same org, so a page with the list and a drawer open pays
28
- * for it once. `orgId` null issues no read and answers the starter set,
29
- * unready.
21
+ * The org's lead source values (AGL-3298) — {@link useCrmPicklist} for the
22
+ * lead source: the lead page's select, the New lead drawer, the contact's
23
+ * card, the leads list's filter and the import drawer.
30
24
  */ export function useLeadSourcePicklist(orgId) {
31
- const firestore = useFirestore();
32
- const { data, status, fromCache } = useFirestoreDoc(()=>orgId ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.picklists, CRM_LEAD_SOURCE_PICKLIST) : null, [
33
- firestore,
34
- orgId
35
- ]);
25
+ const { picklist, stored, ready, fromCache } = useCrmPicklist(CRM_LEAD_SOURCE_PICKLIST, orgId);
36
26
  return useMemo(()=>({
37
- picklist: effectiveCrmLeadSourcePicklist(data),
38
- stored: normalizeCrmPicklist(data) !== null,
39
- ready: Boolean(orgId) && status !== 'loading',
27
+ picklist,
28
+ stored,
29
+ ready,
40
30
  fromCache
41
31
  }), [
42
- data,
43
- orgId,
44
- status,
32
+ picklist,
33
+ stored,
34
+ ready,
45
35
  fromCache
46
36
  ]);
47
37
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-lead-source-picklist.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n CRM_COLLECTIONS,\n CRM_LEAD_SOURCE_PICKLIST,\n type CrmPicklist,\n effectiveCrmLeadSourcePicklist,\n normalizeCrmPicklist,\n} from '@aglyn/aglyn'\nimport { useFirestore, useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport { doc } from 'firebase/firestore'\nimport { useMemo } from 'react'\n\nexport interface LeadSourcePicklistResult {\n /** The list every picker offers — the org's own, or the starter set. */\n picklist: CrmPicklist\n /** The org has written its own list; false while it reads the starter set. */\n stored: boolean\n /** The server has answered, so the list is the org's and not a placeholder. */\n ready: boolean\n /** The document has not been confirmed by the server — `writeGuardedBySeed`'s input. */\n fromCache: boolean\n}\n\n/**\n * The org's lead source values (AGL-3298), for every surface that offers\n * or manages them: the lead page's select, the New lead drawer, the\n * contact's card, the leads list's filter and the Fields page.\n *\n * One document listen, shared by the Firestore SDK across every mount that\n * asks for the same org, so a page with the list and a drawer open pays\n * for it once. `orgId` null issues no read and answers the starter set,\n * unready.\n */\nexport function useLeadSourcePicklist(orgId: string | null | undefined): LeadSourcePicklistResult {\n const firestore = useFirestore()\n const { data, status, fromCache } = useFirestoreDoc<Record<string, unknown>>(\n () =>\n orgId\n ? doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.picklists, CRM_LEAD_SOURCE_PICKLIST)\n : null,\n [firestore, orgId],\n )\n return useMemo(\n () => ({\n picklist: effectiveCrmLeadSourcePicklist(data),\n stored: normalizeCrmPicklist(data) !== null,\n ready: Boolean(orgId) && status !== 'loading',\n fromCache,\n }),\n [data, orgId, status, fromCache],\n )\n}\n\nexport default useLeadSourcePicklist\n"],"names":["CRM_COLLECTIONS","CRM_LEAD_SOURCE_PICKLIST","effectiveCrmLeadSourcePicklist","normalizeCrmPicklist","useFirestore","useFirestoreDoc","doc","useMemo","useLeadSourcePicklist","orgId","firestore","data","status","fromCache","picklists","picklist","stored","ready","Boolean"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SACEA,eAAe,EACfC,wBAAwB,EAExBC,8BAA8B,EAC9BC,oBAAoB,QACf,eAAc;AACrB,SAASC,YAAY,EAAEC,eAAe,QAAQ,iCAAgC;AAC9E,SAASC,GAAG,QAAQ,qBAAoB;AACxC,SAASC,OAAO,QAAQ,QAAO;AAa/B;;;;;;;;;CASC,GACD,OAAO,SAASC,sBAAsBC,KAAgC;IACpE,MAAMC,YAAYN;IAClB,MAAM,EAAEO,IAAI,EAAEC,MAAM,EAAEC,SAAS,EAAE,GAAGR,gBAClC,IACEI,QACIH,IAAII,WAAW,QAAQD,OAAOT,gBAAgBc,SAAS,EAAEb,4BACzD,MACN;QAACS;QAAWD;KAAM;IAEpB,OAAOF,QACL,IAAO,CAAA;YACLQ,UAAUb,+BAA+BS;YACzCK,QAAQb,qBAAqBQ,UAAU;YACvCM,OAAOC,QAAQT,UAAUG,WAAW;YACpCC;QACF,CAAA,GACA;QAACF;QAAMF;QAAOG;QAAQC;KAAU;AAEpC;AAEA,eAAeL,sBAAqB"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-lead-source-picklist.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CRM_LEAD_SOURCE_PICKLIST } from '@aglyn/aglyn'\nimport { useMemo } from 'react'\nimport { type CrmPicklistResult, useCrmPicklist } from './use-crm-picklist'\n\nexport type LeadSourcePicklistResult = Omit<CrmPicklistResult, 'definition'>\n\n/**\n * The org's lead source values (AGL-3298) — {@link useCrmPicklist} for the\n * lead source: the lead page's select, the New lead drawer, the contact's\n * card, the leads list's filter and the import drawer.\n */\nexport function useLeadSourcePicklist(orgId: string | null | undefined): LeadSourcePicklistResult {\n const { picklist, stored, ready, fromCache } = useCrmPicklist(CRM_LEAD_SOURCE_PICKLIST, orgId)\n return useMemo(() => ({ picklist, stored, ready, fromCache }), [picklist, stored, ready, fromCache])\n}\n\nexport default useLeadSourcePicklist\n"],"names":["CRM_LEAD_SOURCE_PICKLIST","useMemo","useCrmPicklist","useLeadSourcePicklist","orgId","picklist","stored","ready","fromCache"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,wBAAwB,QAAQ,eAAc;AACvD,SAASC,OAAO,QAAQ,QAAO;AAC/B,SAAiCC,cAAc,QAAQ,wBAAoB;AAI3E;;;;CAIC,GACD,OAAO,SAASC,sBAAsBC,KAAgC;IACpE,MAAM,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,KAAK,EAAEC,SAAS,EAAE,GAAGN,eAAeF,0BAA0BI;IACxF,OAAOH,QAAQ,IAAO,CAAA;YAAEI;YAAUC;YAAQC;YAAOC;QAAU,CAAA,GAAI;QAACH;QAAUC;QAAQC;QAAOC;KAAU;AACrG;AAEA,eAAeL,sBAAqB"}
@@ -0,0 +1,9 @@
1
+ import { type CrmPicklistResult } from './use-crm-picklist';
2
+ export type LeadStatusPicklistResult = Omit<CrmPicklistResult, 'definition'>;
3
+ /**
4
+ * The org's lead status values (AGL-3512) — {@link useCrmPicklist} for the
5
+ * lead status: every chip, select and filter that shows a lead's status by
6
+ * the label the org gave its meaning. One shared document listen.
7
+ */
8
+ export declare function useLeadStatusPicklist(orgId: string | null | undefined): LeadStatusPicklistResult;
9
+ export default useLeadStatusPicklist;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { CRM_LEAD_STATUS_PICKLIST } from "@aglyn/aglyn";
18
+ import { useMemo } from "react";
19
+ import { useCrmPicklist } from "./use-crm-picklist.js";
20
+ /**
21
+ * The org's lead status values (AGL-3512) — {@link useCrmPicklist} for the
22
+ * lead status: every chip, select and filter that shows a lead's status by
23
+ * the label the org gave its meaning. One shared document listen.
24
+ */ export function useLeadStatusPicklist(orgId) {
25
+ const { picklist, stored, ready, fromCache } = useCrmPicklist(CRM_LEAD_STATUS_PICKLIST, orgId);
26
+ return useMemo(()=>({
27
+ picklist,
28
+ stored,
29
+ ready,
30
+ fromCache
31
+ }), [
32
+ picklist,
33
+ stored,
34
+ ready,
35
+ fromCache
36
+ ]);
37
+ }
38
+ export default useLeadStatusPicklist;
39
+
40
+ //# sourceMappingURL=use-lead-status-picklist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/hooks/use-lead-status-picklist.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CRM_LEAD_STATUS_PICKLIST } from '@aglyn/aglyn'\nimport { useMemo } from 'react'\nimport { type CrmPicklistResult, useCrmPicklist } from './use-crm-picklist'\n\nexport type LeadStatusPicklistResult = Omit<CrmPicklistResult, 'definition'>\n\n/**\n * The org's lead status values (AGL-3512) — {@link useCrmPicklist} for the\n * lead status: every chip, select and filter that shows a lead's status by\n * the label the org gave its meaning. One shared document listen.\n */\nexport function useLeadStatusPicklist(orgId: string | null | undefined): LeadStatusPicklistResult {\n const { picklist, stored, ready, fromCache } = useCrmPicklist(CRM_LEAD_STATUS_PICKLIST, orgId)\n return useMemo(() => ({ picklist, stored, ready, fromCache }), [picklist, stored, ready, fromCache])\n}\n\nexport default useLeadStatusPicklist\n"],"names":["CRM_LEAD_STATUS_PICKLIST","useMemo","useCrmPicklist","useLeadStatusPicklist","orgId","picklist","stored","ready","fromCache"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,wBAAwB,QAAQ,eAAc;AACvD,SAASC,OAAO,QAAQ,QAAO;AAC/B,SAAiCC,cAAc,QAAQ,wBAAoB;AAI3E;;;;CAIC,GACD,OAAO,SAASC,sBAAsBC,KAAgC;IACpE,MAAM,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,KAAK,EAAEC,SAAS,EAAE,GAAGN,eAAeF,0BAA0BI;IACxF,OAAOH,QAAQ,IAAO,CAAA;YAAEI;YAAUC;YAAQC;YAAOC;QAAU,CAAA,GAAI;QAACH;QAAUC;QAAQC;QAAOC;KAAU;AACrG;AAEA,eAAeL,sBAAqB"}