makersclaw 0.7.0 → 0.8.1

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 (419) hide show
  1. package/README.md +17 -4
  2. package/package.json +1 -1
  3. package/r/activity-log.json +52 -0
  4. package/r/agent-changes.json +51 -0
  5. package/r/agent-chat.json +53 -0
  6. package/r/agent-column.json +85 -0
  7. package/r/agent-dock.json +57 -0
  8. package/r/agent-kit.json +49 -0
  9. package/r/agent-marks.json +49 -0
  10. package/r/agent-pane.json +93 -0
  11. package/r/ai-action.json +56 -0
  12. package/r/annotate.json +4 -4
  13. package/r/approval-request.json +2 -2
  14. package/r/approval.json +54 -0
  15. package/r/ask-bar.json +50 -0
  16. package/r/audio-player.json +2 -2
  17. package/r/auth-form.json +2 -2
  18. package/r/automation-editor.json +66 -0
  19. package/r/automation-list.json +57 -0
  20. package/r/automation-model.json +118 -0
  21. package/r/automations-screen.json +71 -0
  22. package/r/board.json +2 -2
  23. package/r/calendar-view.json +3 -3
  24. package/r/cart.json +2 -2
  25. package/r/chart.json +5 -5
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +3 -3
  28. package/r/code-editor.json +2 -2
  29. package/r/comment-box.json +3 -3
  30. package/r/connect-card.json +51 -0
  31. package/r/contact-section.json +2 -2
  32. package/r/core.json +18 -6
  33. package/r/cost.json +51 -0
  34. package/r/csv-import.json +3 -3
  35. package/r/data-picker.json +60 -0
  36. package/r/data-table.json +2 -2
  37. package/r/diagram.json +2 -2
  38. package/r/doc-editor.json +2 -2
  39. package/r/doc-page.json +3 -3
  40. package/r/email-render.json +2 -2
  41. package/r/faq.json +2 -2
  42. package/r/file-upload.json +2 -2
  43. package/r/first-run.json +63 -0
  44. package/r/fix-note.json +57 -0
  45. package/r/flow-canvas.json +3 -3
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +3 -3
  48. package/r/gantt.json +3 -3
  49. package/r/job-panel.json +2 -2
  50. package/r/json-editor.json +3 -3
  51. package/r/library-shelf.json +56 -0
  52. package/r/map.json +2 -2
  53. package/r/margin-notes.json +67 -0
  54. package/r/menubar.json +2 -2
  55. package/r/mind-map.json +4 -4
  56. package/r/navigation-menu.json +2 -2
  57. package/r/needs-you.json +55 -0
  58. package/r/order-detail.json +2 -2
  59. package/r/org-chart.json +4 -4
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +3 -3
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +3 -3
  65. package/r/product-detail.json +2 -2
  66. package/r/product-grid.json +3 -3
  67. package/r/record-form.json +2 -2
  68. package/r/record-grid.json +52 -0
  69. package/r/record-notes.json +4 -4
  70. package/r/registry.json +4089 -1510
  71. package/r/run-history.json +52 -0
  72. package/r/run-view.json +80 -0
  73. package/r/schedule-card.json +54 -0
  74. package/r/schedule-engine.json +79 -0
  75. package/r/schedule-gantt.json +83 -0
  76. package/r/schedule-ruler.json +64 -0
  77. package/r/search-dialog.json +2 -2
  78. package/r/settings-list.json +2 -2
  79. package/r/setup-checklist.json +2 -2
  80. package/r/share-dialog.json +2 -2
  81. package/r/sidebar.json +3 -3
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +3 -3
  84. package/r/source-receipt.json +52 -0
  85. package/r/spreadsheet.json +3 -3
  86. package/r/stat-cards.json +3 -3
  87. package/r/step-picker.json +53 -0
  88. package/r/step-settings.json +72 -0
  89. package/r/suggestion.json +58 -0
  90. package/r/sum-bar.json +64 -0
  91. package/r/task-list.json +3 -3
  92. package/r/task-model.json +2 -2
  93. package/r/testimonials.json +2 -2
  94. package/r/tier-map.json +67 -0
  95. package/r/time-grid.json +73 -0
  96. package/r/time-strip.json +64 -0
  97. package/r/top-bar.json +66 -0
  98. package/r/transaction-list.json +2 -2
  99. package/r/trigger-picker.json +61 -0
  100. package/r/whiteboard.json +4 -4
  101. package/r/workflow-view.json +55 -0
  102. package/registry/blocks/activity-log/README.md +112 -0
  103. package/registry/blocks/activity-log/activity-log.jsx +351 -0
  104. package/registry/blocks/activity-log/block.json +33 -0
  105. package/registry/blocks/activity-log/demo.jsx +48 -0
  106. package/registry/blocks/activity-log/index.js +4 -0
  107. package/registry/blocks/agent-changes/README.md +94 -0
  108. package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
  109. package/registry/blocks/agent-changes/block.json +28 -0
  110. package/registry/blocks/agent-changes/demo.jsx +39 -0
  111. package/registry/blocks/agent-changes/index.js +3 -0
  112. package/registry/blocks/agent-chat/README.md +145 -0
  113. package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
  114. package/registry/blocks/agent-chat/block.json +30 -0
  115. package/registry/blocks/agent-chat/demo.jsx +165 -0
  116. package/registry/blocks/agent-chat/index.js +3 -0
  117. package/registry/blocks/agent-column/README.md +197 -0
  118. package/registry/blocks/agent-column/agent-column.jsx +492 -0
  119. package/registry/blocks/agent-column/block.json +67 -0
  120. package/registry/blocks/agent-column/column-picker.jsx +163 -0
  121. package/registry/blocks/agent-column/demo.jsx +50 -0
  122. package/registry/blocks/agent-column/index.js +7 -0
  123. package/registry/blocks/agent-column/model.js +164 -0
  124. package/registry/blocks/agent-column/receipt.jsx +483 -0
  125. package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
  126. package/registry/blocks/agent-dock/README.md +210 -0
  127. package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
  128. package/registry/blocks/agent-dock/block.json +47 -0
  129. package/registry/blocks/agent-dock/demo.jsx +153 -0
  130. package/registry/blocks/agent-dock/dock-model.js +118 -0
  131. package/registry/blocks/agent-dock/index.js +5 -0
  132. package/registry/blocks/agent-kit/README.md +73 -0
  133. package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
  134. package/registry/blocks/agent-kit/block.json +10 -0
  135. package/registry/blocks/agent-kit/demo.jsx +35 -0
  136. package/registry/blocks/agent-kit/index.js +3 -0
  137. package/registry/blocks/agent-marks/README.md +80 -0
  138. package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
  139. package/registry/blocks/agent-marks/block.json +27 -0
  140. package/registry/blocks/agent-marks/demo.jsx +49 -0
  141. package/registry/blocks/agent-marks/index.js +3 -0
  142. package/registry/blocks/agent-pane/README.md +225 -0
  143. package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
  144. package/registry/blocks/agent-pane/block.json +41 -0
  145. package/registry/blocks/agent-pane/composer.jsx +6 -0
  146. package/registry/blocks/agent-pane/demo.jsx +233 -0
  147. package/registry/blocks/agent-pane/dock-context.js +10 -0
  148. package/registry/blocks/agent-pane/index.js +4 -0
  149. package/registry/blocks/agent-pane/prose.jsx +84 -0
  150. package/registry/blocks/agent-pane/questions.jsx +134 -0
  151. package/registry/blocks/agent-pane/transcript.jsx +268 -0
  152. package/registry/blocks/agent-pane/work.jsx +368 -0
  153. package/registry/blocks/ai-action/README.md +94 -0
  154. package/registry/blocks/ai-action/ai-action.jsx +188 -0
  155. package/registry/blocks/ai-action/block.json +34 -0
  156. package/registry/blocks/ai-action/demo.jsx +93 -0
  157. package/registry/blocks/ai-action/index.js +3 -0
  158. package/registry/blocks/annotate/README.md +14 -11
  159. package/registry/blocks/approval/README.md +145 -0
  160. package/registry/blocks/approval/approval.jsx +163 -0
  161. package/registry/blocks/approval/block.json +31 -0
  162. package/registry/blocks/approval/demo.jsx +121 -0
  163. package/registry/blocks/approval/index.js +3 -0
  164. package/registry/blocks/ask-bar/README.md +105 -0
  165. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  166. package/registry/blocks/ask-bar/block.json +26 -0
  167. package/registry/blocks/ask-bar/demo.jsx +78 -0
  168. package/registry/blocks/ask-bar/index.js +3 -0
  169. package/registry/blocks/automation-editor/README.md +291 -0
  170. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  171. package/registry/blocks/automation-editor/block.json +39 -0
  172. package/registry/blocks/automation-editor/demo.jsx +284 -0
  173. package/registry/blocks/automation-editor/index.js +4 -0
  174. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  175. package/registry/blocks/automation-list/README.md +129 -0
  176. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  177. package/registry/blocks/automation-list/block.json +35 -0
  178. package/registry/blocks/automation-list/demo.jsx +67 -0
  179. package/registry/blocks/automation-list/index.js +3 -0
  180. package/registry/blocks/automation-model/README.md +109 -0
  181. package/registry/blocks/automation-model/block.json +135 -0
  182. package/registry/blocks/automation-model/catalog.js +256 -0
  183. package/registry/blocks/automation-model/check.js +161 -0
  184. package/registry/blocks/automation-model/demo.jsx +42 -0
  185. package/registry/blocks/automation-model/edit.js +262 -0
  186. package/registry/blocks/automation-model/fixes.js +287 -0
  187. package/registry/blocks/automation-model/glyph.jsx +13 -0
  188. package/registry/blocks/automation-model/graph.js +410 -0
  189. package/registry/blocks/automation-model/index.js +33 -0
  190. package/registry/blocks/automation-model/overlay.js +175 -0
  191. package/registry/blocks/automation-model/parts.jsx +94 -0
  192. package/registry/blocks/automation-model/schedule.js +53 -0
  193. package/registry/blocks/automation-model/templates.js +128 -0
  194. package/registry/blocks/automation-model/values.js +29 -0
  195. package/registry/blocks/automation-model/words.js +439 -0
  196. package/registry/blocks/automations-screen/README.md +207 -0
  197. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  198. package/registry/blocks/automations-screen/block.json +47 -0
  199. package/registry/blocks/automations-screen/demo.jsx +364 -0
  200. package/registry/blocks/automations-screen/index.js +4 -0
  201. package/registry/blocks/automations-screen/screen-model.js +129 -0
  202. package/registry/blocks/chart/cartesian.jsx +1 -1
  203. package/registry/blocks/chart/core.jsx +33 -23
  204. package/registry/blocks/chart/pie.jsx +1 -1
  205. package/registry/blocks/chat/README.md +4 -1
  206. package/registry/blocks/chat/demo.jsx +2 -2
  207. package/registry/blocks/chat-pane/README.md +143 -0
  208. package/registry/blocks/chat-pane/block.json +48 -0
  209. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  210. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  211. package/registry/blocks/chat-pane/chat-context.js +17 -0
  212. package/registry/blocks/chat-pane/chat-model.js +43 -0
  213. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  214. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  215. package/registry/blocks/chat-pane/demo.jsx +103 -0
  216. package/registry/blocks/chat-pane/index.js +9 -0
  217. package/registry/blocks/connect-card/README.md +99 -0
  218. package/registry/blocks/connect-card/block.json +10 -0
  219. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  220. package/registry/blocks/connect-card/demo.jsx +49 -0
  221. package/registry/blocks/connect-card/index.js +3 -0
  222. package/registry/blocks/cost/README.md +115 -0
  223. package/registry/blocks/cost/block.json +10 -0
  224. package/registry/blocks/cost/cost.jsx +176 -0
  225. package/registry/blocks/cost/demo.jsx +66 -0
  226. package/registry/blocks/cost/index.js +3 -0
  227. package/registry/blocks/data-picker/README.md +81 -0
  228. package/registry/blocks/data-picker/block.json +38 -0
  229. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  230. package/registry/blocks/data-picker/demo.jsx +34 -0
  231. package/registry/blocks/data-picker/fields.js +89 -0
  232. package/registry/blocks/data-picker/index.js +4 -0
  233. package/registry/blocks/data-table/demo.jsx +1 -1
  234. package/registry/blocks/first-run/README.md +118 -0
  235. package/registry/blocks/first-run/block.json +11 -0
  236. package/registry/blocks/first-run/demo.jsx +88 -0
  237. package/registry/blocks/first-run/first-run-model.js +51 -0
  238. package/registry/blocks/first-run/first-run.jsx +156 -0
  239. package/registry/blocks/first-run/index.js +5 -0
  240. package/registry/blocks/first-run/probe-rules.js +26 -0
  241. package/registry/blocks/fix-note/README.md +79 -0
  242. package/registry/blocks/fix-note/block.json +35 -0
  243. package/registry/blocks/fix-note/demo.jsx +30 -0
  244. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  245. package/registry/blocks/fix-note/index.js +3 -0
  246. package/registry/blocks/flow-canvas/README.md +15 -8
  247. package/registry/blocks/flow-editor/README.md +108 -0
  248. package/registry/blocks/flow-editor/block.json +44 -0
  249. package/registry/blocks/flow-editor/demo.jsx +115 -0
  250. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  251. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  252. package/registry/blocks/flow-editor/index.js +6 -0
  253. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  254. package/registry/blocks/flow-editor/outline.jsx +134 -0
  255. package/registry/blocks/footer/README.md +3 -2
  256. package/registry/blocks/library-shelf/README.md +117 -0
  257. package/registry/blocks/library-shelf/block.json +28 -0
  258. package/registry/blocks/library-shelf/demo.jsx +68 -0
  259. package/registry/blocks/library-shelf/index.js +3 -0
  260. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  261. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  262. package/registry/blocks/margin-notes/README.md +222 -0
  263. package/registry/blocks/margin-notes/block.json +10 -0
  264. package/registry/blocks/margin-notes/demo.jsx +144 -0
  265. package/registry/blocks/margin-notes/index.js +20 -0
  266. package/registry/blocks/margin-notes/margin-model.js +224 -0
  267. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  268. package/registry/blocks/mind-map/README.md +4 -2
  269. package/registry/blocks/needs-you/README.md +177 -0
  270. package/registry/blocks/needs-you/block.json +34 -0
  271. package/registry/blocks/needs-you/demo.jsx +143 -0
  272. package/registry/blocks/needs-you/index.js +3 -0
  273. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  274. package/registry/blocks/org-chart/README.md +4 -2
  275. package/registry/blocks/pace-bar/README.md +230 -0
  276. package/registry/blocks/pace-bar/block.json +10 -0
  277. package/registry/blocks/pace-bar/demo.jsx +255 -0
  278. package/registry/blocks/pace-bar/index.js +22 -0
  279. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  280. package/registry/blocks/pace-bar/pace-model.js +288 -0
  281. package/registry/blocks/page-builder/README.md +1 -1
  282. package/registry/blocks/page-builder/demo.jsx +3 -3
  283. package/registry/blocks/pdf-viewer/README.md +4 -1
  284. package/registry/blocks/record-grid/README.md +100 -0
  285. package/registry/blocks/record-grid/block.json +28 -0
  286. package/registry/blocks/record-grid/demo.jsx +43 -0
  287. package/registry/blocks/record-grid/index.js +3 -0
  288. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  289. package/registry/blocks/run-history/README.md +138 -0
  290. package/registry/blocks/run-history/block.json +10 -0
  291. package/registry/blocks/run-history/demo.jsx +74 -0
  292. package/registry/blocks/run-history/index.js +3 -0
  293. package/registry/blocks/run-history/run-history.jsx +218 -0
  294. package/registry/blocks/run-view/README.md +174 -0
  295. package/registry/blocks/run-view/block.json +50 -0
  296. package/registry/blocks/run-view/demo.jsx +286 -0
  297. package/registry/blocks/run-view/index.js +5 -0
  298. package/registry/blocks/run-view/run-controls.jsx +266 -0
  299. package/registry/blocks/run-view/run-view.jsx +236 -0
  300. package/registry/blocks/run-view/runs-list.jsx +99 -0
  301. package/registry/blocks/schedule-card/README.md +121 -0
  302. package/registry/blocks/schedule-card/block.json +10 -0
  303. package/registry/blocks/schedule-card/demo.jsx +82 -0
  304. package/registry/blocks/schedule-card/index.js +3 -0
  305. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  306. package/registry/blocks/schedule-engine/README.md +137 -0
  307. package/registry/blocks/schedule-engine/block.json +10 -0
  308. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  309. package/registry/blocks/schedule-engine/engine.js +769 -0
  310. package/registry/blocks/schedule-engine/index.js +9 -0
  311. package/registry/blocks/schedule-engine/ops.js +71 -0
  312. package/registry/blocks/schedule-engine/place.js +294 -0
  313. package/registry/blocks/schedule-engine/tree.js +79 -0
  314. package/registry/blocks/schedule-engine/waits.js +80 -0
  315. package/registry/blocks/schedule-gantt/README.md +159 -0
  316. package/registry/blocks/schedule-gantt/block.json +10 -0
  317. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  318. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  319. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  320. package/registry/blocks/schedule-gantt/index.js +26 -0
  321. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  322. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  323. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  324. package/registry/blocks/schedule-ruler/README.md +148 -0
  325. package/registry/blocks/schedule-ruler/block.json +10 -0
  326. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  327. package/registry/blocks/schedule-ruler/index.js +21 -0
  328. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  329. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  330. package/registry/blocks/sidebar/README.md +23 -13
  331. package/registry/blocks/sketch-canvas/README.md +15 -9
  332. package/registry/blocks/source-receipt/README.md +97 -0
  333. package/registry/blocks/source-receipt/block.json +30 -0
  334. package/registry/blocks/source-receipt/demo.jsx +71 -0
  335. package/registry/blocks/source-receipt/index.js +3 -0
  336. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  337. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  338. package/registry/blocks/step-picker/README.md +78 -0
  339. package/registry/blocks/step-picker/block.json +31 -0
  340. package/registry/blocks/step-picker/demo.jsx +23 -0
  341. package/registry/blocks/step-picker/index.js +3 -0
  342. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  343. package/registry/blocks/step-settings/README.md +100 -0
  344. package/registry/blocks/step-settings/block.json +44 -0
  345. package/registry/blocks/step-settings/demo.jsx +93 -0
  346. package/registry/blocks/step-settings/fields.jsx +58 -0
  347. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  348. package/registry/blocks/step-settings/index.js +5 -0
  349. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  350. package/registry/blocks/suggestion/README.md +171 -0
  351. package/registry/blocks/suggestion/block.json +40 -0
  352. package/registry/blocks/suggestion/demo.jsx +91 -0
  353. package/registry/blocks/suggestion/index.js +3 -0
  354. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  355. package/registry/blocks/sum-bar/README.md +122 -0
  356. package/registry/blocks/sum-bar/block.json +10 -0
  357. package/registry/blocks/sum-bar/demo.jsx +110 -0
  358. package/registry/blocks/sum-bar/index.js +5 -0
  359. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  360. package/registry/blocks/sum-bar/sum-model.js +126 -0
  361. package/registry/blocks/tier-map/README.md +217 -0
  362. package/registry/blocks/tier-map/block.json +10 -0
  363. package/registry/blocks/tier-map/demo.jsx +222 -0
  364. package/registry/blocks/tier-map/index.js +24 -0
  365. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  366. package/registry/blocks/tier-map/tier-model.js +318 -0
  367. package/registry/blocks/time-grid/README.md +305 -0
  368. package/registry/blocks/time-grid/block.json +10 -0
  369. package/registry/blocks/time-grid/demo.jsx +279 -0
  370. package/registry/blocks/time-grid/grid-model.js +322 -0
  371. package/registry/blocks/time-grid/index.js +25 -0
  372. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  373. package/registry/blocks/time-strip/README.md +141 -0
  374. package/registry/blocks/time-strip/block.json +10 -0
  375. package/registry/blocks/time-strip/demo.jsx +129 -0
  376. package/registry/blocks/time-strip/index.js +19 -0
  377. package/registry/blocks/time-strip/strip-model.js +178 -0
  378. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  379. package/registry/blocks/top-bar/README.md +149 -0
  380. package/registry/blocks/top-bar/block.json +35 -0
  381. package/registry/blocks/top-bar/demo.jsx +78 -0
  382. package/registry/blocks/top-bar/index.js +5 -0
  383. package/registry/blocks/top-bar/probe-rules.js +74 -0
  384. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  385. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  386. package/registry/blocks/trigger-picker/README.md +98 -0
  387. package/registry/blocks/trigger-picker/block.json +38 -0
  388. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  389. package/registry/blocks/trigger-picker/index.js +3 -0
  390. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  391. package/registry/blocks/whiteboard/README.md +20 -14
  392. package/registry/blocks/workflow-view/README.md +123 -0
  393. package/registry/blocks/workflow-view/block.json +10 -0
  394. package/registry/blocks/workflow-view/demo.jsx +90 -0
  395. package/registry/blocks/workflow-view/index.js +3 -0
  396. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  397. package/src/cli.mjs +2 -2
  398. package/src/install.mjs +100 -22
  399. package/src/registry.mjs +37 -3
  400. package/templates/next/browser/lib/data.js +6 -1
  401. package/templates/next/files/README.md +909 -26
  402. package/templates/next/files/app/shell.jsx +54 -37
  403. package/templates/next/files/check/automation-format.ts +2103 -0
  404. package/templates/next/files/check/automation-package.ts +142 -0
  405. package/templates/next/files/check/run.mjs +1043 -12
  406. package/templates/next/files/components/ui/field.jsx +17 -4
  407. package/templates/next/files/components/ui/icon.jsx +13 -0
  408. package/templates/next/files/components/ui/index.js +3 -1
  409. package/templates/next/files/components/ui/layout.jsx +382 -0
  410. package/templates/next/files/components/ui/notice.jsx +70 -0
  411. package/templates/next/files/components/ui/page.jsx +124 -0
  412. package/templates/next/files/components/ui/stat.jsx +22 -7
  413. package/templates/next/files/components/ui/toast.jsx +6 -3
  414. package/templates/next/files/lib/automations.js +660 -0
  415. package/templates/next/files/lib/claw.js +244 -5
  416. package/templates/next/files/lib/door.js +92 -0
  417. package/templates/next/files/lib/hooks.js +1694 -6
  418. package/templates/next/files/lib/platform.js +611 -14
  419. package/templates/next/template.json +22 -3
