@graph8/sdk 0.362.0 → 0.373.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (615) hide show
  1. package/README.md +33 -10
  2. package/blocks/_foundation/README.md +78 -1
  3. package/blocks/_foundation/block.json +123 -6
  4. package/blocks/_foundation/components/api-error.tsx +9 -7
  5. package/blocks/_foundation/components/brand-provider.tsx +23 -0
  6. package/blocks/_foundation/components/confirm-spend-dialog.tsx +15 -8
  7. package/blocks/_foundation/components/confirmed-action.tsx +90 -0
  8. package/blocks/_foundation/components/connect-graph8.tsx +280 -0
  9. package/blocks/_foundation/components/empty-state.tsx +5 -2
  10. package/blocks/_foundation/components/list-select.tsx +112 -0
  11. package/blocks/_foundation/components/paging-notices.tsx +55 -0
  12. package/blocks/_foundation/components/screen/detail-panel.tsx +2 -1
  13. package/blocks/_foundation/components/screen/filter-controls.tsx +92 -0
  14. package/blocks/_foundation/components/screen/index.ts +2 -0
  15. package/blocks/_foundation/components/screen/record-link.tsx +76 -0
  16. package/blocks/_foundation/components/screen/split-view.tsx +1 -1
  17. package/blocks/_foundation/components/screen/time-series-chart-recharts.tsx +65 -0
  18. package/blocks/_foundation/components/screen/time-series-chart.tsx +15 -97
  19. package/blocks/_foundation/components/screen/time-series-format.ts +57 -0
  20. package/blocks/_foundation/hooks/use-all-pages.ts +54 -0
  21. package/blocks/_foundation/hooks/use-brand.ts +52 -0
  22. package/blocks/_foundation/hooks/use-g8-mutation.ts +23 -0
  23. package/blocks/_foundation/hooks/use-g8-query.ts +127 -1
  24. package/blocks/_foundation/hooks/use-load-more-list.ts +61 -0
  25. package/blocks/_foundation/hooks/use-paginated.ts +120 -0
  26. package/blocks/_foundation/hooks/use-row-activation.ts +57 -0
  27. package/blocks/_foundation/hooks/use-url-filters.ts +93 -0
  28. package/blocks/_foundation/lib/g8-cache.ts +454 -0
  29. package/blocks/_foundation/lib/g8-client.ts +1 -1
  30. package/blocks/_foundation/lib/paging.ts +57 -0
  31. package/blocks/_foundation/lib/plural.ts +23 -0
  32. package/blocks/_foundation/lib/use-debounced-value.ts +13 -0
  33. package/blocks/_foundation/server/connect-route.ts +15 -0
  34. package/blocks/_foundation/server/connect.ts +127 -0
  35. package/blocks/_foundation/server/local-key.ts +70 -0
  36. package/blocks/_foundation/server/proxy.ts +103 -3
  37. package/blocks/_foundation/server/route.ts +16 -4
  38. package/blocks/agents/README.md +93 -2
  39. package/blocks/agents/block.json +343 -2
  40. package/blocks/agents/components/agent-activity.tsx +112 -0
  41. package/blocks/agents/components/agent-approvals.tsx +135 -0
  42. package/blocks/agents/components/agent-builder.tsx +29 -10
  43. package/blocks/agents/components/agent-conversations.tsx +143 -0
  44. package/blocks/agents/components/agent-knowledge-panel.tsx +4 -3
  45. package/blocks/agents/components/agent-operators.tsx +164 -0
  46. package/blocks/agents/components/agent-run-detail.tsx +119 -0
  47. package/blocks/agents/components/agent-runs.tsx +19 -10
  48. package/blocks/agents/components/agent-skills-panel.tsx +7 -7
  49. package/blocks/agents/components/agent-test-history.tsx +121 -0
  50. package/blocks/agents/components/agents-screen.tsx +226 -0
  51. package/blocks/agents/components/assistant-sessions.tsx +150 -0
  52. package/blocks/agents/components/duplicate-agent-button.tsx +42 -0
  53. package/blocks/agents/components/from-template-button.tsx +65 -0
  54. package/blocks/agents/components/knowledge-browser.tsx +107 -0
  55. package/blocks/agents/components/knowledge-detail.tsx +156 -0
  56. package/blocks/agents/components/knowledge-form.tsx +69 -0
  57. package/blocks/agents/components/name-dialog.tsx +32 -0
  58. package/blocks/agents/components/receptionist-button.tsx +46 -0
  59. package/blocks/agents/components/save-as-template-button.tsx +32 -0
  60. package/blocks/agents/components/skill-editor.tsx +147 -0
  61. package/blocks/agents/components/skill-library.tsx +111 -0
  62. package/blocks/agents/lib/agent-types.ts +7 -1
  63. package/blocks/agents/lib/facts.tsx +13 -0
  64. package/blocks/agents/lib/knowledge-utils.ts +49 -0
  65. package/blocks/agents/lib/load-more.tsx +141 -0
  66. package/blocks/agents/lib/skill-utils.ts +91 -0
  67. package/blocks/agents/recipes/create-agent-and-attach-skill.ts +1 -1
  68. package/blocks/analytics/README.md +13 -0
  69. package/blocks/analytics/block.json +45 -1
  70. package/blocks/analytics/components/analytics-screen.tsx +222 -0
  71. package/blocks/analytics/components/kpi-tiles.tsx +1 -1
  72. package/blocks/analytics/components/leaderboard.tsx +14 -7
  73. package/blocks/analytics/components/report-builder.tsx +38 -11
  74. package/blocks/analytics/components/report-detail.tsx +84 -0
  75. package/blocks/analytics/components/trend-chart.tsx +62 -0
  76. package/blocks/appointments/README.md +6 -0
  77. package/blocks/appointments/block.json +33 -2
  78. package/blocks/appointments/components/availability-editor.tsx +17 -5
  79. package/blocks/appointments/components/booking-page.tsx +2 -2
  80. package/blocks/appointments/components/event-type-editor.tsx +2 -1
  81. package/blocks/appointments/components/event-type-related.tsx +4 -2
  82. package/blocks/appointments/components/meeting-contact-links.tsx +49 -0
  83. package/blocks/appointments/components/meeting-detail.tsx +2 -2
  84. package/blocks/appointments/components/meeting-list.tsx +38 -18
  85. package/blocks/appointments/components/meetings-screen.tsx +7 -4
  86. package/blocks/appointments/components/record-meetings-tab.tsx +92 -0
  87. package/blocks/appointments/components/scheduling-screen.tsx +2 -1
  88. package/blocks/block.schema.json +18 -0
  89. package/blocks/block.types.ts +17 -0
  90. package/blocks/campaigns/README.md +41 -11
  91. package/blocks/campaigns/block.json +105 -42
  92. package/blocks/campaigns/components/campaign-assets.tsx +17 -6
  93. package/blocks/campaigns/components/campaign-launch-step.tsx +114 -26
  94. package/blocks/campaigns/components/campaign-list.tsx +7 -3
  95. package/blocks/campaigns/components/campaign-metrics.tsx +1 -1
  96. package/blocks/campaigns/components/campaign-wizard.tsx +52 -14
  97. package/blocks/campaigns/components/campaigns-screen.tsx +267 -0
  98. package/blocks/campaigns/components/icp-detail.tsx +163 -0
  99. package/blocks/campaigns/components/icp-editor.tsx +22 -17
  100. package/blocks/campaigns/components/persona-detail.tsx +181 -0
  101. package/blocks/campaigns/components/persona-editor.tsx +19 -11
  102. package/blocks/campaigns/lib/campaigns-utils.ts +138 -5
  103. package/blocks/campaigns/recipes/attach-audience-and-launch.ts +16 -3
  104. package/blocks/campaigns/recipes/generate-ideas-and-create-campaign.ts +8 -4
  105. package/blocks/coach/README.md +10 -0
  106. package/blocks/coach/block.json +16 -1
  107. package/blocks/coach/components/call-scorecard.tsx +7 -7
  108. package/blocks/coach/components/coach-screen.tsx +222 -0
  109. package/blocks/company-intelligence/README.md +132 -0
  110. package/blocks/company-intelligence/block.json +318 -0
  111. package/blocks/company-intelligence/components/company-intelligence-screen.tsx +114 -0
  112. package/blocks/company-intelligence/components/company-intelligence-tab.tsx +88 -0
  113. package/blocks/company-intelligence/components/company-profile.tsx +68 -0
  114. package/blocks/company-intelligence/components/intelligence-sources.tsx +63 -0
  115. package/blocks/company-intelligence/components/report-detail.tsx +189 -0
  116. package/blocks/company-intelligence/components/research-reports.tsx +136 -0
  117. package/blocks/company-intelligence/components/research-run.tsx +161 -0
  118. package/blocks/company-intelligence/components/source-detail.tsx +117 -0
  119. package/blocks/company-intelligence/components/source-view.tsx +274 -0
  120. package/blocks/company-intelligence/components/wiki-document-detail.tsx +116 -0
  121. package/blocks/company-intelligence/components/wiki-documents.tsx +66 -0
  122. package/blocks/company-intelligence/hooks/use-intelligence.ts +173 -0
  123. package/blocks/company-intelligence/lib/intelligence-types.ts +230 -0
  124. package/blocks/company-intelligence/lib/safe-markdown.tsx +150 -0
  125. package/blocks/company-intelligence/recipes/read-competitors-and-news.ts +33 -0
  126. package/blocks/company-intelligence/recipes/research-your-website.ts +43 -0
  127. package/blocks/company-intelligence/recipes/write-the-research-reports.ts +54 -0
  128. package/blocks/copilot/README.md +13 -0
  129. package/blocks/copilot/block.json +14 -1
  130. package/blocks/copilot/components/copilot-memory.tsx +6 -2
  131. package/blocks/copilot/components/copilot-panel.tsx +14 -5
  132. package/blocks/copilot/components/copilot-screen.tsx +148 -0
  133. package/blocks/copilot/components/copilot-team-chat.tsx +13 -6
  134. package/blocks/crm/README.md +34 -0
  135. package/blocks/crm/block.json +107 -2
  136. package/blocks/crm/components/companies-screen.tsx +359 -0
  137. package/blocks/crm/components/company-detail.tsx +10 -8
  138. package/blocks/crm/components/company-table.tsx +11 -4
  139. package/blocks/crm/components/contact-detail.tsx +10 -7
  140. package/blocks/crm/components/contact-lookup-link.tsx +44 -0
  141. package/blocks/crm/components/contact-table.tsx +10 -3
  142. package/blocks/crm/components/contacts-screen.tsx +377 -0
  143. package/blocks/crm/components/dedupe-review.tsx +13 -6
  144. package/blocks/crm/components/import-wizard.tsx +7 -9
  145. package/blocks/crm/components/list-select.tsx +20 -0
  146. package/blocks/crm/components/notes-panel.tsx +4 -4
  147. package/blocks/crm/components/record-engagement-tab.tsx +103 -0
  148. package/blocks/crm/components/record-form.tsx +6 -4
  149. package/blocks/crm/components/task-list.tsx +4 -4
  150. package/blocks/crm/components/tasks-screen.tsx +399 -0
  151. package/blocks/crm/hooks/use-all-lists.ts +18 -0
  152. package/blocks/crm/hooks/use-custom-fields.ts +6 -1
  153. package/blocks/crm/hooks/use-page-query.ts +9 -1
  154. package/blocks/crm/lib/crm-types.ts +26 -2
  155. package/blocks/crm/lib/read-lists.ts +16 -0
  156. package/blocks/crm/lib/screen-parts.tsx +105 -0
  157. package/blocks/deals/README.md +24 -6
  158. package/blocks/deals/block.json +160 -5
  159. package/blocks/deals/components/close-deal-dialog.tsx +169 -0
  160. package/blocks/deals/components/deal-contacts-editor.tsx +134 -0
  161. package/blocks/deals/components/deal-detail.tsx +25 -13
  162. package/blocks/deals/components/deal-filters.tsx +65 -0
  163. package/blocks/deals/components/deal-line-items.tsx +120 -0
  164. package/blocks/deals/components/deal-notes-tab.tsx +97 -0
  165. package/blocks/deals/components/deal-related.tsx +31 -10
  166. package/blocks/deals/components/deal-tasks-tab.tsx +88 -0
  167. package/blocks/deals/components/deals-screen.tsx +66 -26
  168. package/blocks/deals/components/forecast-view.tsx +4 -4
  169. package/blocks/deals/components/pipeline-board.tsx +8 -6
  170. package/blocks/deals/components/pipeline-editor.tsx +132 -0
  171. package/blocks/deals/components/record-deals-tab.tsx +62 -0
  172. package/blocks/deals/components/stage-editor.tsx +5 -5
  173. package/blocks/deals/hooks/use-pipeline-deals.ts +21 -4
  174. package/blocks/deals/hooks/use-pipelines.ts +1 -1
  175. package/blocks/deals/lib/deal-extras.ts +156 -0
  176. package/blocks/dialer/README.md +45 -4
  177. package/blocks/dialer/block.json +84 -3
  178. package/blocks/dialer/components/call-contact-button.tsx +269 -0
  179. package/blocks/dialer/components/call-log-screen.tsx +208 -0
  180. package/blocks/dialer/components/call-log.tsx +23 -7
  181. package/blocks/dialer/components/call-queue.tsx +4 -4
  182. package/blocks/dialer/components/dialer-screen.tsx +361 -0
  183. package/blocks/dialer/components/dialer-session-detail.tsx +153 -0
  184. package/blocks/dialer/components/disposition-panel.tsx +1 -1
  185. package/blocks/dialer/components/live-calls-table.tsx +7 -3
  186. package/blocks/dialer/components/record-calls-tab.tsx +101 -0
  187. package/blocks/dialer/components/session-start-form.tsx +61 -12
  188. package/blocks/dialer/components/softphone.tsx +4 -2
  189. package/blocks/enrichment/README.md +29 -7
  190. package/blocks/enrichment/block.json +49 -9
  191. package/blocks/enrichment/components/bulk-enrich-panel.tsx +83 -29
  192. package/blocks/enrichment/components/email-verify-badge.tsx +31 -11
  193. package/blocks/enrichment/components/enrich-button.tsx +32 -9
  194. package/blocks/enrichment/components/enrichment-job-detail.tsx +78 -0
  195. package/blocks/enrichment/components/enrichment-screen.tsx +341 -0
  196. package/blocks/enrichment/components/waterfall-config.tsx +66 -17
  197. package/blocks/enrichment/lib/enrichment-types.ts +39 -0
  198. package/blocks/enrichment/recipes/bulk-enrich-and-poll.ts +15 -4
  199. package/blocks/enrichment/recipes/waterfall-pipeline.ts +3 -2
  200. package/blocks/forms/README.md +8 -0
  201. package/blocks/forms/block.json +139 -18
  202. package/blocks/forms/components/form-activity.tsx +71 -0
  203. package/blocks/forms/components/form-backfill.tsx +108 -0
  204. package/blocks/forms/components/form-builder.tsx +4 -2
  205. package/blocks/forms/components/form-embed.tsx +4 -2
  206. package/blocks/forms/components/form-groups.tsx +151 -0
  207. package/blocks/forms/components/form-mapping-editor.tsx +6 -9
  208. package/blocks/forms/components/form-route-history.tsx +72 -0
  209. package/blocks/forms/components/form-saved-views.tsx +81 -0
  210. package/blocks/forms/components/forms-screen.tsx +56 -19
  211. package/blocks/forms/components/more-rows.tsx +30 -0
  212. package/blocks/forms/components/submissions-export.tsx +67 -0
  213. package/blocks/forms/components/submissions-table.tsx +17 -6
  214. package/blocks/forms/lib/forms-extra.ts +67 -0
  215. package/blocks/inbox/README.md +32 -3
  216. package/blocks/inbox/block.json +29 -2
  217. package/blocks/inbox/components/inbox-list.tsx +7 -3
  218. package/blocks/inbox/components/inbox-screen.tsx +294 -27
  219. package/blocks/inbox/components/record-conversations-tab.tsx +154 -0
  220. package/blocks/inbox/components/reply-composer.tsx +65 -9
  221. package/blocks/inbox/components/tag-and-assign.tsx +4 -2
  222. package/blocks/inbox/components/thread-badge.tsx +2 -2
  223. package/blocks/inbox/components/thread-view.tsx +1 -1
  224. package/blocks/inbox/hooks/use-inbox-thread.ts +1 -1
  225. package/blocks/inbox/hooks/use-inbox-threads.ts +1 -0
  226. package/blocks/inbox/lib/inbox-types.ts +47 -1
  227. package/blocks/inbox/recipes/01-triage-and-reply.ts +12 -2
  228. package/blocks/integrations/README.md +63 -1
  229. package/blocks/integrations/block.json +234 -15
  230. package/blocks/integrations/components/ad-accounts.tsx +82 -0
  231. package/blocks/integrations/components/connection-health.tsx +59 -0
  232. package/blocks/integrations/components/crm-detail.tsx +119 -0
  233. package/blocks/integrations/components/crm-records.tsx +103 -0
  234. package/blocks/integrations/components/field-mappings.tsx +61 -0
  235. package/blocks/integrations/components/integration-list.tsx +13 -8
  236. package/blocks/integrations/components/integrations-screen.tsx +152 -0
  237. package/blocks/integrations/components/migration-panel.tsx +133 -0
  238. package/blocks/integrations/components/sugarcrm-connect.tsx +95 -0
  239. package/blocks/integrations/components/sync-status.tsx +11 -9
  240. package/blocks/integrations/components/sync-triggers.tsx +134 -0
  241. package/blocks/integrations/components/webhook-detail.tsx +179 -0
  242. package/blocks/integrations/components/webhook-manager.tsx +43 -25
  243. package/blocks/integrations/components/workspace-tools.tsx +127 -0
  244. package/blocks/integrations/lib/crm-utils.ts +39 -0
  245. package/blocks/integrations/lib/facts.tsx +13 -0
  246. package/blocks/integrations/lib/integrations-utils.ts +11 -1
  247. package/blocks/integrations/lib/load-more.tsx +141 -0
  248. package/blocks/intent/README.md +14 -0
  249. package/blocks/intent/block.json +27 -1
  250. package/blocks/intent/components/account-intent-score.tsx +5 -5
  251. package/blocks/intent/components/intent-feed.tsx +13 -10
  252. package/blocks/intent/components/intent-keyword-manager.tsx +16 -12
  253. package/blocks/intent/components/intent-screen.tsx +265 -0
  254. package/blocks/intent/components/keyword-detail.tsx +124 -0
  255. package/blocks/intent/lib/intent-utils.ts +4 -4
  256. package/blocks/lifecycle/block.json +13 -8
  257. package/blocks/lifecycle/components/account-related.tsx +8 -1
  258. package/blocks/lifecycle/components/churn-list.tsx +5 -2
  259. package/blocks/lifecycle/components/customer-table.tsx +1 -1
  260. package/blocks/lifecycle/components/lifecycle-board.tsx +3 -1
  261. package/blocks/lifecycle/components/lifecycle-screen.tsx +3 -1
  262. package/blocks/lifecycle/lib/lifecycle.ts +1 -1
  263. package/blocks/lists/README.md +20 -1
  264. package/blocks/lists/block.json +69 -3
  265. package/blocks/lists/components/add-company-people-to-list-button.tsx +73 -0
  266. package/blocks/lists/components/add-to-list-button.tsx +20 -9
  267. package/blocks/lists/components/list-picker.tsx +17 -3
  268. package/blocks/lists/components/list-table.tsx +12 -6
  269. package/blocks/lists/components/lists-screen.tsx +346 -0
  270. package/blocks/lists/components/record-lists-tab.tsx +99 -0
  271. package/blocks/lists/components/suppression-manager.tsx +33 -8
  272. package/blocks/lists/components/suppressions-screen.tsx +264 -0
  273. package/blocks/mailboxes/README.md +17 -0
  274. package/blocks/mailboxes/block.json +69 -17
  275. package/blocks/mailboxes/components/connect-mailbox.tsx +32 -21
  276. package/blocks/mailboxes/components/domain-detail.tsx +148 -0
  277. package/blocks/mailboxes/components/domain-purchase.tsx +20 -14
  278. package/blocks/mailboxes/components/mailbox-detail.tsx +157 -0
  279. package/blocks/mailboxes/components/mailbox-list.tsx +8 -3
  280. package/blocks/mailboxes/components/mailboxes-screen.tsx +228 -0
  281. package/blocks/mailboxes/components/warmup-health.tsx +24 -22
  282. package/blocks/mailboxes/lib/mailboxes-utils.ts +26 -5
  283. package/blocks/mailboxes/lib/use-provider-domains.ts +23 -0
  284. package/blocks/newsletter/README.md +12 -0
  285. package/blocks/newsletter/block.json +157 -24
  286. package/blocks/newsletter/components/issue-scheduler.tsx +4 -3
  287. package/blocks/newsletter/components/issue-versions.tsx +93 -0
  288. package/blocks/newsletter/components/more-rows.tsx +30 -0
  289. package/blocks/newsletter/components/newsletter-editor.tsx +1 -1
  290. package/blocks/newsletter/components/newsletter-list-syncs.tsx +121 -0
  291. package/blocks/newsletter/components/newsletter-screen.tsx +39 -14
  292. package/blocks/newsletter/components/newsletter-settings.tsx +211 -0
  293. package/blocks/newsletter/components/newsletter-stats.tsx +2 -2
  294. package/blocks/newsletter/components/newsletter-templates.tsx +133 -0
  295. package/blocks/newsletter/components/subscriber-table.tsx +5 -7
  296. package/blocks/newsletter/components/subscriber-timeline.tsx +65 -0
  297. package/blocks/newsletter/lib/newsletter-extra.ts +60 -0
  298. package/blocks/nurture/block.json +28 -14
  299. package/blocks/nurture/components/nurture-builder.tsx +13 -3
  300. package/blocks/nurture/components/nurture-enroll.tsx +12 -10
  301. package/blocks/nurture/components/nurture-form.tsx +27 -10
  302. package/blocks/nurture/components/nurture-screen.tsx +26 -11
  303. package/blocks/nurture/components/nurture-stats.tsx +5 -4
  304. package/blocks/nurture/lib/nurture-types.ts +1 -1
  305. package/blocks/objects/README.md +18 -1
  306. package/blocks/objects/block.json +42 -21
  307. package/blocks/objects/components/attribute-field-input.tsx +14 -1
  308. package/blocks/objects/components/object-not-found.tsx +3 -1
  309. package/blocks/objects/components/object-record-detail.tsx +10 -2
  310. package/blocks/objects/components/object-schema-editor.tsx +4 -2
  311. package/blocks/objects/components/object-table.tsx +13 -3
  312. package/blocks/objects/components/objects-screen.tsx +147 -0
  313. package/blocks/objects/components/record-roles-panel.tsx +15 -5
  314. package/blocks/objects/lib/object-types.ts +1 -1
  315. package/blocks/pages/README.md +14 -0
  316. package/blocks/pages/block.json +140 -23
  317. package/blocks/pages/components/brand-kit-editor.tsx +5 -2
  318. package/blocks/pages/components/content-library.tsx +9 -4
  319. package/blocks/pages/components/more-rows.tsx +30 -0
  320. package/blocks/pages/components/page-ai-tools.tsx +196 -0
  321. package/blocks/pages/components/page-analytics.tsx +176 -0
  322. package/blocks/pages/components/page-clone.tsx +99 -0
  323. package/blocks/pages/components/page-domains.tsx +167 -0
  324. package/blocks/pages/components/page-editor.tsx +1 -1
  325. package/blocks/pages/components/page-generation-status.tsx +48 -0
  326. package/blocks/pages/components/page-list.tsx +2 -1
  327. package/blocks/pages/components/page-tracking.tsx +137 -0
  328. package/blocks/pages/components/pages-screen.tsx +57 -16
  329. package/blocks/pages/components/seo-report.tsx +6 -1
  330. package/blocks/pages/lib/studio.ts +7 -0
  331. package/blocks/phone-numbers/README.md +74 -0
  332. package/blocks/phone-numbers/block.json +262 -0
  333. package/blocks/phone-numbers/components/a2p-registration.tsx +230 -0
  334. package/blocks/phone-numbers/components/assign-number.tsx +104 -0
  335. package/blocks/phone-numbers/components/number-search.tsx +239 -0
  336. package/blocks/phone-numbers/components/number-settings.tsx +134 -0
  337. package/blocks/phone-numbers/components/number-usage.tsx +97 -0
  338. package/blocks/phone-numbers/components/phone-number-detail.tsx +84 -0
  339. package/blocks/phone-numbers/components/phone-number-list.tsx +110 -0
  340. package/blocks/phone-numbers/components/phone-numbers-screen.tsx +201 -0
  341. package/blocks/phone-numbers/components/register-owned-number.tsx +98 -0
  342. package/blocks/phone-numbers/components/release-number.tsx +126 -0
  343. package/blocks/phone-numbers/hooks/use-phone-numbers.ts +58 -0
  344. package/blocks/phone-numbers/lib/phone-numbers-utils.ts +202 -0
  345. package/blocks/phone-numbers/recipes/01-search-and-buy-number.ts +49 -0
  346. package/blocks/phone-numbers/recipes/02-assign-number-to-rep.ts +25 -0
  347. package/blocks/phone-numbers/recipes/03-audit-numbers.ts +36 -0
  348. package/blocks/phone-numbers/recipes/04-register-text-messaging.ts +39 -0
  349. package/blocks/pickers/README.md +23 -0
  350. package/blocks/pickers/block.json +103 -0
  351. package/blocks/pickers/components/company-picker.tsx +90 -0
  352. package/blocks/pickers/components/contact-picker.tsx +131 -0
  353. package/blocks/pickers/components/member-picker.tsx +99 -0
  354. package/blocks/pickers/components/search-picker.tsx +98 -0
  355. package/blocks/pickers/hooks/use-current-member.ts +104 -0
  356. package/blocks/pickers/hooks/use-picker-pages.ts +73 -0
  357. package/blocks/pickers/lib/use-debounced.ts +13 -0
  358. package/blocks/quotes/README.md +13 -0
  359. package/blocks/quotes/block.json +65 -13
  360. package/blocks/quotes/components/create-quote-from-deal.tsx +48 -0
  361. package/blocks/quotes/components/product-picker.tsx +3 -1
  362. package/blocks/quotes/components/quote-builder.tsx +1 -1
  363. package/blocks/quotes/components/quote-lifecycle-actions.tsx +146 -0
  364. package/blocks/quotes/components/quote-list.tsx +5 -3
  365. package/blocks/quotes/components/quote-related.tsx +8 -4
  366. package/blocks/quotes/components/quote-viewer.tsx +7 -2
  367. package/blocks/quotes/components/record-quotes-tab.tsx +90 -0
  368. package/blocks/radar/README.md +10 -0
  369. package/blocks/radar/block.json +41 -1
  370. package/blocks/radar/components/competitor-battle-card.tsx +1 -1
  371. package/blocks/radar/components/competitor-detail.tsx +117 -0
  372. package/blocks/radar/components/competitor-tracker.tsx +3 -1
  373. package/blocks/radar/components/radar-overview.tsx +4 -4
  374. package/blocks/radar/components/radar-report.tsx +4 -2
  375. package/blocks/radar/components/radar-screen.tsx +214 -0
  376. package/blocks/radar/components/report-detail.tsx +104 -0
  377. package/blocks/search/README.md +10 -0
  378. package/blocks/search/block.json +16 -1
  379. package/blocks/search/components/filter-builder.tsx +3 -3
  380. package/blocks/search/components/prospect-results.tsx +5 -3
  381. package/blocks/search/components/prospect-search-screen.tsx +235 -0
  382. package/blocks/search/components/saved-searches.tsx +4 -1
  383. package/blocks/search/hooks/use-filter-options.ts +20 -6
  384. package/blocks/search/lib/search-types.ts +2 -0
  385. package/blocks/sequencer/README.md +55 -9
  386. package/blocks/sequencer/block.json +126 -19
  387. package/blocks/sequencer/components/add-to-sequence-button.tsx +82 -0
  388. package/blocks/sequencer/components/enroll-dialog.tsx +11 -5
  389. package/blocks/sequencer/components/record-sequences-tab.tsx +126 -0
  390. package/blocks/sequencer/components/sequence-builder.tsx +224 -60
  391. package/blocks/sequencer/components/sequence-detail.tsx +261 -0
  392. package/blocks/sequencer/components/sequence-enrollments.tsx +116 -0
  393. package/blocks/sequencer/components/sequence-list.tsx +34 -9
  394. package/blocks/sequencer/components/sequence-stats.tsx +11 -10
  395. package/blocks/sequencer/components/sequence-steps-panel.tsx +103 -0
  396. package/blocks/sequencer/components/sequences-screen.tsx +162 -0
  397. package/blocks/sequencer/components/step-editor.tsx +14 -12
  398. package/blocks/sequencer/lib/sequencer-utils.ts +133 -10
  399. package/blocks/sequencer/recipes/create-multichannel-sequence.ts +33 -5
  400. package/blocks/sequencer/recipes/launch-and-enroll.ts +19 -2
  401. package/blocks/social-ads/README.md +19 -0
  402. package/blocks/social-ads/block.json +233 -1
  403. package/blocks/social-ads/components/ad-campaign-list.tsx +9 -5
  404. package/blocks/social-ads/components/ads-screen.tsx +152 -0
  405. package/blocks/social-ads/components/audience-sync-detail.tsx +194 -0
  406. package/blocks/social-ads/components/audience-sync.tsx +17 -9
  407. package/blocks/social-ads/components/campaign-ads.tsx +166 -0
  408. package/blocks/social-ads/components/campaign-detail.tsx +138 -0
  409. package/blocks/social-ads/components/campaign-editor.tsx +134 -0
  410. package/blocks/social-ads/components/creative-concepts.tsx +74 -0
  411. package/blocks/social-ads/components/creative-detail.tsx +155 -0
  412. package/blocks/social-ads/components/creative-gallery.tsx +35 -7
  413. package/blocks/social-ads/components/creative-revisions.tsx +57 -0
  414. package/blocks/social-ads/components/creative-tools.tsx +176 -0
  415. package/blocks/social-ads/components/post-composer.tsx +7 -3
  416. package/blocks/social-ads/components/post-detail.tsx +163 -0
  417. package/blocks/social-ads/components/social-ideas.tsx +64 -0
  418. package/blocks/social-ads/components/social-performance.tsx +80 -0
  419. package/blocks/social-ads/components/social-post-list.tsx +11 -3
  420. package/blocks/social-ads/components/social-screen.tsx +187 -0
  421. package/blocks/social-ads/lib/ads-extra.ts +67 -0
  422. package/blocks/surveys/README.md +91 -0
  423. package/blocks/surveys/block.json +299 -0
  424. package/blocks/surveys/components/account-nps.tsx +69 -0
  425. package/blocks/surveys/components/contact-survey-history.tsx +52 -0
  426. package/blocks/surveys/components/org-summary.tsx +82 -0
  427. package/blocks/surveys/components/sending-domains.tsx +113 -0
  428. package/blocks/surveys/components/survey-form.tsx +126 -0
  429. package/blocks/surveys/components/survey-responses.tsx +145 -0
  430. package/blocks/surveys/components/survey-results.tsx +72 -0
  431. package/blocks/surveys/components/survey-send-history.tsx +58 -0
  432. package/blocks/surveys/components/survey-send.tsx +162 -0
  433. package/blocks/surveys/components/survey-triggers.tsx +166 -0
  434. package/blocks/surveys/components/surveys-screen.tsx +234 -0
  435. package/blocks/surveys/lib/surveys-types.ts +228 -0
  436. package/blocks/surveys/recipes/create-an-nps-survey.ts +22 -0
  437. package/blocks/surveys/recipes/send-a-survey-and-follow-it.ts +27 -0
  438. package/blocks/surveys/recipes/survey-score-report.ts +27 -0
  439. package/blocks/visitors/README.md +10 -0
  440. package/blocks/visitors/block.json +25 -1
  441. package/blocks/visitors/components/snippet-install.tsx +21 -10
  442. package/blocks/visitors/components/traffic-chart.tsx +4 -4
  443. package/blocks/visitors/components/visitor-company-card.tsx +26 -16
  444. package/blocks/visitors/components/visitor-detail.tsx +105 -0
  445. package/blocks/visitors/components/visitor-feed.tsx +16 -7
  446. package/blocks/visitors/components/visitors-screen.tsx +166 -0
  447. package/blocks/webchat/README.md +10 -0
  448. package/blocks/webchat/block.json +21 -7
  449. package/blocks/webchat/components/chat-widget-config.tsx +8 -5
  450. package/blocks/webchat/components/conversation-list.tsx +8 -4
  451. package/blocks/webchat/components/webchat-screen.tsx +245 -0
  452. package/blocks/workbench/README.md +11 -0
  453. package/blocks/workbench/block.json +48 -1
  454. package/blocks/workbench/components/column-recipe-editor.tsx +5 -3
  455. package/blocks/workbench/components/run-progress.tsx +1 -1
  456. package/blocks/workbench/components/workbench-grid.tsx +10 -4
  457. package/blocks/workbench/components/workbench-row-detail.tsx +104 -0
  458. package/blocks/workbench/components/workbench-screen.tsx +202 -0
  459. package/blocks/workbench/components/workbench-sources.tsx +194 -0
  460. package/blocks/workbench/components/workbench-table-list.tsx +14 -2
  461. package/blocks/workflows/README.md +13 -0
  462. package/blocks/workflows/block.json +28 -9
  463. package/blocks/workflows/components/run-history.tsx +31 -9
  464. package/blocks/workflows/components/trigger-config.tsx +3 -1
  465. package/blocks/workflows/components/workflow-editor.tsx +4 -2
  466. package/blocks/workflows/components/workflow-list.tsx +13 -6
  467. package/blocks/workflows/components/workflows-screen.tsx +193 -0
  468. package/dist/cli.js +3109 -1977
  469. package/dist/errors.d.mts +34 -0
  470. package/dist/errors.d.ts +34 -0
  471. package/dist/errors.js +46 -0
  472. package/dist/errors.js.map +1 -0
  473. package/dist/errors.mjs +21 -0
  474. package/dist/errors.mjs.map +1 -0
  475. package/dist/index.browser.js +11 -5
  476. package/dist/index.browser.js.map +1 -1
  477. package/dist/index.browser.mjs +11 -5
  478. package/dist/index.browser.mjs.map +1 -1
  479. package/dist/index.d.mts +164 -25
  480. package/dist/index.d.ts +164 -25
  481. package/dist/index.js +11 -5
  482. package/dist/index.js.map +1 -1
  483. package/dist/index.mjs +11 -5
  484. package/dist/index.mjs.map +1 -1
  485. package/dist/react.browser.js +10 -4
  486. package/dist/react.browser.js.map +1 -1
  487. package/dist/react.browser.mjs +10 -4
  488. package/dist/react.browser.mjs.map +1 -1
  489. package/dist/react.d.mts +142 -5
  490. package/dist/react.d.ts +142 -5
  491. package/dist/react.js +10 -4
  492. package/dist/react.js.map +1 -1
  493. package/dist/react.mjs +10 -4
  494. package/dist/react.mjs.map +1 -1
  495. package/dist/types/blocks/add.d.ts +11 -4
  496. package/dist/types/blocks/brand.d.ts +122 -0
  497. package/dist/types/blocks/compose.d.ts +53 -0
  498. package/dist/types/blocks/create.d.ts +27 -20
  499. package/dist/types/blocks/doctor.d.ts +6 -1
  500. package/dist/types/blocks/flows.d.ts +7 -1
  501. package/dist/types/blocks/navfile.d.ts +35 -0
  502. package/dist/types/blocks/orgBrand.d.ts +34 -0
  503. package/dist/types/blocks/paths.d.ts +4 -0
  504. package/dist/types/blocks/prefixes.d.ts +37 -0
  505. package/dist/types/blocks/registry.d.ts +17 -0
  506. package/dist/types/blocks/screens.d.ts +53 -0
  507. package/dist/types/cli.d.ts +5 -0
  508. package/dist/types/errors.d.ts +33 -0
  509. package/dist/types/http.d.ts +2 -18
  510. package/dist/types/version.d.ts +2 -2
  511. package/docs/agents.md +15 -4
  512. package/docs/api/README.md +2 -2
  513. package/docs/api/by-path.md +1 -0
  514. package/docs/api/desk.d.ts +98 -2
  515. package/docs/api/desk.md +123 -1
  516. package/docs/api/inbox.d.ts +10 -2
  517. package/docs/api/inbox.md +10 -2
  518. package/docs/api/seo.d.ts +19 -1
  519. package/docs/api/seo.md +24 -1
  520. package/package.json +16 -2
  521. package/stacks/6sense/pages/companies.tsx.tmpl +21 -0
  522. package/stacks/6sense/pages/contacts.tsx.tmpl +19 -0
  523. package/stacks/6sense/pages/tasks.tsx.tmpl +19 -0
  524. package/stacks/6sense.json +55 -17
  525. package/stacks/apollo/pages/calls.tsx.tmpl +23 -0
  526. package/stacks/apollo/pages/companies.tsx.tmpl +33 -0
  527. package/stacks/apollo/pages/contacts.tsx.tmpl +51 -0
  528. package/stacks/apollo/pages/deals.tsx.tmpl +17 -0
  529. package/stacks/apollo/pages/inbox-contact.tsx.tmpl +13 -0
  530. package/stacks/apollo/pages/lists.tsx.tmpl +12 -0
  531. package/stacks/apollo/pages/meetings.tsx.tmpl +13 -0
  532. package/stacks/apollo/pages/sequences.tsx.tmpl +12 -0
  533. package/stacks/apollo/pages/tasks.tsx.tmpl +20 -0
  534. package/stacks/apollo.json +147 -37
  535. package/stacks/calendly/pages/companies.tsx.tmpl +19 -0
  536. package/stacks/calendly/pages/contacts.tsx.tmpl +21 -0
  537. package/stacks/calendly/pages/meetings.tsx.tmpl +13 -0
  538. package/stacks/calendly/pages/tasks.tsx.tmpl +19 -0
  539. package/stacks/calendly.json +64 -0
  540. package/stacks/clay/pages/companies.tsx.tmpl +31 -0
  541. package/stacks/clay/pages/contacts.tsx.tmpl +31 -0
  542. package/stacks/clay/pages/lists.tsx.tmpl +12 -0
  543. package/stacks/clay/pages/tasks.tsx.tmpl +19 -0
  544. package/stacks/clay.json +73 -27
  545. package/stacks/gong/pages/calls.tsx.tmpl +23 -0
  546. package/stacks/gong/pages/companies.tsx.tmpl +22 -0
  547. package/stacks/gong/pages/contacts.tsx.tmpl +32 -0
  548. package/stacks/gong/pages/lists.tsx.tmpl +12 -0
  549. package/stacks/gong/pages/meetings.tsx.tmpl +13 -0
  550. package/stacks/gong/pages/tasks.tsx.tmpl +19 -0
  551. package/stacks/gong.json +98 -35
  552. package/stacks/hootsuite/pages/companies.tsx.tmpl +22 -0
  553. package/stacks/hootsuite/pages/contacts.tsx.tmpl +28 -0
  554. package/stacks/hootsuite/pages/lists.tsx.tmpl +12 -0
  555. package/stacks/hootsuite/pages/tasks.tsx.tmpl +19 -0
  556. package/stacks/hootsuite.json +104 -0
  557. package/stacks/hubspot/pages/companies.tsx.tmpl +26 -0
  558. package/stacks/hubspot/pages/contacts.tsx.tmpl +45 -0
  559. package/stacks/hubspot/pages/deals.tsx.tmpl +20 -0
  560. package/stacks/hubspot/pages/inbox.tsx.tmpl +103 -0
  561. package/stacks/hubspot/pages/lifecycle.tsx.tmpl +23 -0
  562. package/stacks/hubspot/pages/lists.tsx.tmpl +12 -0
  563. package/stacks/hubspot/pages/meetings.tsx.tmpl +13 -0
  564. package/stacks/hubspot/pages/quotes.tsx.tmpl +11 -0
  565. package/stacks/hubspot/pages/sequences.tsx.tmpl +12 -0
  566. package/stacks/hubspot/pages/tasks.tsx.tmpl +20 -0
  567. package/stacks/hubspot.json +181 -64
  568. package/stacks/intercom/pages/companies.tsx.tmpl +19 -0
  569. package/stacks/intercom/pages/contacts.tsx.tmpl +21 -0
  570. package/stacks/intercom/pages/inbox-contact.tsx.tmpl +13 -0
  571. package/stacks/intercom/pages/tasks.tsx.tmpl +19 -0
  572. package/stacks/intercom.json +52 -20
  573. package/stacks/mailchimp/pages/companies.tsx.tmpl +22 -0
  574. package/stacks/mailchimp/pages/contacts.tsx.tmpl +28 -0
  575. package/stacks/mailchimp/pages/lists.tsx.tmpl +12 -0
  576. package/stacks/mailchimp/pages/tasks.tsx.tmpl +19 -0
  577. package/stacks/mailchimp.json +68 -34
  578. package/stacks/outreach/pages/calls.tsx.tmpl +23 -0
  579. package/stacks/outreach/pages/companies.tsx.tmpl +22 -0
  580. package/stacks/outreach/pages/contacts.tsx.tmpl +46 -0
  581. package/stacks/outreach/pages/inbox-contact.tsx.tmpl +13 -0
  582. package/stacks/outreach/pages/lists.tsx.tmpl +12 -0
  583. package/stacks/outreach/pages/meetings.tsx.tmpl +13 -0
  584. package/stacks/outreach/pages/sequences.tsx.tmpl +12 -0
  585. package/stacks/outreach/pages/tasks.tsx.tmpl +19 -0
  586. package/stacks/outreach.json +106 -25
  587. package/stacks/pipedrive/pages/companies.tsx.tmpl +23 -0
  588. package/stacks/pipedrive/pages/contacts.tsx.tmpl +27 -0
  589. package/stacks/pipedrive/pages/deals.tsx.tmpl +20 -0
  590. package/stacks/pipedrive/pages/inbox.tsx.tmpl +103 -0
  591. package/stacks/pipedrive/pages/meetings.tsx.tmpl +13 -0
  592. package/stacks/pipedrive/pages/quotes.tsx.tmpl +11 -0
  593. package/stacks/pipedrive/pages/tasks.tsx.tmpl +20 -0
  594. package/stacks/pipedrive.json +117 -0
  595. package/stacks/salesforce/pages/companies.tsx.tmpl +26 -0
  596. package/stacks/salesforce/pages/contacts.tsx.tmpl +32 -0
  597. package/stacks/salesforce/pages/deals.tsx.tmpl +20 -0
  598. package/stacks/salesforce/pages/lifecycle.tsx.tmpl +23 -0
  599. package/stacks/salesforce/pages/lists.tsx.tmpl +12 -0
  600. package/stacks/salesforce/pages/quotes.tsx.tmpl +11 -0
  601. package/stacks/salesforce/pages/tasks.tsx.tmpl +20 -0
  602. package/stacks/salesforce.json +85 -31
  603. package/stacks/zoominfo/pages/companies.tsx.tmpl +31 -0
  604. package/stacks/zoominfo/pages/contacts.tsx.tmpl +31 -0
  605. package/stacks/zoominfo/pages/lists.tsx.tmpl +12 -0
  606. package/stacks/zoominfo/pages/tasks.tsx.tmpl +19 -0
  607. package/stacks/zoominfo.json +115 -0
  608. package/styles/styles.css +1 -1
  609. package/templates/next-app/README.md.tmpl +40 -9
  610. package/templates/next-app/app/globals.css.tmpl +349 -64
  611. package/templates/next-app/app/layout.tsx.tmpl +7 -2
  612. package/templates/next-app/components/app-shell.tsx.tmpl +104 -88
  613. package/templates/next-app/components/shell/quick-jump.tsx.tmpl +4 -0
  614. package/templates/next-app/dot-gitignore.tmpl +2 -0
  615. package/templates/next-app/package.json.tmpl +1 -1
