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,465 @@
1
+ "use client";
2
+
3
+ // Passages of text with notes in the margin, level with their words. Each
4
+ // passage is a row: the words on one side, the notes about them on the
5
+ // other (stacked under the words when the container is narrow). A note says
6
+ // where the words came from (source), that they need a look (flag), that
7
+ // they were cut and why (cut), or what someone thought (comment); an app
8
+ // can add kinds. The words a note is about are marked in the passage, and
9
+ // the selected note and its passage are linked: click either, or press J
10
+ // and K to walk the notes that still need a person.
11
+ //
12
+ // Props in, callbacks out: the block never reads or writes data. A press on
13
+ // a note's button calls onAction(note, actionId); the app does the work and
14
+ // hands back changed notes. README.md beside this file is the contract.
15
+
16
+ import { useEffect, useMemo, useRef, useState } from "react";
17
+ import { Badge, Button, Empty, Icon, Kbd, Notice, Skeleton, cx } from "../../ui";
18
+ import { AgentMark } from "../agent-marks";
19
+ import { actionsOf, arrangeNotes, countNotes, countWords, cycleNote, inlineMarks, isSettled, noteLook, resolveKinds, walkNext } from "./margin-model";
20
+
21
+ // Literal class names, so Tailwind sees every one of them.
22
+ const GRID = {
23
+ right: {
24
+ sm: "@2xl:grid-cols-[minmax(0,1fr)_15rem]",
25
+ md: "@2xl:grid-cols-[minmax(0,1fr)_18rem]",
26
+ lg: "@2xl:grid-cols-[minmax(0,1fr)_22rem]",
27
+ },
28
+ left: {
29
+ sm: "@2xl:grid-cols-[15rem_minmax(0,1fr)]",
30
+ md: "@2xl:grid-cols-[18rem_minmax(0,1fr)]",
31
+ lg: "@2xl:grid-cols-[22rem_minmax(0,1fr)]",
32
+ },
33
+ };
34
+
35
+ const TEXT = { sm: "text-sm leading-relaxed", md: "text-base leading-relaxed", lg: "text-lg leading-relaxed" };
36
+
37
+ // The coloured bar down a note's inline-start edge.
38
+ const BAR = {
39
+ neutral: "bg-muted-foreground",
40
+ primary: "bg-primary",
41
+ info: "bg-info",
42
+ success: "bg-success",
43
+ warning: "bg-warning",
44
+ danger: "bg-destructive",
45
+ };
46
+ const BAR_HUE = { 1: "bg-chart-1", 2: "bg-chart-2", 3: "bg-chart-3", 4: "bg-chart-4", 5: "bg-chart-5" };
47
+
48
+ const DECO = {
49
+ neutral: "decoration-muted-foreground",
50
+ primary: "decoration-primary",
51
+ info: "decoration-info",
52
+ success: "decoration-success",
53
+ warning: "decoration-warning",
54
+ danger: "decoration-destructive",
55
+ };
56
+ const DECO_HUE = { 1: "decoration-chart-1", 2: "decoration-chart-2", 3: "decoration-chart-3", 4: "decoration-chart-4", 5: "decoration-chart-5" };
57
+
58
+ const WASH = {
59
+ neutral: "bg-muted",
60
+ primary: "bg-primary/15",
61
+ info: "bg-info/15",
62
+ success: "bg-success/15",
63
+ warning: "bg-warning/15",
64
+ danger: "bg-destructive/15",
65
+ };
66
+ const WASH_HUE = { 1: "bg-chart-1/15", 2: "bg-chart-2/15", 3: "bg-chart-3/15", 4: "bg-chart-4/15", 5: "bg-chart-5/15" };
67
+
68
+ const deco = (look) => (look.hue ? DECO_HUE[look.hue] : DECO[look.tone]);
69
+ const wash = (look) => (look.hue ? WASH_HUE[look.hue] : WASH[look.tone]);
70
+
71
+ const domId = (root, kind, id) => `${root}-${kind}-${String(id).replace(/[^a-zA-Z0-9_-]/g, "_")}`;
72
+
73
+ const reducedMotion = () => typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
74
+
75
+ /** Words typed into, or a key meant for something else: J and K are left alone. */
76
+ function isTyping(el) {
77
+ if (!el || el.nodeType !== 1) return false;
78
+ return Boolean(el.closest?.("input, textarea, select, [contenteditable=''], [contenteditable='true']"));
79
+ }
80
+
81
+ /** The words of a passage, with the marks the notes make on them. */
82
+ function Words({ passage, notes, kinds, selectedId, rootId, as: Tag = "p" }) {
83
+ const looks = useMemo(() => new Map(notes.map((n) => [n.id, noteLook(n, kinds)])), [notes, kinds]);
84
+ const { segments } = useMemo(() => inlineMarks(passage.text, notes, (n) => looks.get(n.id)?.mark ?? "none"), [passage.text, notes, looks]);
85
+ if (passage.node != null) {
86
+ const struck = notes.find((n) => !isSettled(n) && looks.get(n.id)?.mark === "strike");
87
+ const look = struck ? looks.get(struck.id) : null;
88
+ return <div className={cx("min-w-0 break-words", look && cx("text-muted-foreground line-through decoration-2", deco(look)))}>{passage.node}</div>;
89
+ }
90
+ return (
91
+ <Tag className={cx("m-0 min-w-0 break-words", Tag !== "p" && "text-[1.05em] font-semibold leading-snug")}>
92
+ {segments.map((seg, i) => {
93
+ if (!seg.ids.length) return <span key={i}>{seg.text}</span>;
94
+ const id = seg.ids.includes(selectedId) ? selectedId : seg.ids[0];
95
+ const look = looks.get(id);
96
+ const on = seg.ids.includes(selectedId);
97
+ const common = { "data-note": id, "data-selected": on ? "" : undefined, "aria-describedby": domId(rootId, "note", id) };
98
+ if (look.mark === "strike")
99
+ return (
100
+ <del key={i} {...common} className={cx("rounded-sm text-muted-foreground line-through decoration-2", deco(look), on && wash(look))}>
101
+ <span className="sr-only">{look.label}: </span>
102
+ {seg.text}
103
+ </del>
104
+ );
105
+ return (
106
+ <mark
107
+ key={i}
108
+ {...common}
109
+ className={cx(
110
+ "rounded-sm text-inherit",
111
+ look.mark === "highlight" || on ? wash(look) : "bg-transparent",
112
+ look.mark === "underline" && "underline decoration-dotted decoration-2 underline-offset-4",
113
+ look.mark === "wavy" && "underline decoration-wavy decoration-1 underline-offset-4",
114
+ look.mark !== "highlight" && deco(look),
115
+ )}
116
+ >
117
+ <span className="sr-only">{look.label}: </span>
118
+ {seg.text}
119
+ </mark>
120
+ );
121
+ })}
122
+ </Tag>
123
+ );
124
+ }
125
+
126
+ /** One note. */
127
+ function Note({ note, kinds, selected, busy, error, readOnly, canAct, onSelect, onPress, rootId, cardRef, quoteShown }) {
128
+ const look = noteLook(note, kinds);
129
+ const settled = isSettled(note);
130
+ const actions = canAct ? actionsOf(note, kinds, { readOnly }) : [];
131
+ const agent = note.by === "agent" || note.by?.agent === true;
132
+ const byName = typeof note.by === "string" ? (note.by === "agent" ? "" : note.by) : (note.by?.name ?? "");
133
+ const showReopen = settled && canAct && !readOnly && look.reopen;
134
+
135
+ return (
136
+ <article
137
+ ref={cardRef}
138
+ id={domId(rootId, "note", note.id)}
139
+ tabIndex={-1}
140
+ data-note={note.id}
141
+ data-kind={note.kind}
142
+ data-selected={selected ? "" : undefined}
143
+ aria-current={selected ? "true" : undefined}
144
+ aria-label={note.title && note.title !== look.label ? `${look.label}: ${note.title}` : look.label}
145
+ onClick={() => onSelect(note.id)}
146
+ className={cx(
147
+ "relative grid min-w-0 gap-1.5 overflow-hidden rounded-lg border border-border py-3 pe-3 ps-4 text-sm text-card-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring",
148
+ selected && "ring-2 ring-ring",
149
+ settled ? "bg-muted" : "bg-card",
150
+ )}
151
+ >
152
+ <span aria-hidden="true" className={cx("absolute inset-y-0 start-0 w-1", look.hue ? BAR_HUE[look.hue] : BAR[look.tone], settled && "opacity-40")} />
153
+ {settled ? (
154
+ <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
155
+ <Icon name="check" size={14} className="shrink-0 text-success" />
156
+ <span className="text-[13px] font-medium">{note.answer || "Settled"}</span>
157
+ {note.at ? <span className="text-xs text-muted-foreground">{note.at}</span> : null}
158
+ {showReopen ? (
159
+ <Button size="sm" variant="link" tone="muted" loading={busy === "reopen"} aria-label={`${look.reopen.label ?? "Reopen"}: ${look.label}`} onClick={() => onPress(note, "reopen")}>
160
+ {look.reopen.label ?? "Reopen"}
161
+ </Button>
162
+ ) : null}
163
+ </div>
164
+ ) : (
165
+ <>
166
+ <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
167
+ <Badge variant="soft" tone={look.hue ? undefined : look.tone} hue={look.hue ?? undefined} className="gap-1">
168
+ <Icon name={look.icon} size={12} aria-hidden="true" />
169
+ {look.label}
170
+ </Badge>
171
+ {agent ? <AgentMark label="Raised by the agent" /> : null}
172
+ {byName ? <span className="text-xs text-muted-foreground">{byName}</span> : null}
173
+ {note.at ? <span className="text-xs tabular-nums text-muted-foreground">{note.at}</span> : null}
174
+ </div>
175
+ {note.title ? <p className="m-0 font-medium">{note.title}</p> : null}
176
+ {note.meta ? <p className="m-0 text-xs text-muted-foreground">{note.meta}</p> : null}
177
+ {quoteShown && note.quote ? <p className="m-0 break-words text-[13px] italic text-muted-foreground">{`“${note.quote}”`}</p> : null}
178
+ {note.text ? <p className="m-0 break-words">{note.text}</p> : null}
179
+ {note.detail ? <p className="m-0 mt-0.5 break-words border-t border-dashed border-border pt-1.5 text-[13px] leading-snug text-muted-foreground">{note.detail}</p> : null}
180
+ {note.href ? (
181
+ <a href={note.href} target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 justify-self-start rounded-sm text-xs font-medium text-primary underline-offset-4 hover:underline focus-visible:ring-2 focus-visible:ring-ring">
182
+ {note.hrefLabel || "Open the source"}
183
+ <Icon name="external" size={12} aria-hidden="true" />
184
+ </a>
185
+ ) : null}
186
+ {note.locked ? (
187
+ <p className="m-0 flex items-start gap-1.5 text-xs text-muted-foreground">
188
+ <Icon name="lock" size={12} className="mt-0.5 shrink-0" />
189
+ <span className="min-w-0">{note.locked}</span>
190
+ </p>
191
+ ) : null}
192
+ {actions.length ? (
193
+ <div className="flex flex-wrap items-center gap-1.5 pt-0.5">
194
+ {actions.map((a) => (
195
+ <Button
196
+ key={a.id}
197
+ size="sm"
198
+ variant={a.variant || "secondary"}
199
+ icon={a.icon}
200
+ loading={busy === a.id}
201
+ disabled={Boolean(busy) && busy !== a.id}
202
+ aria-label={`${a.label}: ${look.label}${note.title ? `, ${note.title}` : ""}`}
203
+ onClick={() => onPress(note, a.id)}
204
+ >
205
+ {a.label}
206
+ </Button>
207
+ ))}
208
+ </div>
209
+ ) : null}
210
+ </>
211
+ )}
212
+ {error ? (
213
+ <p role="alert" className="m-0 text-xs text-destructive">
214
+ {error}
215
+ </p>
216
+ ) : null}
217
+ </article>
218
+ );
219
+ }
220
+
221
+ /** Rows of grey bars where the passages and their notes will be. */
222
+ function Loading({ cols }) {
223
+ return (
224
+ <div role="status" aria-label="Loading" aria-busy="true" className={cx("grid grid-cols-[minmax(0,1fr)] gap-x-6 gap-y-4", cols)}>
225
+ {[0, 1, 2].map((i) => (
226
+ <div key={i} className="contents">
227
+ <div className="grid min-w-0 gap-2 py-2">
228
+ <Skeleton className="w-full" />
229
+ <Skeleton className="w-11/12" />
230
+ <Skeleton className="w-2/3" />
231
+ </div>
232
+ <div className="grid min-w-0 content-start py-2">
233
+ <Skeleton shape="rect" className="h-16 w-full" />
234
+ </div>
235
+ </div>
236
+ ))}
237
+ </div>
238
+ );
239
+ }
240
+
241
+ /**
242
+ * passages [{ id, text | node, lead?, label?, level? }]: the words. `lead` is a
243
+ * short figure before them (a time, a number); `label` a name above
244
+ * (a speaker, a section); `level` 2 · 3 · 4 draws the text as a heading.
245
+ * notes [{ id, passage, kind, title?, meta?, text?, detail?, quote?, by?, at?,
246
+ * href?, hrefLabel?, locked?, state?, answer?, actions?, tone?, hue?,
247
+ * mark?, label? }]
248
+ * selected / defaultSelected / onSelect(id | null) the selected note
249
+ * onAction(note, actionId) async → { ok } | { ok: false, error }
250
+ * kinds changes to the built-in kinds, or new ones
251
+ * side right (default) · left: which side of the words the margin is on
252
+ * marginWidth sm · md (default) · lg
253
+ * marginTitle the margin's heading
254
+ * showNotes false hides the margin (default true)
255
+ * textSize sm · md (default) · lg
256
+ * status ready (default) · loading · failed, with `error` and onRetry
257
+ * readOnly notes to read: no buttons
258
+ * keys J and K walk the notes (default true)
259
+ */
260
+ export function MarginNotes({
261
+ passages = [],
262
+ notes = [],
263
+ selected,
264
+ defaultSelected = null,
265
+ onSelect,
266
+ onAction,
267
+ kinds: kindChanges,
268
+ side = "right",
269
+ marginWidth = "md",
270
+ marginTitle,
271
+ showNotes = true,
272
+ textSize = "md",
273
+ status = "ready",
274
+ error,
275
+ onRetry,
276
+ readOnly = false,
277
+ keys = true,
278
+ noNotes = "Nothing in the margin.",
279
+ orphanTitle = "Not tied to a passage",
280
+ emptyTitle = "Nothing to read yet",
281
+ emptyBody,
282
+ countLabels,
283
+ label = "Passages with notes in the margin",
284
+ className,
285
+ }) {
286
+ const rootId = useRef(`mn${Math.random().toString(36).slice(2, 8)}`).current;
287
+ const kinds = useMemo(() => resolveKinds(kindChanges), [kindChanges]);
288
+ const { byPassage, ordered, orphans } = useMemo(() => arrangeNotes(passages, notes), [passages, notes]);
289
+ const counts = useMemo(() => countNotes(notes), [notes]);
290
+
291
+ const [inner, setInner] = useState(defaultSelected);
292
+ const raw = selected === undefined ? inner : selected;
293
+ const current = raw != null && ordered.some((n) => n.id === raw) ? raw : null;
294
+ const position = current == null ? 0 : ordered.findIndex((n) => n.id === current) + 1;
295
+
296
+ const [busy, setBusy] = useState({});
297
+ const [errors, setErrors] = useState({});
298
+ const cards = useRef(new Map());
299
+ const rows = useRef(new Map());
300
+ const frame = useRef(0);
301
+ useEffect(() => () => cancelAnimationFrame(frame.current), []);
302
+
303
+ const choose = (id, bring = false) => {
304
+ if (selected === undefined) setInner(id);
305
+ onSelect?.(id);
306
+ if (bring && id != null) {
307
+ cancelAnimationFrame(frame.current);
308
+ frame.current = requestAnimationFrame(() => {
309
+ cards.current.get(id)?.focus({ preventScroll: true });
310
+ (rows.current.get(ordered.find((n) => n.id === id)?.passage) ?? cards.current.get(id))?.scrollIntoView({ block: "nearest", behavior: reducedMotion() ? "auto" : "smooth" });
311
+ });
312
+ }
313
+ };
314
+
315
+ async function press(note, actionId) {
316
+ if (!onAction) return;
317
+ const key = note.id;
318
+ if (busy[key]) return;
319
+ setBusy((b) => ({ ...b, [key]: actionId }));
320
+ setErrors((e) => ({ ...e, [key]: null }));
321
+ let r;
322
+ try {
323
+ r = await onAction(note, actionId);
324
+ } catch (e) {
325
+ r = { ok: false, error: e?.message ?? String(e) };
326
+ }
327
+ setBusy((b) => ({ ...b, [key]: null }));
328
+ if (r && r.ok === false) setErrors((e) => ({ ...e, [key]: r.error || "That did not work. Try again." }));
329
+ }
330
+
331
+ function onKeyDown(e) {
332
+ if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey || isTyping(e.target)) return;
333
+ if (e.key === "Escape" && current != null) {
334
+ e.preventDefault();
335
+ choose(null);
336
+ } else if (keys && showNotes && (e.key === "j" || e.key === "J" || e.key === "k" || e.key === "K")) {
337
+ const next = walkNext(ordered, current, e.key.toLowerCase() === "j" ? 1 : -1);
338
+ if (next == null) return;
339
+ e.preventDefault();
340
+ choose(next, true);
341
+ }
342
+ }
343
+
344
+ const cols = showNotes ? (GRID[side] ?? GRID.right)[marginWidth] ?? GRID.right.md : "";
345
+ const marginFirst = side === "left";
346
+ const typeSize = TEXT[textSize] ?? TEXT.md;
347
+ const summary = countWords(counts, countLabels);
348
+
349
+ const noteList = (list) =>
350
+ list.map((n) => (
351
+ <Note
352
+ key={n.id}
353
+ note={n}
354
+ kinds={kinds}
355
+ selected={n.id === current}
356
+ busy={busy[n.id]}
357
+ error={errors[n.id]}
358
+ readOnly={readOnly}
359
+ canAct={Boolean(onAction)}
360
+ onSelect={(id) => choose(id)}
361
+ onPress={press}
362
+ rootId={rootId}
363
+ cardRef={(el) => (el ? cards.current.set(n.id, el) : cards.current.delete(n.id))}
364
+ quoteShown={passages.find((p) => p.id === n.passage)?.node != null}
365
+ />
366
+ ));
367
+
368
+ let body;
369
+ if (status === "loading") body = <Loading cols={cols} />;
370
+ else if (status === "failed")
371
+ body = (
372
+ <Notice tone="danger" title="The notes did not load" action={onRetry ? <Button size="sm" icon="refresh" onClick={onRetry}>Try again</Button> : null}>
373
+ {error || "Something went wrong. Try again."}
374
+ </Notice>
375
+ );
376
+ else if (!passages.length) body = <Empty icon="message-square" title={emptyTitle} body={emptyBody} />;
377
+ else
378
+ body = (
379
+ <>
380
+ <ol className="m-0 grid list-none gap-y-1 p-0">
381
+ {passages.map((p) => {
382
+ const mine = byPassage.get(p.id) ?? [];
383
+ const selectedHere = mine.some((n) => n.id === current);
384
+ const Heading = p.level >= 2 && p.level <= 4 ? `h${p.level}` : null;
385
+ const onPassage = mine.length ? () => choose(cycleNote(mine, current)) : undefined;
386
+ return (
387
+ <li
388
+ key={p.id}
389
+ ref={(el) => (el ? rows.current.set(p.id, el) : rows.current.delete(p.id))}
390
+ data-passage={p.id}
391
+ data-selected={selectedHere ? "" : undefined}
392
+ className={cx("grid grid-cols-[minmax(0,1fr)] gap-x-6 gap-y-2 py-1.5", cols)}
393
+ >
394
+ <div
395
+ {...(mine.length
396
+ ? {
397
+ tabIndex: 0,
398
+ onClick: onPassage,
399
+ onKeyDown: (e) => {
400
+ if ((e.key === "Enter" || e.key === " ") && e.target === e.currentTarget) {
401
+ e.preventDefault();
402
+ onPassage();
403
+ }
404
+ },
405
+ "aria-label": `${p.label ? `${p.label}. ` : ""}${mine.length} ${mine.length === 1 ? "note" : "notes"}. Press Enter to select.`,
406
+ role: "group",
407
+ }
408
+ : {})}
409
+ className={cx(
410
+ "flex min-w-0 gap-3 rounded-md px-2 py-1.5 outline-none",
411
+ typeSize,
412
+ marginFirst && showNotes && "@2xl:order-last",
413
+ mine.length && "cursor-pointer focus-visible:ring-2 focus-visible:ring-ring",
414
+ selectedHere ? "bg-accent" : mine.length ? "hover:bg-accent/50" : "",
415
+ )}
416
+ >
417
+ {p.lead ? <span className="w-12 shrink-0 pt-0.5 text-xs tabular-nums text-muted-foreground">{p.lead}</span> : null}
418
+ <div className="grid min-w-0 grow gap-0.5">
419
+ {p.label ? <span className="text-[13px] font-semibold leading-snug">{p.label}</span> : null}
420
+ <Words passage={p} notes={mine} kinds={kinds} selectedId={current} rootId={rootId} as={Heading ?? "p"} />
421
+ </div>
422
+ </div>
423
+ {showNotes ? <div className={cx("grid min-w-0 content-start gap-2", marginFirst && "@2xl:order-first")}>{noteList(mine)}</div> : null}
424
+ </li>
425
+ );
426
+ })}
427
+ </ol>
428
+ {showNotes && orphans.length ? (
429
+ <section aria-label={orphanTitle} className="mt-2 grid gap-2 border-t border-border pt-3">
430
+ <h3 className="m-0 text-xs font-medium uppercase tracking-wide text-muted-foreground">{orphanTitle}</h3>
431
+ <div className="grid grid-cols-[minmax(0,1fr)] gap-2 @2xl:grid-cols-2">{noteList(orphans)}</div>
432
+ </section>
433
+ ) : null}
434
+ </>
435
+ );
436
+
437
+ return (
438
+ <section
439
+ aria-label={label}
440
+ tabIndex={0}
441
+ onKeyDown={onKeyDown}
442
+ className={cx("@container grid min-w-0 grid-cols-[minmax(0,1fr)] gap-3 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ring", className)}
443
+ >
444
+ {showNotes && status === "ready" && passages.length > 0 && Boolean(marginTitle || summary || (keys && ordered.length > 0) || !notes.length) ? (
445
+ <header className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
446
+ {marginTitle ? <h2 className="m-0 text-base font-semibold leading-tight">{marginTitle}</h2> : null}
447
+ <p className="m-0 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
448
+ {summary ? <span>{summary}</span> : !notes.length ? <span>{noNotes}</span> : null}
449
+ {keys && ordered.length ? (
450
+ <span className="hidden items-center gap-1 @2xl:inline-flex">
451
+ <Kbd>J</Kbd>
452
+ <Kbd>K</Kbd>
453
+ <span>next and previous note</span>
454
+ </span>
455
+ ) : null}
456
+ </p>
457
+ </header>
458
+ ) : null}
459
+ <p role="status" aria-live="polite" className="sr-only">
460
+ {current != null ? `Note ${position} of ${ordered.length}` : ""}
461
+ </p>
462
+ {body}
463
+ </section>
464
+ );
465
+ }
@@ -96,7 +96,9 @@ string, or nothing (a fresh map). The component runs it on `value`.
96
96
  - `placeholder` — what an empty topic shows while it is typed (default
97
97
  "New topic").