@@ -0,0 +1,483 @@
1
+ "use client";
2
+
3
+ import { useId, useState } from "react";
4
+ import { Button, Input, cx } from "../../ui";
5
+ import { AgentMark } from "../agent-marks";
6
+ import { CONFIDENCE, answerState, decidingWords, shortUrl } from "./model";
7
+
8
+ // The receipt: an answer as a claim with its citation (grown in Data
9
+ // Enrichment 0.5.0, the v2 design's signature). In a dense grid the
10
+ // answer shrinks to one line, its value and its trust as a mark and a
11
+ // word (AnswerLine, TrustMark); opened, it is drawn big: the value, how
12
+ // sure, and each source as a clipping (the page's title, its address and
13
+ // date, and the words on it with the deciding ones underlined). Two
14
+ // answers are two clippings to pick from; "not found" is a receipt too,
15
+ // every page the agent tried crossed off. And a column's heading as a job
16
+ // (JobHeader): its name, how far it got, what a row costs, its menu.
17
+ //
18
+ // Every state is a shape and a word, never colour alone. Colours are the
19
+ // theme's slots: chart-1 sure, chart-2 likely, chart-3 guess, chart-4
20
+ // sent, chart-5 typed by a person, success a person's check, warning
21
+ // two answers or a flag, info looking up, destructive failed; the rest
22
+ // muted. Props in, callbacks out. Tokens only.
23
+
24
+ /* ------------------------------ the marks ------------------------------ */
25
+
26
+ // The agent's mark is the platform's one (the agent-marks block): a
27
+ // filled diamond. Re-exported so a screen that took AgentMark from here
28
+ // keeps it.
29
+ export { AgentMark };
30
+
31
+ const Dot = ({ kind }) =>
32
+ kind === "sure" ? (
33
+ <span aria-hidden="true" className="inline-block size-2 shrink-0 rounded-full bg-current" />
34
+ ) : kind === "likely" ? (
35
+ <span aria-hidden="true" className="relative inline-block size-2 shrink-0 overflow-hidden rounded-full border-[1.5px] border-current">
36
+ <span className="absolute inset-y-0 left-0 w-1/2 bg-current" />
37
+ </span>
38
+ ) : kind === "guess" ? (
39
+ <span aria-hidden="true" className="inline-block size-[9px] shrink-0 rounded-full border-[1.5px] border-dashed border-current" />
40
+ ) : kind === "two" ? (
41
+ <span aria-hidden="true" className="relative inline-block size-[9px] shrink-0 border-[1.5px] border-current">
42
+ <span className="absolute inset-y-0 left-1/2 w-[1.5px] -translate-x-1/2 bg-current" />
43
+ </span>
44
+ ) : kind === "wait" ? (
45
+ <span aria-hidden="true" className="inline-block size-2 shrink-0 rounded-full border-[1.5px] border-current border-t-transparent" />
46
+ ) : kind === "none" ? (
47
+ <span aria-hidden="true" className="relative inline-block size-[9px] shrink-0 overflow-hidden rounded-full border-[1.5px] border-current">
48
+ <span className="absolute left-1/2 top-[-2px] h-[13px] w-[1.5px] -translate-x-1/2 rotate-45 bg-current" />
49
+ </span>
50
+ ) : kind === "looking" ? (
51
+ <span aria-hidden="true" className="relative inline-block h-[3px] w-[18px] shrink-0 overflow-hidden rounded-full border border-current">
52
+ <span className="absolute inset-y-0 left-0 w-1/3 animate-pulse bg-current motion-reduce:animate-none" />
53
+ </span>
54
+ ) : kind === "failed" ? (
55
+ <span aria-hidden="true" className="text-[10px] leading-none">▲</span>
56
+ ) : kind === "typed" ? (
57
+ <span aria-hidden="true" className="text-[11px] leading-none">✎</span>
58
+ ) : kind === "sent" ? (
59
+ <span aria-hidden="true" className="text-[11px] leading-none">↗</span>
60
+ ) : kind === "stale" ? (
61
+ <span aria-hidden="true" className="text-[11px] leading-none">↻</span>
62
+ ) : null;
63
+
64
+ const TONE = {
65
+ sure: "text-chart-1",
66
+ likely: "text-chart-2",
67
+ guess: "text-chart-3",
68
+ two: "text-warning",
69
+ warn: "text-warning",
70
+ looking: "text-info",
71
+ failed: "text-destructive",
72
+ typed: "text-chart-5",
73
+ sent: "text-chart-4",
74
+ ok: "text-success",
75
+ quiet: "text-muted-foreground",
76
+ };
77
+
78
+ /**
79
+ * A trust mark and its word, in the state's tone: sure ●, likely ◐,
80
+ * guess ◌ (never shown as verified), two answers ▣, looking up ▬, waits
81
+ * ◔, not found ⊘, failed ▲, typed ✎, sent ↗, out of date ↻.
82
+ *
83
+ * kind sure · likely · guess · two · warn · looking · wait · none ·
84
+ * failed · typed · sent · stale · quiet
85
+ * word the word beside it ("" for the mark alone, which still names
86
+ * itself to a screen reader)
87
+ * check a person's tick after it
88
+ */
89
+ export function TrustMark({ kind, word, check = false, className }) {
90
+ const glyph = { warn: "two", quiet: null }[kind] ?? kind;
91
+ const tone = TONE[kind] ?? TONE.quiet;
92
+ const said = word ?? CONFIDENCE[kind]?.label ?? "";
93
+ const aria = [said || CONFIDENCE[kind]?.label || kind, check ? "checked" : ""].filter(Boolean).join(", ");
94
+ return (
95
+ <span className={cx("relative inline-flex shrink-0 items-center gap-1 whitespace-nowrap text-[11px]", tone, className)}>
96
+ {glyph ? <Dot kind={glyph === "wait" || glyph === "none" ? glyph : glyph} /> : null}
97
+ {said ? <span>{said}</span> : <span className="sr-only">{aria}</span>}
98
+ {check ? (
99
+ <span className="text-[11px] font-bold text-success" aria-label="checked">
100
+ ✓
101
+ </span>
102
+ ) : null}
103
+ </span>
104
+ );
105
+ }
106
+
107
+ const sureKind = (c) => (c === "sure" || c === "likely" || c === "guess" ? c : "quiet");
108
+
109
+ /* ------------------------------ the line ------------------------------ */
110
+
111
+ /**
112
+ * One answer on one line, as a dense grid draws it: the value at the
113
+ * start, its trust at the end (a person's check after it); a state with
114
+ * no value says the state in words.
115
+ *
116
+ * answer the answer (model.js), or null for not asked yet
117
+ * type text · link · email · number · domain
118
+ * onRetry a failed answer's "Try again"
119
+ * queuedWord what a queued answer says ("queued", "back in the queue")
120
+ */
121
+ export function AnswerLine({ answer, onRetry, queuedWord = "queued", className }) {
122
+ const st = answerState(answer);
123
+ const a = answer ?? {};
124
+ const value = (v, struck) => <span className={cx("min-w-0 flex-[0_1_auto] truncate", struck && "text-muted-foreground line-through decoration-muted-foreground")}>{v}</span>;
125
+ const row = (children) => <span className={cx("flex w-full min-w-0 items-center gap-1.5", className)}>{children}</span>;
126
+ const end = (node) => <span className="ml-auto flex shrink-0 items-center gap-1">{node}</span>;
127
+ switch (st) {
128
+ case "empty":
129
+ return row(<span className="text-input">—</span>);
130
+ case "queued":
131
+ return row(<TrustMark kind="quiet" word={a.value ? `${queuedWord} · ${a.value}` : queuedWord} />);
132
+ case "waiting":
133
+ return row(<TrustMark kind="wait" word={a.waitsFor?.length ? `waits for ${a.waitsFor.join(", ")}` : "waits for the row"} className="text-muted-foreground" />);
134
+ case "blocked":
135
+ return row(<TrustMark kind="wait" word={`can't fill · needs ${(a.blockedBy ?? []).join(" and ")}`} className="text-muted-foreground" />);
136
+ case "working":
137
+ return row(<TrustMark kind="looking" word={a.value ? "writing" : a.looking ? `looking up · ${a.looking}` : "looking up"} className="min-w-0 truncate" />);
138
+ case "not_found":
139
+ return row(<TrustMark kind="none" word={a.checked ? "not found, kept empty" : "not found"} check={a.checked} className="text-muted-foreground" />);
140
+ case "failed":
141
+ return row(
142
+ <>
143
+ <TrustMark kind="failed" word={`failed${a.detail || a.note ? ` · ${a.detail || a.note}` : ""}`} className="min-w-0 truncate" />
144
+ {onRetry ? (
145
+ <span className="ml-auto shrink-0">
146
+ <Button variant="link" size="inherit" onClick={(e) => (e.stopPropagation(), onRetry())} className="text-xs">
147
+ Try again
148
+ </Button>
149
+ </span>
150
+ ) : null}
151
+ </>,
152
+ );
153
+ case "two_answers":
154
+ return row(
155
+ <>
156
+ {value(`${a.value} · ${a.other?.value ?? ""}`)}
157
+ {end(<TrustMark kind="two" word="2 answers" />)}
158
+ </>,
159
+ );
160
+ case "stale":
161
+ return row(
162
+ <>
163
+ {value(a.value, true)}
164
+ {end(<TrustMark kind="stale" word="out of date" className="text-muted-foreground" />)}
165
+ </>,
166
+ );
167
+ case "typed":
168
+ return row(
169
+ <>
170
+ {value(a.value)}
171
+ {end(<TrustMark kind="typed" word="typed" />)}
172
+ </>,
173
+ );
174
+ default: {
175
+ if (a.flag && !a.checked) return row(<TrustMark kind="warn" word={a.flag === "left" ? `${a.value}${a.movedTo ? ` · ${a.movedTo}` : ""}` : `${a.value ?? ""}${a.flag === "may_not_fit" ? ": may not fit" : ""}`} className="min-w-0 truncate" />);
176
+ const checked = st === "checked";
177
+ const kind = sureKind(a.confidence);
178
+ return row(
179
+ <>
180
+ {value(a.value)}
181
+ {end(<TrustMark kind={kind} word={checked && kind !== "guess" ? "" : CONFIDENCE[kind]?.label ?? ""} check={checked} />)}
182
+ </>,
183
+ );
184
+ }
185
+ }
186
+ }
187
+
188
+ /* ------------------------------ the heading ------------------------------ */
189
+
190
+ /**
191
+ * A column's heading as a job: the agent's mark and its name, its menu,
192
+ * then a bar of how far it got, the words ("138 of 480 · 2 to check")
193
+ * and what a row costs. A person's own column says where it came from.
194
+ *
195
+ * name "Headcount"
196
+ * agent false: a person's own column
197
+ * source for a person's column, the line under its name ("yours ·
198
+ * summit-leads.csv"; default "yours")
199
+ * progress "21 of 22 · 3 to check"; part 0 to 1 for the bar
200
+ * cost "40 cr/row"
201
+ * menu a node at the end of the first line (a kit Menu)
202
+ */
203
+ export function JobHeader({ name, agent = true, source, progress, part, cost, menu, className }) {
204
+ return (
205
+ <div className={cx("grid min-w-0 gap-1.5", className)}>
206
+ <div className={cx("flex min-w-0 items-center gap-1.5", agent ? "font-semibold" : "font-medium")}>
207
+ {agent ? <AgentMark /> : null}
208
+ <span className="min-w-0 flex-1 truncate">{name}</span>
209
+ {menu ?? null}
210
+ </div>
211
+ <div className={cx("flex min-w-0 items-center gap-1.5 whitespace-nowrap text-[11px] font-normal", agent ? "text-muted-foreground" : "text-chart-5")}>
212
+ {agent ? (
213
+ <>
214
+ <span aria-hidden="true" className="relative inline-block h-[3px] w-[30px] shrink-0 overflow-hidden rounded-full bg-muted">
215
+ <span className="absolute inset-y-0 left-0 bg-primary" style={{ width: `${Math.round(Math.max(0, Math.min(1, part ?? 0)) * 100)}%` }} />
216
+ </span>
217
+ <span className="min-w-0 truncate">{progress}</span>
218
+ {cost ? <span className="ml-auto shrink-0">{cost}</span> : null}
219
+ </>
220
+ ) : (
221
+ <span className="truncate">{source ?? "yours"}</span>
222
+ )}
223
+ </div>
224
+ </div>
225
+ );
226
+ }
227
+
228
+ /* ------------------------------ the receipt ------------------------------ */
229
+
230
+ /** The words on the page, the deciding ones underlined: `[[…]]` in the
231
+ * words marks them, else the answer's value where it appears. */
232
+ function Quote({ words, mark }) {
233
+ const parts = decidingWords(words, mark);
234
+ return (
235
+ <q className="block leading-normal [quotes:none] before:content-['\201C'] after:content-['\201D']">
236
+ {parts.map((p, i) =>
237
+ p.marked ? (
238
+ <mark key={i} className="bg-accent px-px text-accent-foreground underline decoration-primary decoration-2 underline-offset-[3px]">
239
+ {p.text}
240
+ </mark>
241
+ ) : (
242
+ <span key={i}>{p.text}</span>
243
+ ),
244
+ )}
245
+ </q>
246
+ );
247
+ }
248
+
249
+ /**
250
+ * A source as a clipping: its trust, the page's title, an action at the
251
+ * end (Pick 85), the address and when it was read, the words on it with
252
+ * the deciding ones underlined, and a footnote.
253
+ *
254
+ * source { url, title, evidence, read } (read: "read 22 Sep")
255
+ * trust sure · likely · guess (the dot before the title), or null
256
+ * mark the value to underline when the words carry no [[…]]
257
+ * title overrides source.title ("62 people · likely")
258
+ * action a node at the head's end
259
+ * footnote a muted line under the words
260
+ * picked drawn as the one chosen
261
+ */
262
+ export function Clipping({ source, trust, mark, title, action, footnote, picked = false, children, className }) {
263
+ const s = source ?? {};
264
+ const url = s.url ? shortUrl(s.url) : null;
265
+ return (
266
+ <div className={cx("grid gap-1.5 rounded-[var(--radius)] border bg-card px-3 py-2.5 text-card-foreground", picked ? "border-primary ring-1 ring-primary" : "border-border", className)}>
267
+ <div className="flex min-w-0 items-center gap-2">
268
+ {trust ? <TrustMark kind={sureKind(trust)} word="" /> : null}
269
+ <b className="min-w-0 flex-1 truncate font-semibold">{title ?? s.title ?? url ?? "A page"}</b>
270
+ {action ?? null}
271
+ </div>
272
+ {url || s.read ? (
273
+ <div className="min-w-0 truncate text-xs text-muted-foreground">
274
+ {url ? (
275
+ <a href={/^https?:/i.test(s.url) ? s.url : `https://${s.url}`} target="_blank" rel="noreferrer" className="underline-offset-2 outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring">
276
+ {url}
277
+ </a>
278
+ ) : null}
279
+ {url && s.read ? " · " : null}
280
+ {s.read ?? null}
281
+ </div>
282
+ ) : null}
283
+ {s.evidence ? <Quote words={s.evidence} mark={mark} /> : null}
284
+ {footnote ? <div className="text-xs text-muted-foreground">{footnote}</div> : null}
285
+ {children}
286
+ </div>
287
+ );
288
+ }
289
+
290
+ /** What the agent tried, each page crossed off, with why it gave up. */
291
+ export function TriedList({ tried = [], className }) {
292
+ if (!tried.length) return null;
293
+ return (
294
+ <ul className={cx("grid gap-1 text-xs", className)}>
295
+ {tried.map((t, i) => (
296
+ <li key={i} className="flex min-w-0 items-baseline gap-2">
297
+ <s className="min-w-0 truncate text-muted-foreground">{t.title || shortUrl(t.url) || "a page"}</s>
298
+ {t.evidence ? <span className="min-w-0 truncate">{t.evidence}</span> : null}
299
+ </li>
300
+ ))}
301
+ </ul>
302
+ );
303
+ }
304
+
305
+ /**
306
+ * The receipt: one answer opened, drawn big. Its head (the record, the
307
+ * question, the row), the value and its state in words, then the
308
+ * clippings: one for a found answer, two to pick from for two answers,
309
+ * the page that says a person left and who holds the role now, or what
310
+ * was tried for not found.
311
+ *
312
+ * answer the answer (model.js)
313
+ * title the record ("Klarwerk"); question ("Headcount"); where ("row 2")
314
+ * onPick(which) "one" | "other": Pick on each of two answers
315
+ * pickWords(value) the Pick button's words (default "Pick <value>")
316
+ * picked which of two was picked ("one" | "other"), drawn chosen
317
+ * read the date the pages were read ("read 22 Sep")
318
+ * by who found it, a node ("Found by the agent · 22 Sep, 10:31")
319
+ * valueLabel overrides the big value ("Head of Product, or Product Lead")
320
+ * stateWords overrides the state's words beside it
321
+ * leftTitle for a person who left: the title over who holds the role now
322
+ * children your actions, under the receipt
323
+ */
324
+ export function Receipt({ answer, title, question, where, onPick, pickWords, picked, read, by, valueLabel, stateWords, leftTitle = "Now in the role", busy = false, children, className }) {
325
+ const st = answerState(answer);
326
+ const a = answer ?? {};
327
+ const two = st === "two_answers" || (a.other?.value && picked);
328
+ const left = a.flag === "left";
329
+ const kind = left || st === "two_answers" ? "two" : st === "not_found" ? "none" : st === "failed" ? "failed" : st === "typed" ? "typed" : st === "working" ? "looking" : sureKind(a.confidence);
330
+ const big =
331
+ valueLabel ??
332
+ (st === "two_answers" ? `${a.value} or ${a.other?.value ?? ""}` : st === "not_found" ? "Not found" : st === "failed" ? "Failed" : st === "working" ? "Looking up" : st === "empty" ? "Not asked yet" : a.value);
333
+ const words =
334
+ stateWords ??
335
+ (left
336
+ ? "left the company · needs you"
337
+ : st === "two_answers"
338
+ ? "two answers · the sources disagree"
339
+ : st === "checked"
340
+ ? `${CONFIDENCE[a.confidence]?.label ?? "found"} · checked`
341
+ : st === "typed"
342
+ ? "typed by a person · never overwritten"
343
+ : st === "not_found"
344
+ ? a.checked
345
+ ? "kept empty"
346
+ : "what it tried, crossed off"
347
+ : st === "failed"
348
+ ? "a page didn't answer"
349
+ : CONFIDENCE[a.confidence]
350
+ ? `${CONFIDENCE[a.confidence].label} · ${CONFIDENCE[a.confidence].words}`
351
+ : "");
352
+ const pickLabel = (v) => (pickWords ? pickWords(v) : `Pick ${v}`);
353
+ const withRead = (s) => (s ? { ...s, read: s.read ?? read } : s);
354
+ return (
355
+ <div className={cx("grid min-w-0 gap-3", className)}>
356
+ {title || question ? (
357
+ <div className="flex min-w-0 flex-wrap items-baseline gap-x-1.5">
358
+ {title ? <b className="text-sm font-semibold">{title}</b> : null}
359
+ {question || where ? <span className="text-muted-foreground">· {[question, where].filter(Boolean).join(" · ")}</span> : null}
360
+ </div>
361
+ ) : null}
362
+ <div className="grid gap-1">
363
+ <span className={cx("break-words font-semibold leading-tight", String(big ?? "").length > 24 ? "text-xl" : "text-2xl", a.confidence === "guess" && st === "found" && "italic")}>{big}</span>
364
+ {words ? <TrustMark kind={kind} word={words} check={st === "checked"} className="text-xs" /> : null}
365
+ {a.detail && !two && st !== "failed" ? <span className="text-xs text-muted-foreground">{a.detail}</span> : null}
366
+ </div>
367
+ {two && !left ? (
368
+ <>
369
+ <Clipping
370
+ source={withRead(a.source)}
371
+ trust={a.confidence ?? "likely"}
372
+ mark={a.value}
373
+ picked={picked === "one"}
374
+ action={onPick ? (picked === "one" ? <Button size="sm" variant="primary" disabled>Picked</Button> : <Button size="sm" onClick={() => onPick("one")} disabled={busy}>{pickLabel(a.value)}</Button>) : null}
375
+ footnote={a.detail}
376
+ />
377
+ <Clipping
378
+ source={withRead(a.other?.source)}
379
+ trust={a.other?.confidence ?? a.confidence ?? "likely"}
380
+ mark={a.other?.value}
381
+ picked={picked === "other"}
382
+ action={onPick ? (picked === "other" ? <Button size="sm" variant="primary" disabled>Picked</Button> : <Button size="sm" onClick={() => onPick("other")} disabled={busy}>{pickLabel(a.other?.value)}</Button>) : null}
383
+ footnote={a.other?.detail}
384
+ />
385
+ </>
386
+ ) : left ? (
387
+ <>
388
+ {a.source ? <Clipping source={withRead(a.source)} trust={a.confidence ?? "sure"} mark={a.value} footnote={a.note} /> : null}
389
+ {a.other?.value ? (
390
+ <>
391
+ <span className="text-[11px] uppercase tracking-[0.04em] text-muted-foreground">{leftTitle}</span>
392
+ <Clipping source={withRead(a.other.source)} trust="sure" title={`${a.other.value}${a.other.detail ? `, ${a.other.detail}` : ""}`} mark={a.other.value} />
393
+ </>
394
+ ) : null}
395
+ </>
396
+ ) : st === "not_found" || st === "failed" ? (
397
+ <Clipping source={{ title: st === "failed" ? "What it read" : "What it tried", read }} title={st === "failed" ? "What it read" : "What it tried"} footnote={a.note}>
398
+ <TriedList tried={a.tried?.length ? a.tried : a.source?.url ? [{ title: a.source.title, url: a.source.url, evidence: a.detail }] : []} />
399
+ </Clipping>
400
+ ) : a.source?.url || a.source?.evidence ? (
401
+ <Clipping source={withRead(a.source)} trust={a.confidence} mark={a.value} footnote={st === "stale" ? "Out of date: its question or its row changed since. It keeps this until a new answer lands." : undefined} />
402
+ ) : null}
403
+ {a.note && st !== "not_found" && st !== "failed" && !left ? (
404
+ <div className="text-xs">
405
+ <span className="text-[11px] uppercase tracking-[0.04em] text-muted-foreground">How it was found</span>
406
+ <br />
407
+ {a.note}
408
+ </div>
409
+ ) : null}
410
+ {by ? <div className="flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground">{by}</div> : null}
411
+ {children}
412
+ </div>
413
+ );
414
+ }
415
+
416
+ /**
417
+ * What a person can do with an answer: type their own (theirs, never
418
+ * overwritten), or ask again with a hint, its price said.
419
+ *
420
+ * onType(value) · typePlaceholder
421
+ * onAskAgain(hint) · hintPlaceholder · askCost ("about 40 credits")
422
+ * askNote a line under it ("The old answers go into this answer's history.")
423
+ * askLabel the button's words (default "Ask again")
424
+ * busy
425
+ */
426
+ export function ReceiptActions({ onType, typePlaceholder = "Your answer", onAskAgain, hintPlaceholder = "Ask again with a hint", askCost, askNote, askLabel = "Ask again", hint: initialHint = "", busy = false, className }) {
427
+ const [typing, setTyping] = useState(false);
428
+ const [own, setOwn] = useState("");
429
+ const [hint, setHint] = useState(initialHint ?? "");
430
+ const ownId = useId();
431
+ const hintId = useId();
432
+ return (
433
+ <div className={cx("grid gap-2", className)}>
434
+ {onType ? (
435
+ typing ? (
436
+ <form
437
+ className="relative flex gap-2"
438
+ onSubmit={(e) => {
439
+ e.preventDefault();
440
+ if (own.trim()) onType(own.trim());
441
+ }}
442
+ >
443
+ <label htmlFor={ownId} className="sr-only">
444
+ Your own answer
445
+ </label>
446
+ <Input id={ownId} value={own} onChange={(e) => setOwn(e.target.value)} placeholder={typePlaceholder} className="min-w-0 flex-1" autoFocus />
447
+ <Button type="submit" size="sm" disabled={busy || !own.trim()}>
448
+ Save
449
+ </Button>
450
+ </form>
451
+ ) : (
452
+ <div className="flex flex-wrap items-center gap-2">
453
+ <Button size="sm" onClick={() => setTyping(true)} disabled={busy}>
454
+ Type my own
455
+ </Button>
456
+ <span className="text-xs text-muted-foreground">yours, never overwritten</span>
457
+ </div>
458
+ )
459
+ ) : null}
460
+ {onAskAgain ? (
461
+ <form
462
+ className="relative grid gap-1"
463
+ onSubmit={(e) => {
464
+ e.preventDefault();
465
+ onAskAgain(hint.trim());
466
+ }}
467
+ >
468
+ <div className="flex gap-2">
469
+ <label htmlFor={hintId} className="sr-only">
470
+ A hint for the agent
471
+ </label>
472
+ <Input id={hintId} value={hint} onChange={(e) => setHint(e.target.value)} placeholder={hintPlaceholder} className="min-w-0 flex-1" />
473
+ <Button type="submit" size="sm" disabled={busy}>
474
+ <AgentMark />
475
+ {askLabel}
476
+ </Button>
477
+ </div>
478
+ {askCost || askNote ? <span className="text-xs text-muted-foreground">{[askCost, askNote].filter(Boolean).join(". ")}</span> : null}
479
+ </form>
480
+ ) : null}
481
+ </div>
482
+ );
483
+ }
@@ -0,0 +1,24 @@
1
+ "use client";
2
+
3
+ import { AnswerCell } from "./agent-column";
4
+ import { answerWords } from "./model";
5
+
6
+ // A column type for the spreadsheet block (and base-view, which passes
7
+ // `types` through): the value is an answer, drawn by AnswerCell. A person
8
+ // who types in the cell sets their own value (setBy "person"), which the
9
+ // app saves and the agent never overwrites.
10
+ //
11
+ // <Spreadsheet types={{ answer: answerColumnType }}
12
+ // columns={[{ key: "headcount", name: "Headcount", type: "answer", answerType: "number" }]} … />
13
+ export const answerColumnType = {
14
+ label: "Agent answer",
15
+ icon: "sparkles",
16
+ width: 200,
17
+ editor: "text",
18
+ empty: (v) => v == null || (v.value == null && v.status == null),
19
+ parse: (text) => ({ value: { status: "found", value: String(text ?? "").trim(), setBy: "person" } }),
20
+ toText: (v) => (v?.value == null ? "" : String(v.value)),
21
+ format: (v) => (v?.value != null ? String(v.value) : answerWords(v)),
22
+ compare: (a, b) => String(a?.value ?? "").localeCompare(String(b?.value ?? ""), undefined, { numeric: true }),
23
+ render: (v, column) => <AnswerCell answer={v} type={column?.answerType ?? "text"} lines={1} />,
24
+ };