@@ -27,6 +27,7 @@ import { listOf, mentionLabel, summariseReply } from "../lib/copilot-types";
27
27
  import type { ChatTurn, CopilotReply, MentionHit } from "../lib/copilot-types";
28
28
  import { CopilotMemory } from "./copilot-memory";
29
29
  import { CopilotTeamChat } from "./copilot-team-chat";
30
+ import { useBrand } from "@/g8/hooks/use-brand";
30
31
 
31
32
  export interface CopilotPanelProps {
32
33
  /** Where the copilot is being asked from; passed as `canvas_context`. */
@@ -35,6 +36,10 @@ export interface CopilotPanelProps {
35
36
  initialTab?: "ask" | "team" | "memory";
36
37
  /** Ask for confirmation before every message instead of once per session. */
37
38
  confirmEveryMessage?: boolean;
39
+ /** Hide the Ask / Team / Memory tab bar when the host (for example CopilotScreen) provides its own navigation. */
40
+ hideTabs?: boolean;
41
+ /** Example questions shown as buttons in the empty conversation; clicking one fills the message box. */
42
+ starterPrompts?: string[];
38
43
  className?: string;
39
44
  }
40
45
 
@@ -47,7 +52,8 @@ const mentionsIn = (message: string, list: MentionHit[]): MentionHit[] | undefin
47
52
  };