98
98
  - `height` — px or any CSS length, default `600`. A height class in
99
- `className` (`h-dvh`, `h-full`, `flex-1`) replaces it.
99
+ `className` (`h-full`, `min-h-0 flex-1`) replaces it: `min-h-0 flex-1`
100
+ fills what the surface has left (the Example). Never `h-dvh` or a `vh`
101
+ height, which `npm run check` refuses.
100
102
  - `label` — the map's accessible name (default "Mind map").
101
103
  - `onSelectionChange(topic | null)` — the selected topic changed (a side
102
104
  panel with its notes).
@@ -186,7 +188,7 @@ function PlanMap({ plan }) {
186
188
  onChange={setMap}
187
189
  onSave={(m) => updateRow({ source: "plans", id: plan.id, patch: { map: m, map_text: mindMapToText(m) } })}
188
190
  label={`${plan.name} map`}
189
- className="h-[calc(100dvh-8rem)]"
191
+ className="min-h-0 flex-1"
190
192
  />
191
193
  );
192
194
  }
@@ -0,0 +1,177 @@
1
+ # NeedsYou
2
+
3
+ What waits on the member, drawn inside the app. Four pieces:
4
+
5
+ - **NeedsYou** — the queue. The agent's questions and its yeses on this
6
+ app. A question is **answered in place** (`QuestionBox`); a yes is the
7
+ `approval` block's press frame (`renderYes`); anything else the app
8
+ cannot settle (connecting an account, spending money, several questions
9
+ at once) opens the desk with one press.
10
+ - **QuestionBox** — the agent's question, answered where it was asked: its
11
+ options, one press each, and a box for the member's own words where the
12
+ question welcomes them.
13
+ - **WaitingYes** — the frozen-text card. What goes out, frozen while the
14
+ ask waits, then "Waiting for your yes on the desk", **Open the desk**
15
+ and **Take the ask back**. It is also what the `approval` block shows
16
+ when its press frame cannot load.
17
+ - **AgentWorking** — the strip while the agent works: what it is on now,
18
+ **Stop**, and "Stop keeps everything written so far".
19
+
20
+ An answer is words, so the app takes it. The yes is not: the app's own
21
+ code never draws an Approve. The press is the Makersclaw-held frame of the
22
+ `approval` block, which app code cannot script. Connecting an account and
23
+ money stay on the desk.
24
+
25
+ ```jsx
26
+ import { NeedsYou, QuestionBox, WaitingYes, AgentWorking } from "../components/blocks/needs-you"; // a Makersclaw app ("./blocks/needs-you" from components/)
27
+ import { NeedsYou, QuestionBox, WaitingYes, AgentWorking } from "@/components/makersclaw/blocks/needs-you"; // a shadcn project
28
+ ```
29
+
30
+ Client components. The Example is at the end.
31
+
32
+ ## Which hook feeds it
33
+
34
+ ```js
35
+ const needs = useNeedsYou(); // lib/hooks.js
36
+ // → { items, working, open(item), answer(item, …), takeBack(item), stop(request), loading, error, unavailable, reload }
37
+ ```
38
+
39
+ It reads `GET _claw/requests`: only the member's own asks (`mine`).
40
+ `items` are the asks that wait on them; `working` are their asks that
41
+ run now. Each item says how the app can settle it: `via` is `"answer"` (a
42
+ question: `answer(item, { optionId | text })`, which is
43
+ `POST _claw/requests/:id/answer`), `"press"` (the one ask's yes: the
44
+ `approval` block, `useApproval(item.id)`) or `null` (the desk: `open`).
45
+ `takeBack` and `stop` are `POST _claw/requests/:id/stop`.
46
+
47
+ ## Props
48
+
49
+ ### NeedsYou
50
+
51
+ - `items` — `needs.items`: `[{ id, request, kind, text, title, at, via,
52
+ options, free, needsAt }]`. `kind` is `question`, `yes` or `spend`
53
+ ("Waiting for your yes on the desk · Open the desk" when the app cannot
54
+ take it), `connect` ("Connect on the desk"); any other word reads "Needs
55
+ you on the desk". `text` is the agent's words, `title` the ask's, `at`
56
+ when (words, a `Date` or ISO).
57
+ - `onOpen(item)` — `needs.open`. The press of everything the app cannot
58
+ settle itself. Without it those rows have no press.
59
+ - `onAnswer(item, { optionId | text })` — `needs.answer`. An item with
60
+ `via: "answer"` then shows its `QuestionBox`; without it that item opens
61
+ the desk, as before.
62
+ - `renderYes(item)` — draws the yes of an item with `via: "press"`: a
63
+ component of yours that calls `useApproval(item.id)` and returns the
64
+ `approval` block. Without it that item opens the desk.
65
+ - `empty` — the line when nothing waits. Default "Nothing waits on you
66
+ here." `false` draws nothing at all when the list is empty.
67
+ - `title` — the head. Default "Needs you"; `null` for none.
68
+ - `loading` — `needs.loading`: skeleton lines before the first read.
69
+ - `unavailable` — `needs.unavailable`: a quiet "not connected yet".
70
+ - `className` — layout around it. Never colour.
71
+
72
+ ### QuestionBox
73
+
74
+ - `options` — `[{ id, label }]` the question offers (none: words only).
75
+ A lone press answers on the spot, as the desk's form does.
76
+ - `free` — `false` when the question takes one of its options only
77
+ (default: words are welcome).
78
+ - `onAnswer({ optionId } | { text })` — `needs.answer(item, …)` or
79
+ `chat.answer(…)`; async, answers `{ ok }` or `{ ok: false, error }`. A
80
+ refusal is shown as the door words it.
81
+ - `placeholder`, `sendLabel`, `className`.
82
+
83
+ ### WaitingYes
84
+
85
+ - `title` — what it is ("How to cover a sudden sick day").
86
+ - `frozen` — what goes out, exactly as it will go (text or a node). It is
87
+ drawn frozen (muted, with a lock) while the ask waits.
88
+ - `kicker` — the line over it. Default "Ready to send".
89
+ - `state` — `ready` (nothing asked yet: the text only, no state line) ·
90
+ `waiting` (default) · `approved` ("You said yes · the agent is on it")
91
+ · `declined` · `taken` · `failed` (with `error`).
92
+ - `body` — one sentence under "Waiting for your yes on the desk", in the
93
+ app's words: say what the agent does after the yes.
94
+ - `onOpen()` — opens the desk on this ask (`() => needs.open(item)`).
95
+ - `onTakeBack()` — async, answers `{ ok: true }` or `{ ok: false, error
96
+ }` (`() => needs.takeBack(item)`). It stops the ask while the agent
97
+ has not acted; the card then says "Taken back. Nothing went out."
98
+ Without it there is no Take back.
99
+ - `takeBackLabel` — default "Take the ask back".
100
+
101
+ ### AgentWorking
102
+
103
+ - `words` — what the agent is doing, in the app's words ("Writing the
104
+ draft"). Default "Working on it".
105
+ - `steps` — `[{ label, status }]` (`running` · `done` · `failed`): the
106
+ running step shows, with "2 of 6 steps done".
107
+ - `onStop()` — `() => needs.stop(request)` or `chat.stop`. It may be
108
+ async and answer `{ ok }` or `{ ok: false, error }`: the button spins
109
+ while it is out and a failure says why. Without it there is no Stop.
110
+ - `stopping` — true while a stop you track yourself is out.
111
+ - `stopHint` — default "Stop keeps everything written so far"; `null`
112
+ for none.
113
+
114
+ ## Who may do what
115
+
116
+ - Every member sees only their own asks: the door lists `mine`.
117
+ - Stop and Take back: the asker, an owner, an admin, or the app's owner
118
+ (`mayStop` on the request). Give `onStop`/`onTakeBack` only when the
119
+ request says the member may; the door refuses anyone else anyway.
120
+ - Only the member who asked answers a question or gives a yes; the door
121
+ refuses everyone else (owners and admins too), and a question answered
122
+ after it moved on (`needsAt`) is refused.
123
+ - The yes: the `approval` block's press frame, never these blocks.
124
+ - An account sign-in and money: the desk, always.
125
+
126
+ ## Never
127
+
128
+ - **Never an Approve, a Yes, or a Send that gives the yes.** The yes is
129
+ the `approval` block's frame; this block's only press toward it is Open
130
+ the desk, when the frame cannot load.
131
+ - Never answer the one ask (a yes) through `QuestionBox`: the door refuses
132
+ it (`needs_a_press`).
133
+ - Never let the frozen text be edited while the ask waits. To change it,
134
+ take the ask back first.
135
+ - Never show another member's asks here.
136
+
137
+ ## Example
138
+
139
+ A post that waits for its yes, the strip while the agent works, and the
140
+ queue on the home screen.
141
+
142
+ ```jsx
143
+ "use client";
144
+ import { useNeedsYou } from "../lib/hooks";
145
+ import { NeedsYou, WaitingYes, AgentWorking } from "../components/blocks/needs-you";
146
+
147
+ export function PostStatus({ post }) {
148
+ const needs = useNeedsYou();
149
+ const item = needs.items.find((i) => i.request?.id === post.request_id);
150
+ const running = needs.working.find((r) => r.id === post.request_id);
151
+ if (running) return <AgentWorking words="Putting the post on Webflow" onStop={() => needs.stop(running)} />;
152
+ return (
153
+ <WaitingYes
154
+ title={post.title}
155
+ frozen={post.body}
156
+ state={item ? "waiting" : "ready"}
157
+ body="Say yes there, and the agent makes this one post live on Webflow, then adds its link here."
158
+ onOpen={item ? () => needs.open(item) : undefined}
159
+ onTakeBack={item ? () => needs.takeBack(item) : undefined}
160
+ />
161
+ );
162
+ }
163
+
164
+ export function Waiting() {
165
+ const needs = useNeedsYou();
166
+ return (
167
+ <NeedsYou
168
+ items={needs.items}
169
+ onOpen={needs.open}
170
+ onAnswer={needs.answer}
171
+ renderYes={(item) => <SendCard item={item} />} // an Approval card, see the approval block
172
+ loading={needs.loading}
173
+ unavailable={needs.unavailable}
174
+ />
175
+ );
176
+ }
177
+ ```