48
53
  const MENTION_AT_END = /(^|\s)@([\w.-]{1,40})$/;
49
54
 
50
- export function CopilotPanel({ context, initialTab = "ask", confirmEveryMessage = false, className }: CopilotPanelProps) {
55
+ export function CopilotPanel({ context, initialTab = "ask", confirmEveryMessage = false, hideTabs = false, starterPrompts, className }: CopilotPanelProps) {
56
+ const brand = useBrand();
51
57
  const [tab, setTab] = useState<Tab>(initialTab);
52
58
  const [turns, setTurns] = useState<ChatTurn[]>([]);
53
59
  const [draft, setDraft] = useState("");
@@ -129,22 +135,25 @@ export function CopilotPanel({ context, initialTab = "ask", confirmEveryMessage
129
135
 
130
136
  return (
131
137
  <div className={`flex h-full min-h-[24rem] flex-col gap-3 ${className ?? ""}`}>
132
- <div role="tablist" className="flex gap-1 border-b">
138
+ {hideTabs ? null : <div role="tablist" className="flex gap-1 border-b">
133
139
  {TABS.map((t) => (
134
140
  <button key={t.id} role="tab" type="button" aria-selected={tab === t.id} onClick={() => setTab(t.id)}
135
141
  className={`px-3 py-2 text-sm ${tab === t.id ? "border-b-2 border-primary font-medium" : "text-muted-foreground"}`}>{t.label}</button>
136
142
  ))}
137
- </div>
143
+ </div>}
138
144
 
139
145
  {tab === "ask" ? (
140
146
  <>
141
147
  <div className="flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto" aria-live="polite" data-testid="transcript">
142
- {turns.length === 0 ? <EmptyState title="Ask the copilot" description="It can look things up, draft copy and propose changes. Type @ to mention a campaign, document or teammate." /> : null}
148
+ {turns.length === 0 ? (
149
+ <EmptyState title="Ask the copilot" description="It can look things up, draft copy and propose changes. Type @ to mention a campaign, document or teammate."
150
+ action={starterPrompts?.length ? <div className="flex flex-wrap justify-center gap-2">{starterPrompts.map((p) => <Button key={p} size="sm" variant="outline" onClick={() => setDraft(p)}>{p}</Button>)}</div> : undefined} />
151
+ ) : null}
143
152
  {turns.map((t) => (
144
153
  <div key={t.id} data-testid={`turn-${t.role}`} className={`max-w-[85%] rounded-lg px-3 py-2 text-sm ${t.role === "user" ? "self-end bg-primary text-primary-foreground" : t.error ? "self-start border border-destructive" : "self-start bg-muted"}`}>
145
154
  <p className="whitespace-pre-wrap">{t.text}</p>
146
155
  {t.tools?.length ? <p className="mt-1 text-xs opacity-70">Used: {t.tools.join(", ")}</p> : null}
147
- {t.needsApproval?.length ? <p className="mt-1 text-xs text-amber-700">Needs your approval in graph8 before it runs: {t.needsApproval.join(", ")}</p> : null}
156
+ {t.needsApproval?.length ? <p className="mt-1 text-xs text-warning-foreground">Needs your approval in {brand.linkLabel} before it runs: {t.needsApproval.join(", ")}</p> : null}
148
157
  {t.sources ? <p className="mt-1 text-xs opacity-70">{t.sources} sources</p> : null}
149
158
  </div>
150
159
  ))}
@@ -0,0 +1,148 @@
1
+ "use client";
2
+
3
+ /**
4
+ * CopilotScreen: the graph8 copilot as a full page. Three tabs.
5
+ * Ask: the conversation (CopilotPanel without its own tabs), starter questions, an "Ask about" card that points the
6
+ * copilot at the whole workspace, one campaign or one account, and a "What it can do" card listing its tools and
7
+ * which need a person's approval in graph8.
8
+ * Team: every Work channel the key can read as a list; opening one (deep link ?id=) shows the whole thread: its details
9
+ * and the polled conversation with "ask an agent" and a message box (CopilotTeamChat).
10
+ * Memory: what the copilot remembers, add / forget (CopilotMemory).
11
+ * The Ask conversation stays alive while you visit other tabs.
12
+ * The first message of a session asks to confirm credits (billable) inside CopilotPanel; forgetting a memory and
13
+ * posting to an agent are confirmed in their parts.
14
+ *
15
+ * SDK operations of its own:
16
+ * 1. GET /copilot/tools (copilot.listCopilotTools) read the "What it can do" card
17
+ * Everything else is CopilotPanel / CopilotTeamChat / CopilotMemory (chat, mention search, work channels and
18
+ * messages, memories). Slot props: toolbarActions, sidebarExtra.
19
+ */
20
+ import { useState, type ReactNode } from "react";
21
+ import { Sparkles } from "lucide-react";
22
+ import { Input, Label, Skeleton } from "@graph8/sdk/ui";
23
+ import { EmptyState } from "@/g8/components/empty-state";
24
+ import { DetailPanel } from "@/g8/components/screen/detail-panel";
25
+ import { KeyValueList } from "@/g8/components/screen/key-value-list";
26
+ import { SplitView } from "@/g8/components/screen/split-view";
27
+ import { ApiError } from "@/g8/components/api-error";
28
+ import { useG8Query } from "@/g8/hooks/use-g8-query";
29
+ import { g8Get } from "@/g8/lib/g8-client";
30
+ import { ScreenLayout } from "@/g8/components/screen/screen-layout";
31
+ import { SectionCard } from "@/g8/components/screen/section-card";
32
+ import { StatusPill } from "@/g8/components/screen/status-pill";
33
+ import { useUrlState } from "@/g8/hooks/use-url-state";
34
+ import { listOf } from "../lib/copilot-types";
35
+ import type { ToolRow } from "../lib/copilot-types";
36
+ import { CopilotMemory } from "./copilot-memory";
37
+ import { CopilotPanel } from "./copilot-panel";
38
+ import { CopilotTeamChat } from "./copilot-team-chat";
39
+ import type { WorkChannel } from "../lib/copilot-types";
40
+ import { useBrand } from "@/g8/hooks/use-brand";
41
+
42
+ export interface CopilotScreenProps {
43
+ /** Starter questions shown in the empty conversation. */
44
+ starterPrompts?: string[];
45
+ /** Start with the copilot pointed at this campaign or account. */
46
+ initialContext?: { mode: "global" | "campaign" | "account"; id?: string };
47
+ toolbarActions?: ReactNode;
48
+ sidebarExtra?: ReactNode;
49
+ className?: string;
50
+ }
51
+
52
+ const TABS = [{ id: "ask", label: "Ask" }, { id: "team", label: "Team" }, { id: "memory", label: "Memory" }];
53
+ const MODES = [{ id: "global", label: "Everything" }, { id: "campaign", label: "One campaign" }, { id: "account", label: "One account" }] as const;
54
+ const STARTERS = ["Summarise how outbound is doing this month", "Draft a follow-up for a prospect who went quiet", "Which of my campaigns needs attention?"];
55
+
56
+ function ToolsCard() {
57
+ const tools = useG8Query((signal) => g8Get("/copilot/tools", undefined, { signal }), []);
58
+ const rows = listOf<ToolRow>(tools.data, "items");
59
+ const gated = rows.filter((t) => t.requires_approval || t.needs_approval);
60
+ return (
61
+ <SectionCard title="What it can do" description={rows.length ? `${rows.length} tools, ${gated.length} need your approval` : undefined}>
62
+ {tools.error ? <ApiError error={tools.error} title="Could not load tools" onRetry={() => void tools.refetch()} /> : null}
63
+ {tools.loading && rows.length === 0 ? <Skeleton className="h-16 w-full" /> : null}
64
+ <ul className="max-h-64 space-y-2 overflow-y-auto" data-testid="tools">
65
+ {rows.map((t) => (
66
+ <li key={t.name} className="flex items-start justify-between gap-2 text-sm">
67
+ <span><span className="font-medium">{t.name}</span>{t.description ? <span className="block text-xs text-muted-foreground">{t.description}</span> : null}</span>
68
+ {t.requires_approval || t.needs_approval ? <StatusPill tone="warning">needs approval</StatusPill> : null}
69
+ </li>
70
+ ))}
71
+ </ul>
72
+ </SectionCard>
73
+ );
74
+ }
75
+
76
+ function TeamPane() {
77
+ const [selected, setSelected] = useUrlState("id", "");
78
+ const [view, setView] = useUrlState("view", "");
79
+ const close = () => { setSelected(""); setView(""); };
80
+ const channels = useG8Query((signal) => g8Get("/work/channels", undefined, { signal }), []);
81
+ const rows = listOf<WorkChannel>(channels.data, "channels");
82
+ const open = rows.find((c) => c.id === selected);
83
+ const label = (c: WorkChannel) => c.displayName ?? c.name ?? c.id ?? "Channel";
84
+ const list = (
85
+ <div className="flex flex-col gap-2">
86
+ {channels.error ? <ApiError error={channels.error} title="Could not load channels" onRetry={() => void channels.refetch()} /> : null}
87
+ {channels.loading && rows.length === 0 ? <Skeleton className="h-14 w-full" /> : null}
88
+ <ul className="rounded-md border" data-testid="channels">
89
+ {rows.map((c) => (
90
+ <li key={c.id} className={c.id === selected ? "bg-accent" : ""}>
91
+ <button type="button" data-testid={`channel-${c.id}`} onClick={() => setSelected(c.id ?? "")} className="block w-full border-b px-3 py-2 text-left">
92
+ <span className="block truncate text-sm font-medium">{label(c)}</span>
93
+ {c.description ? <span className="block truncate text-xs text-muted-foreground">{c.description}</span> : null}
94
+ </button>
95
+ </li>
96
+ ))}
97
+ </ul>
98
+ {!channels.loading && !channels.error && rows.length === 0 ? <EmptyState title="No channels" description="Work channels this key may read show up here." /> : null}
99
+ </div>
100
+ );
101
+ const detail = open ? (
102
+ <DetailPanel title={label(open)} subtitle={open.kind} onClose={close} onExpand={() => setView("full")}
103
+ tabs={[
104
+ { id: "conversation", label: "Conversation", content: <CopilotTeamChat key={open.id} channelId={open.id} hideChannelPicker /> },
105
+ { id: "details", label: "Details", content: <KeyValueList columns={2} items={[{ label: "Name", value: label(open) }, { label: "Kind", value: open.kind }, { label: "Purpose", value: open.description, wide: true }, { label: "Channel id", value: open.id, mono: true }]} /> },
106
+ ]} />
107
+ ) : selected && !channels.loading ? <EmptyState title="Channel not found" description="This key may not have a seat in it." /> : null;
108
+ return <SplitView list={list} detail={detail} detailOpen={Boolean(selected)} onCloseDetail={close} expanded={view === "full"} onExpandedChange={(e) => setView(e ? "full" : "")} detailWidth="xl" />;
109
+ }
110
+
111
+ export function CopilotScreen({ starterPrompts = STARTERS, initialContext, toolbarActions, sidebarExtra, className }: CopilotScreenProps) {
112
+ const brand = useBrand();
113
+ const [tab, setTab] = useUrlState("tab", "ask");
114
+ const [mode, setMode] = useState<"global" | "campaign" | "account">(initialContext?.mode ?? "global");
115
+ const [refId, setRefId] = useState(initialContext?.id ?? "");
116
+ // The id applies on blur or Enter, so typing does not restart the conversation on every keystroke.
117
+ const [refDraft, setRefDraft] = useState(initialContext?.id ?? "");
118
+ const current = TABS.some((t) => t.id === tab) ? tab : "ask";
119
+ const id = refId.trim() || null;
120
+ const context = { mode, campaignId: mode === "campaign" ? id : null, accountId: mode === "account" ? id : null };
121
+
122
+ return (
123
+ <ScreenLayout className={className} title="Copilot" description={`Ask ${brand.linkLabel} anything about your pipeline, draft with it, and decide what it remembers.`}
124
+ icon={<Sparkles className="size-5" />} tabs={TABS} activeTab={current}
125
+ onTabChange={setTab} actions={toolbarActions}>
126
+ <div className={current === "ask" ? "grid gap-4 lg:grid-cols-[minmax(0,2fr)_minmax(0,1fr)]" : "hidden"}>
127
+ {/* Keyed on the context so a changed target starts a fresh conversation instead of mixing subjects. */}
128
+ <CopilotPanel key={`${mode}:${id ?? ""}`} hideTabs initialTab="ask" context={context} starterPrompts={starterPrompts} className="min-h-[32rem] rounded-lg border p-3" />
129
+ <div className="space-y-4">
130
+ <SectionCard title="Ask about" description="Changing this starts a new conversation.">
131
+ <div role="group" aria-label="Ask about" className="flex flex-col gap-2">
132
+ <select aria-label="Subject" className="h-9 rounded-md border bg-background px-2 text-sm" value={mode} onChange={(e) => { setMode(e.target.value as typeof mode); setRefDraft(""); setRefId(""); }}>
133
+ {MODES.map((m) => <option key={m.id} value={m.id}>{m.label}</option>)}
134
+ </select>
135
+ {mode !== "global" ? (
136
+ <div className="flex flex-col gap-1"><Label htmlFor="cp-ref">{mode === "campaign" ? "Campaign id" : "Account id"}</Label><Input id="cp-ref" value={refDraft} onChange={(e) => setRefDraft(e.target.value)} onBlur={() => setRefId(refDraft)} onKeyDown={(e) => { if (e.key === "Enter") setRefId(refDraft); }} /></div>
137
+ ) : null}
138
+ </div>
139
+ </SectionCard>
140
+ <ToolsCard />
141
+ {sidebarExtra}
142
+ </div>
143
+ </div>
144
+ {current === "team" ? <TeamPane /> : null}
145
+ {current === "memory" ? <CopilotMemory /> : null}
146
+ </ScreenLayout>
147
+ );
148
+ }
@@ -19,6 +19,7 @@
19
19
  import { useEffect, useRef, useState } from "react";
20
20
  import { Button, Input } from "@graph8/sdk/ui";
21
21
  import { ApiError } from "@/g8/components/api-error";
22
+ import { FirstNotice } from "@/g8/components/paging-notices";
22
23
  import { ConfirmSpendDialog } from "@/g8/components/confirm-spend-dialog";
23
24
  import { EmptyState } from "@/g8/components/empty-state";
24
25
  import { useG8Mutation } from "@/g8/hooks/use-g8-mutation";
@@ -33,6 +34,8 @@ export interface CopilotTeamChatProps {
33
34
  channelId?: string;
34
35
  /** Poll interval in ms. Default 4000. */
35
36
  pollMs?: number;
37
+ /** Hide the channel picker when the host (for example CopilotScreen) already chose the channel. */
38
+ hideChannelPicker?: boolean;
36
39
  className?: string;
37
40
  }
38
41
 
@@ -41,15 +44,18 @@ interface Page { conversation_id?: string; messages?: WorkMessageRow[] }
41
44
 
42
45
  const newKey = (): string => `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
43
46
 
44
- export function CopilotTeamChat({ channelId, pollMs = 4000, className }: CopilotTeamChatProps) {
47
+ /** The agents roster read has no paging here: a full read is announced under the composer. */
48
+ const AGENT_LIMIT = 50;
49
+
50
+ export function CopilotTeamChat({ channelId, pollMs = 4000, hideChannelPicker, className }: CopilotTeamChatProps) {
45
51
  const [channel, setChannel] = useState<string | undefined>(channelId);
46
52
  const [text, setText] = useState("");
47
53
  const [agentId, setAgentId] = useState("");
48
54
  const [confirming, setConfirming] = useState(false);
49
55
  const draftKey = useRef(newKey());
50
56
 
51
- const channels = useG8Query((signal) => g8Get("/work/channels", undefined, { signal }), []);
52
- const agents = useG8Query((signal) => g8Get("/work/agents", { limit: 50 }, { signal }), []);
57
+ const channels = useG8Query((signal) => g8Get("/work/channels", undefined, { signal }), [], { enabled: !(hideChannelPicker && channelId) });
58
+ const agents = useG8Query((signal) => g8Get("/work/agents", { limit: AGENT_LIMIT }, { signal }), []);
53
59
  const rows = listOf<WorkChannel>(channels.data, "channels");
54
60
  const roster = listOf<AgentRow>(agents.data, "items");
55
61
  const active = channel ?? rows[0]?.id ?? undefined;
@@ -73,10 +79,10 @@ export function CopilotTeamChat({ channelId, pollMs = 4000, className }: Copilot
73
79
  return (
74
80
  <div className={`flex min-h-0 flex-1 flex-col gap-3 ${className ?? ""}`}>
75
81
  {channels.error ? <ApiError error={channels.error} title="Could not load channels" onRetry={() => void channels.refetch()} /> : null}
76
- <select aria-label="Channel" className="h-9 rounded-md border bg-background px-2 text-sm" value={active ?? ""} onChange={(e) => setChannel(e.target.value)}>
82
+ {hideChannelPicker ? null : <select aria-label="Channel" className="h-9 rounded-md border bg-background px-2 text-sm" value={active ?? ""} onChange={(e) => setChannel(e.target.value)}>
77
83
  {rows.map((c) => <option key={c.id} value={c.id}>{c.displayName ?? c.name ?? c.id}</option>)}
78
- </select>
79
- {!channels.loading && !channels.error && rows.length === 0 ? <EmptyState title="No channels" description="Work channels this key may read show up here." /> : null}
84
+ </select>}
85
+ {!hideChannelPicker && !channels.loading && !channels.error && rows.length === 0 ? <EmptyState title="No channels" description="Work channels this key may read show up here." /> : null}
80
86
 
81
87
  {active ? (
82
88
  <>
@@ -101,6 +107,7 @@ export function CopilotTeamChat({ channelId, pollMs = 4000, className }: Copilot
101
107
  onKeyDown={(e) => { if (e.key === "Enter" && text.trim() && !post.loading) submit(); }} />
102
108
  <Button loading={post.loading} disabled={!text.trim()} onClick={submit}>Post</Button>
103
109
  </div>
110
+ <FirstNotice shown={roster.length} limit={AGENT_LIMIT} noun="agents" />
104
111
  </>
105
112
  ) : null}
106
113
 
@@ -7,6 +7,28 @@ list, the dialer opens a `ContactDetail`), so their props are part of the contra
7
7
 
8
8
  Install: `npx @graph8/sdk add crm` (installs `foundation` first).
9
9
 
10
+ ## Screens
11
+
12
+ Three finished screens compose the parts below into complete workspaces. Each needs no props, deep-links the open record
13
+ (`?id=`), and takes optional slot props so other blocks can add buttons and tabs.
14
+
15
+ | Screen | What a person can do | Slots |
16
+ |---|---|---|
17
+ | `ContactsScreen` | Search and filter (name, title, seniority, country), sort the loaded page, paginate, open a contact (timeline, notes, tasks, fields), create, edit, delete one or many, import a CSV/Excel file, review and merge duplicates. Locked emails show as Locked. | `renderRowActions(row, { reload })`, `renderDetailActions(contact, { reload })` (`reload` refetches the list and the open record, keeping filters, page, sort and selection), `extraDetailTabs`, `toolbarActions`, `renderBulkActions`, `onOpenCompany`, `listId` |
18
+ | `CompaniesScreen` | Same flow for accounts: filters (name, domain, industry, country), detail with People, Activity, Notes, Tasks, create (domain required), edit, delete, duplicate review. | `renderRowActions(row, { reload })`, `renderDetailActions(company, { reload })`, `extraDetailTabs`, `toolbarActions`, `renderBulkActions`, `onOpenContact` |
19
+ | `TasksScreen` | The workspace-wide task queue: Open / Completed / All, search, priority / type / linked-record filters, tick to complete or reopen, create, edit, delete, bulk complete and delete, overdue marker. | `renderRowActions`, `renderDetailActions`, `toolbarActions`, `defaultRecord`, `onOpenRecord` |
20
+
21
+ ```tsx
22
+ "use client";
23
+ import { ContactsScreen } from "@/components/g8/crm/contacts-screen";
24
+ export default function Page() { return <ContactsScreen />; }
25
+ ```
26
+
27
+ Prerequisites are the block's own (proxy allow-list including `tasks`, scopes in `block.json`). Sorting works on the loaded page only
28
+ (the API has no sort). Deleting (rows, panel, bulk) and merging always ask first. `TasksScreen` links new tasks to a record only when you
29
+ pass `defaultRecord`; otherwise they are standalone. Company import does not exist in the API: importing contacts creates their
30
+ companies from the domain.
31
+
10
32
  ## What you get
11
33
 
12
34
  | Component | Use it for | Embed props |
@@ -73,6 +95,11 @@ message to a person.
73
95
  - `api-key-scopes` (api): the server key has the scopes in `block.json` (`contacts:delete` is needed for bulk merge).
74
96
  - `import-size-limit` (app): the proxy caps bodies at 5 MiB; larger files need a raised cap or a server-side import.
75
97
 
98
+ ## Known limits
99
+
100
+ - The tasks "Low" priority filter sends `priority=3`. `GET /tasks` takes a single priority value, so historical
101
+ tasks stored as `4` (also Low) are not matched by that filter; they still show as Low in the list.
102
+
76
103
  ## Defaults the agent can use without asking
77
104
 
78
105
  | Decision | Default |
@@ -119,4 +146,11 @@ Ask the person: who may delete or merge records (decide it in the proxy's `autho
119
146
  | duplicateCounts / listDuplicates / listRecentMerges / getBulkMergeStatus | GET /duplicates... | read | DedupeReview |
120
147
  | rejectSuggestion / startBulkMerge / undoMerge | POST /duplicates... | write | DedupeReview |
121
148
  | mergeContact / mergeCompany | POST /contacts/{id}/merge, /companies/{id}/merge | destructive | DedupeReview |
149
+ | listAllTasks / getTask / createGlobalTask | GET /tasks, GET /tasks/{task_id}, POST /tasks | read / read / write | TasksScreen |
122
150
  | assertContact, assertCompany (+ batch) | PUT /contacts/assert, /companies/assert | write | recipes (`g8.contacts.upsert`) |
151
+
152
+ ## Cross-block glue
153
+
154
+ - `ContactLookupLink` (`components/contact-lookup-link.tsx`): "Open contact" for something that only knows an email (an inbox thread, a meeting attendee). It looks the email up (`GET /contacts?email=`) and shows a button only when a contact has it; `onOpen(contactId)` routes to your contacts screen. `ContactsScreen.onOpenCompany`, `CompaniesScreen.onOpenContact` and `TasksScreen.onOpenRecord` are the other ends of the same links: the stack pages pass them (`router.push("/companies?id=...")`).
155
+
156
+ - `RecordEngagementTab` (`components/record-engagement-tab.tsx`): engagement counts, last touch (contacts) and pages visited for a contact or company, an `extraDetailTabs` entry: `{ id: "engagement", label: "Engagement", render: (c) => <RecordEngagementTab kind="contacts" id={c.id} /> }`. Reads `getContactEngagementSummary` / `getCompanyEngagementSummary` and `getContactSitesVisited` / `getCompanySitesVisited`. Also: the contact subtitle is `contactSubtitle(contact)` ("VP of Sales at Acme"; the company is never the person's own name, and "at" is left out without a company).
@@ -9,7 +9,8 @@
9
9
  "create/edit form that renders the org's custom fields",
10
10
  "CSV/Excel import wizard with column mapping and preview",
11
11
  "duplicate review with merge, bulk merge and undo",
12
- "locked (masked) emails and phones shown as Locked, never as values"
12
+ "locked (masked) emails and phones shown as Locked, never as values",
13
+ "finished ContactsScreen, CompaniesScreen and TasksScreen (list, detail, create, edit, delete, import, duplicates)"
13
14
  ],
14
15
  "dependsOn": [
15
16
  "foundation"
@@ -24,6 +25,7 @@
24
25
  "create_company_task_companies__company_id__tasks_post",
25
26
  "create_contacts_contacts_post",
26
27
  "create_field_fields_post",
28
+ "create_global_task_tasks_post",
27
29
  "create_list_lists_post",
28
30
  "create_note_contacts__contact_id__notes_post",
29
31
  "create_task_contacts__contact_id__tasks_post",
@@ -35,8 +37,14 @@
35
37
  "get_activity_feed_activity_feed_get",
36
38
  "get_bulk_merge_status_duplicates_bulk_merge__run_id__get",
37
39
  "get_company_companies__company_id__get",
40
+ "get_company_engagement_summary_companies__company_id__engagement_summary_get",
41
+ "get_company_sites_visited_companies__company_id__sites_visited_get",
38
42
  "get_contact_contacts__contact_id__get",
43
+ "get_contact_engagement_summary_contacts__contact_id__engagement_summary_get",
44
+ "get_contact_sites_visited_contacts__contact_id__sites_visited_get",
45
+ "get_task_tasks__task_id__get",
39
46
  "import_contacts_imports__import_id__contacts_post",
47
+ "list_all_tasks_tasks_get",
40
48
  "list_companies_companies_get",
41
49
  "list_company_fields_fields_companies_get",
42
50
  "list_company_notes_companies__company_id__notes_get",
@@ -256,6 +264,89 @@
256
264
  "write",
257
265
  "destructive"
258
266
  ]
267
+ },
268
+ {
269
+ "name": "ContactsScreen",
270
+ "file": "components/contacts-screen.tsx",
271
+ "purpose": "Finished contacts workspace: search, filters, sort, paging, bulk delete, detail panel with activity/notes/tasks, create, edit, CSV import and duplicate review. No required props; slot props for other blocks.",
272
+ "operations": [
273
+ "delete_contact_contacts__contact_id__delete",
274
+ "duplicate_counts_duplicates_counts_get",
275
+ "get_contact_contacts__contact_id__get",
276
+ "list_contacts_contacts_get"
277
+ ],
278
+ "tiers": [
279
+ "read",
280
+ "destructive"
281
+ ]
282
+ },
283
+ {
284
+ "name": "CompaniesScreen",
285
+ "file": "components/companies-screen.tsx",
286
+ "purpose": "Finished companies workspace: search, filters, sort, paging, bulk delete, detail panel with people/activity/notes/tasks, create, edit and duplicate review. No required props.",
287
+ "operations": [
288
+ "delete_company_companies__company_id__delete",
289
+ "duplicate_counts_duplicates_counts_get",
290
+ "get_company_companies__company_id__get",
291
+ "list_companies_companies_get"
292
+ ],
293
+ "tiers": [
294
+ "read",
295
+ "destructive"
296
+ ]
297
+ },
298
+ {
299
+ "name": "TasksScreen",
300
+ "file": "components/tasks-screen.tsx",
301
+ "purpose": "Workspace-wide task queue: Open/Completed/All, search and filters, complete or reopen, create, edit, delete, bulk complete and delete, detail panel.",
302
+ "operations": [
303
+ "create_global_task_tasks_post",
304
+ "delete_task_tasks__task_id__delete",
305
+ "get_task_tasks__task_id__get",
306
+ "list_all_tasks_tasks_get",
307
+ "update_task_tasks__task_id__patch"
308
+ ],
309
+ "tiers": [
310
+ "read",
311
+ "write",
312
+ "destructive"
313
+ ]
314
+ },
315
+ {
316
+ "name": "ListSelect",
317
+ "file": "components/list-select.tsx",
318
+ "purpose": "Audience-list dropdown, searchable and paged (the foundation ListSelect with GET /lists wired in). Replaces a select fed by one capped list read.",
319
+ "operations": [
320
+ "list_lists_lists_get"
321
+ ],
322
+ "tiers": [
323
+ "read"
324
+ ]
325
+ },
326
+ {
327
+ "name": "ContactLookupLink",
328
+ "file": "components/contact-lookup-link.tsx",
329
+ "purpose": "\"Open contact\" button for something that only knows an email (inbox thread, meeting attendee, visitor): looks the email up in the CRM and calls onOpen(contactId); renders nothing when nobody has it.",
330
+ "operations": [
331
+ "list_contacts_contacts_get"
332
+ ],
333
+ "tiers": [
334
+ "read"
335
+ ]
336
+ },
337
+ {
338
+ "name": "RecordEngagementTab",
339
+ "file": "components/record-engagement-tab.tsx",
340
+ "purpose": "Engagement counts, last touch and pages visited for one contact or company; an extraDetailTabs entry for ContactsScreen and CompaniesScreen.",
341
+ "operations": [
342
+ "get_contact_engagement_summary_contacts__contact_id__engagement_summary_get",
343
+ "get_company_engagement_summary_companies__company_id__engagement_summary_get",
344
+ "get_contact_sites_visited_contacts__contact_id__sites_visited_get",
345
+ "get_company_sites_visited_companies__company_id__sites_visited_get"
346
+ ],
347
+ "tiers": [
348
+ "read"
349
+ ]
259
350
  }
260
351
  ],
261
352
  "hooks": [
@@ -277,12 +368,25 @@
277
368
  "list_contact_fields_fields_get",
278
369
  "list_company_fields_fields_companies_get"
279
370
  ]
371
+ },
372
+ {
373
+ "name": "useAllLists",
374
+ "file": "hooks/use-all-lists.ts",
375
+ "purpose": "Every list, page after page, for lookups by id (a list's size or name); ListSelect is the picker."
280
376
  }
281
377
  ],
282
378
  "lib": [
283
379
  {
284
380
  "file": "lib/crm-types.ts",
285
381
  "purpose": "Record and field types plus helpers (isMasked, contactName, isCustomField) shared by the CRM components."
382
+ },
383
+ {
384
+ "file": "lib/screen-parts.tsx",
385
+ "purpose": "Sorting, row selection, bulk delete and pager shared by ContactsScreen, CompaniesScreen and TasksScreen."
386
+ },
387
+ {
388
+ "file": "lib/read-lists.ts",
389
+ "purpose": "One page of audience lists (GET /lists), the read behind ListSelect and useAllLists."
286
390
  }
287
391
  ],
288
392
  "recipes": [
@@ -373,6 +477,7 @@
373
477
  }
374
478
  ],
375
479
  "peerDependencies": {
376
- "react": ">=18"
480
+ "react": ">=18",
481
+ "lucide-react": ">=0.400.0"
377
482
  }
378
483
  }