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,374 @@
1
+ "use client";
2
+
3
+ // What starts an automation. Eight ways, the platform tells which it runs:
4
+ // by hand; on a schedule in the team's time zone; when an app sends an
5
+ // event; when one of an app's actions finishes; when a record is added or
6
+ // changed; when the automation's own web address is called; when another
7
+ // automation finishes. A connection's own events (a new mail) are listed as
8
+ // "soon", with what to use until then.
9
+ //
10
+ // The schedule is offered in the shapes people ask for ("every weekday at
11
+ // 07:00") and kept as a five-field cron; anything the picker cannot read
12
+ // back stays the custom cron it was.
13
+ //
14
+ // Props in, callbacks out; the definition's trigger is one of
15
+ // { type: "manual" }
16
+ // { type: "schedule", cron, tz }
17
+ // { type: "event", topic, app? }
18
+ // { type: "action", action, app? }
19
+ // { type: "record", kinds?, ops?, app? }
20
+ // { type: "webhook" }
21
+ // { type: "automation", key, when }
22
+
23
+ import { useId, useState } from "react";
24
+ import { Button, Checkbox, Field, Input, Select, Switch, TimeInput, cx } from "../../ui";
25
+ import { Glyph, SidePanel, WEEKDAYS, cronFromParts, cronWords, parseTime, partsFromCron, timeText, triggerGlyph, triggerTitle, triggerWords } from "../automation-model";
26
+
27
+ const FREQS = [
28
+ { value: "daily", label: "Every day" },
29
+ { value: "weekdays", label: "Every weekday" },
30
+ { value: "weekly", label: "Every week" },
31
+ { value: "hourly", label: "Every hour" },
32
+ { value: "custom", label: "Another schedule" },
33
+ ];
34
+
35
+ /** What a platform without the newer triggers offers: two ways, and the rest said honestly. */
36
+ const FALLBACK_CHOICES = [
37
+ { type: "manual", label: "By hand", hint: "Someone presses Run, or the agent runs it.", available: true },
38
+ { type: "schedule", label: "On a schedule", hint: "Every day, every weekday, every hour.", available: true },
39
+ ];
40
+ const LATER = [
41
+ { id: "record", label: "When something is added", hint: "A new person, a new row, a new message." },
42
+ { id: "automation", label: "From another automation", hint: "One flow starts the next." },
43
+ ];
44
+
45
+ /** A fresh trigger of a type, with what the platform lists first filled in. */
46
+ function startOf(type, { app, other }) {
47
+ switch (type) {
48
+ case "schedule":
49
+ return { type, cron: "0 7 * * 1-5", tz: "team" };
50
+ case "event":
51
+ return { type, topic: app?.topics?.[0] ?? "", ...(app && !app.own ? { app: app.name } : {}) };
52
+ case "action":
53
+ return { type, action: app?.actions?.[0]?.name ?? "", ...(app && !app.own ? { app: app.name } : {}) };
54
+ case "record":
55
+ return { type, ...(app && !app.own ? { app: app.name } : {}) };
56
+ case "automation":
57
+ return { type, key: other?.[0]?.key ?? "", when: "done" };
58
+ default:
59
+ return { type };
60
+ }
61
+ }
62
+
63
+ /** The ways, as a list of options for a Select: what is available, and the current one even if it is not. */
64
+ function optionsOf(choices, current) {
65
+ const list = choices.filter((c) => c.available);
66
+ if (current && !list.some((c) => c.type === current)) list.push({ type: current, label: triggerTitle(current), hint: "", available: true });
67
+ return list.map((c) => ({ value: c.type, label: c.label }));
68
+ }
69
+
70
+ function Schedule({ uid, trigger, readOnly, onChange }) {
71
+ const parts = partsFromCron(trigger.cron ?? "0 7 * * 1-5");
72
+ const apply = (next) => onChange({ type: "schedule", cron: cronFromParts({ ...parts, ...next }), tz: trigger.tz ?? "team" });
73
+ const words = cronWords(trigger.cron);
74
+ const team = !trigger.tz || trigger.tz === "team";
75
+ return (
76
+ <>
77
+ <Field id={`${uid}-freq`} label="How often">
78
+ <Select id={`${uid}-freq`} value={parts.freq} disabled={readOnly} options={FREQS} onChange={(e) => apply({ freq: e.target.value })} />
79
+ </Field>
80
+ {parts.freq === "weekly" ? (
81
+ <Field id={`${uid}-day`} label="On">
82
+ <Select id={`${uid}-day`} value={String(parts.weekday)} disabled={readOnly} options={WEEKDAYS.map((d, i) => ({ value: String(i), label: d }))} onChange={(e) => apply({ weekday: Number(e.target.value) })} />
83
+ </Field>
84
+ ) : null}
85
+ {parts.freq === "daily" || parts.freq === "weekdays" || parts.freq === "weekly" ? (
86
+ <Field id={`${uid}-time`} label="At">
87
+ <TimeInput
88
+ id={`${uid}-time`}
89
+ value={timeText(parts.hour, parts.minute)}
90
+ disabled={readOnly}
91
+ onChange={(e) => {
92
+ const t = parseTime(e.target.value);
93
+ if (t) apply(t);
94
+ }}
95
+ />
96
+ </Field>
97
+ ) : null}
98
+ {parts.freq === "hourly" ? (
99
+ <Field id={`${uid}-min`} label="Minutes past the hour">
100
+ <Input id={`${uid}-min`} type="number" min={0} max={59} inputMode="numeric" value={parts.minute} disabled={readOnly} onChange={(e) => apply({ minute: Number(e.target.value) || 0 })} />
101
+ </Field>
102
+ ) : null}
103
+ {parts.freq === "custom" ? (
104
+ <Field id={`${uid}-cron`} label="Schedule" hint="Five fields: minute, hour, day, month, weekday.">
105
+ <Input id={`${uid}-cron`} className="font-mono text-[13px]" value={trigger.cron} disabled={readOnly} placeholder="0 7 * * 1-5" onChange={(e) => onChange({ type: "schedule", cron: e.target.value, tz: trigger.tz })} />
106
+ </Field>
107
+ ) : null}
108
+ <Switch id={`${uid}-team`} checked={team} disabled={readOnly} label="In the team's time zone" onChange={(e) => onChange({ type: "schedule", cron: trigger.cron, tz: e.target.checked ? "team" : "UTC" })} />
109
+ <p className="m-0 -mt-2 text-xs text-muted-foreground">07:00 stays 07:00 through daylight saving. Turn off to name another zone.</p>
110
+ {!team ? (
111
+ <Field id={`${uid}-tz`} label="Time zone">
112
+ <Input id={`${uid}-tz`} className="font-mono text-[13px]" value={trigger.tz} disabled={readOnly} placeholder="America/New_York" onChange={(e) => onChange({ type: "schedule", cron: trigger.cron, tz: e.target.value })} />
113
+ </Field>
114
+ ) : null}
115
+ <p className="m-0 text-xs text-muted-foreground">{words ? `Runs ${words.charAt(0).toLowerCase()}${words.slice(1)}${team ? ", team time" : ""}.` : "That schedule cannot be read yet."}</p>
116
+ </>
117
+ );
118
+ }
119
+
120
+ /** Which app a team automation hears: one picked from the platform's list. An app's own has no choice. */
121
+ function AppField({ uid, trigger, apps, ownedByApp, readOnly, onApp, required }) {
122
+ if (ownedByApp || apps.length === 0) return null;
123
+ return (
124
+ <Field id={`${uid}-app`} label="In which app" hint={required ? undefined : "Leave it open to hear any app."}>
125
+ <Select
126
+ id={`${uid}-app`}
127
+ value={trigger.app ?? ""}
128
+ disabled={readOnly}
129
+ options={[{ value: "", label: required ? "Pick an app" : "Any app" }, ...apps.map((a) => ({ value: a.name, label: a.name }))]}
130
+ onChange={(e) => onApp(e.target.value)}
131
+ />
132
+ </Field>
133
+ );
134
+ }
135
+
136
+ function Webhook({ uid, hook, onRotate, readOnly, origin }) {
137
+ const [shown, setShown] = useState(null);
138
+ const [asking, setAsking] = useState(false);
139
+ const [busy, setBusy] = useState(false);
140
+ const [note, setNote] = useState(null);
141
+ if (!hook) {
142
+ return <p className="m-0 text-xs text-muted-foreground">Save it first. Its web address is made when it exists, and the secret after that.</p>;
143
+ }
144
+ const base = (origin ?? (typeof window !== "undefined" ? window.location.origin : "")).replace(/\/$/, "");
145
+ const address = `${base}${hook.path}`;
146
+ const make = async () => {
147
+ setBusy(true);
148
+ setNote(null);
149
+ try {
150
+ const r = await onRotate?.();
151
+ if (r && r.ok === false) setNote(r.error || "That did not work.");
152
+ else if (r?.hook?.secret) setShown(r.hook.secret);
153
+ setAsking(false);
154
+ } catch (e) {
155
+ setNote(e?.message || "That did not work.");
156
+ } finally {
157
+ setBusy(false);
158
+ }
159
+ };
160
+ return (
161
+ <>
162
+ <Field id={`${uid}-addr`} label="Its web address" hint="Post to it with JSON. What it receives is on the run as trigger.payload.body.">
163
+ <Input id={`${uid}-addr`} readOnly className="font-mono text-[12.5px]" value={address} onFocus={(e) => e.target.select()} />
164
+ </Field>
165
+ {shown ? (
166
+ <Field id={`${uid}-secret`} label="Its secret" hint="Shown once: copy it now. Sign the body with it (x-makersclaw-signature), or add ?token=… to the address when a sender cannot sign.">
167
+ <Input id={`${uid}-secret`} readOnly className="font-mono text-[12.5px]" value={shown} onFocus={(e) => e.target.select()} />
168
+ </Field>
169
+ ) : (
170
+ <p className="m-0 text-xs text-muted-foreground">
171
+ {hook.has_secret ? "It has a secret, and only the sender who holds it can start a run." : "It has no secret yet, so nothing can start it."}
172
+ {hook.last_received_at ? " Last called " + new Date(hook.last_received_at).toLocaleString() + "." : ""}
173
+ </p>
174
+ )}
175
+ {!readOnly ? (
176
+ asking ? (
177
+ <div className="grid gap-2 rounded-md border border-border p-2.5">
178
+ <p className="m-0 text-xs">The old secret stops working at once. Anything that still uses it will be refused.</p>
179
+ <div className="flex gap-2">
180
+ <Button size="sm" variant="danger" onClick={make} disabled={busy}>
181
+ Make a new secret
182
+ </Button>
183
+ <Button size="sm" variant="secondary" onClick={() => setAsking(false)} disabled={busy}>
184
+ Keep the old one
185
+ </Button>
186
+ </div>
187
+ </div>
188
+ ) : (
189
+ <Button size="sm" variant="secondary" className="justify-self-start" icon="key" onClick={() => (hook.has_secret ? setAsking(true) : make())} disabled={busy}>
190
+ {hook.has_secret ? "Make a new secret" : "Make a secret"}
191
+ </Button>
192
+ )
193
+ ) : null}
194
+ {note ? (
195
+ <p role="alert" className="m-0 text-xs text-destructive">
196
+ {note}
197
+ </p>
198
+ ) : null}
199
+ </>
200
+ );
201
+ }
202
+
203
+ /**
204
+ * trigger the definition's trigger (see the list at the top)
205
+ * onChange(trigger)
206
+ * readOnly shown, not editable
207
+ * onClose draws the close button
208
+ * catalog what the platform offers (the list door's `triggers`):
209
+ * { choices: [{ type, label, hint, available, why? }],
210
+ * apps: [{ name, actions: [{ name, description }], kinds, topics }],
211
+ * automations: [{ key, name }] }. Without it: by hand and a
212
+ * schedule, and `later` listed as "soon".
213
+ * ownedByApp the automation belongs to an app: its actions, kinds and
214
+ * topics are that app's (the first of catalog.apps)
215
+ * selfKey this automation's key: it cannot follow itself
216
+ * hook a webhook trigger's address once the automation is saved:
217
+ * { path, has_secret, rotated_at, last_received_at }
218
+ * onRotateHook async () => { ok, hook: { secret } } | { ok: false, error }
219
+ * origin where the address lives (default: this page's origin)
220
+ * later the not-yet ways to start without a catalog, [{ id, label, hint }]
221
+ */
222
+ export function TriggerPicker({ trigger, onChange, readOnly = false, onClose, catalog = null, ownedByApp = false, selfKey = null, hook = null, onRotateHook, origin, later }) {
223
+ const uid = useId();
224
+ const current = trigger ?? { type: "manual" };
225
+ const type = current.type;
226
+ const choices = catalog?.choices?.length ? catalog.choices : FALLBACK_CHOICES;
227
+ const apps = catalog?.apps ?? [];
228
+ const others = (catalog?.automations ?? []).filter((a) => a.key !== selfKey);
229
+ const scope = ownedByApp ? apps[0] : apps.find((a) => a.name === current.app);
230
+ const scoped = scope ? { ...scope, own: ownedByApp } : null;
231
+ const soon = catalog ? choices.filter((c) => !c.available) : (later ?? LATER).map((l) => ({ type: l.id, label: l.label, hint: l.hint, available: false }));
232
+ const switchTo = (next) => onChange(startOf(next, { app: ownedByApp ? scoped : apps.length === 1 ? { ...apps[0], own: false } : null, other: others }));
233
+ const setApp = (name) => {
234
+ const { app: _drop, ...rest } = current;
235
+ onChange(name ? { ...rest, app: name } : rest);
236
+ };
237
+
238
+ return (
239
+ <SidePanel glyph={<Glyph name={triggerGlyph(type)} size={20} />} title="What starts it" subtitle={triggerWords(current)} onClose={onClose} label="What starts it">
240
+ <Field id={`${uid}-type`} label="It starts">
241
+ <Select id={`${uid}-type`} value={type} disabled={readOnly} options={optionsOf(choices, type)} onChange={(e) => switchTo(e.target.value)} />
242
+ </Field>
243
+ <p className="m-0 -mt-2 text-xs text-muted-foreground">{choices.find((c) => c.type === type)?.hint ?? ""}</p>
244
+
245
+ {type === "manual" ? <p className="m-0 text-xs text-muted-foreground">Nothing starts it on its own. Press Run when you want it to go, or let the agent run it.</p> : null}
246
+
247
+ {type === "schedule" ? <Schedule uid={uid} trigger={current} readOnly={readOnly} onChange={onChange} /> : null}
248
+
249
+ {type === "event" ? (
250
+ <>
251
+ <AppField uid={uid} trigger={current} apps={apps} ownedByApp={ownedByApp} readOnly={readOnly} onApp={setApp} required={false} />
252
+ <Field id={`${uid}-topic`} label="Event" hint="The name an app sends, like rows.imported. Keyed events (with a key) run once per item.">
253
+ <Input id={`${uid}-topic`} className="font-mono text-[13px]" list={`${uid}-topics`} value={current.topic ?? ""} disabled={readOnly} placeholder="rows.imported" onChange={(e) => onChange({ ...current, topic: e.target.value.trim().toLowerCase() })} />
254
+ <datalist id={`${uid}-topics`}>{(scoped?.topics ?? apps.flatMap((a) => a.topics ?? [])).map((t) => <option key={t} value={t} />)}</datalist>
255
+ </Field>
256
+ </>
257
+ ) : null}
258
+
259
+ {type === "action" ? (
260
+ <>
261
+ <AppField uid={uid} trigger={current} apps={apps} ownedByApp={ownedByApp} readOnly={readOnly} onApp={(n) => onChange({ type: "action", action: "", ...(n ? { app: n } : {}) })} required />
262
+ <Field id={`${uid}-action`} label="Action" hint="Runs when a person or the app's agent has done it. An action another automation ran does not start this one.">
263
+ {scoped?.actions?.length ? (
264
+ <Select
265
+ id={`${uid}-action`}
266
+ value={current.action ?? ""}
267
+ disabled={readOnly}
268
+ options={[{ value: "", label: "Pick an action" }, ...scoped.actions.map((a) => ({ value: a.name, label: a.name.replace(/_/g, " ") }))]}
269
+ onChange={(e) => onChange({ ...current, action: e.target.value })}
270
+ />
271
+ ) : (
272
+ <Input id={`${uid}-action`} className="font-mono text-[13px]" value={current.action ?? ""} disabled={readOnly} placeholder="add_people" onChange={(e) => onChange({ ...current, action: e.target.value.trim() })} />
273
+ )}
274
+ </Field>
275
+ </>
276
+ ) : null}
277
+
278
+ {type === "record" ? (
279
+ <>
280
+ <AppField uid={uid} trigger={current} apps={apps} ownedByApp={ownedByApp} readOnly={readOnly} onApp={(n) => onChange({ type: "record", ...(n ? { app: n } : {}) })} required />
281
+ <fieldset className="m-0 grid min-w-0 gap-1 border-0 p-0">
282
+ <legend className="mb-1 p-0 text-sm font-medium">Which records</legend>
283
+ {(scoped?.kinds ?? []).map((k) => {
284
+ const picked = current.kinds ?? [];
285
+ return (
286
+ <Checkbox
287
+ key={k}
288
+ id={`${uid}-k-${k}`}
289
+ label={k.replace(/_/g, " ")}
290
+ checked={picked.includes(k)}
291
+ disabled={readOnly}
292
+ onChange={(e) => {
293
+ const next = e.target.checked ? [...picked, k] : picked.filter((x) => x !== k);
294
+ const { kinds: _drop, ...rest } = current;
295
+ onChange(next.length ? { ...rest, kinds: next } : rest);
296
+ }}
297
+ />
298
+ );
299
+ })}
300
+ <p className="m-0 text-xs text-muted-foreground">{(current.kinds ?? []).length ? "Only these." : "None picked: every kind of record the owner can read."}</p>
301
+ </fieldset>
302
+ <fieldset className="m-0 grid min-w-0 gap-1 border-0 p-0">
303
+ <legend className="mb-1 p-0 text-sm font-medium">When it is</legend>
304
+ {[
305
+ ["create", "Added"],
306
+ ["update", "Changed"],
307
+ ].map(([op, label]) => {
308
+ const ops = current.ops ?? ["create", "update"];
309
+ return (
310
+ <Checkbox
311
+ key={op}
312
+ id={`${uid}-op-${op}`}
313
+ label={label}
314
+ checked={ops.includes(op)}
315
+ disabled={readOnly || (ops.length === 1 && ops[0] === op)}
316
+ onChange={(e) => {
317
+ const next = e.target.checked ? [...ops, op] : ops.filter((x) => x !== op);
318
+ const { ops: _drop, ...rest } = current;
319
+ onChange(next.length === 2 ? rest : { ...rest, ops: next });
320
+ }}
321
+ />
322
+ );
323
+ })}
324
+ </fieldset>
325
+ <p className="m-0 text-xs text-muted-foreground">A person, a screen or the app's agent made the change; the app's own jobs do not start it. One run for each record, at most once a minute.</p>
326
+ </>
327
+ ) : null}
328
+
329
+ {type === "webhook" ? <Webhook uid={uid} hook={hook} onRotate={onRotateHook} readOnly={readOnly} origin={origin} /> : null}
330
+
331
+ {type === "automation" ? (
332
+ <>
333
+ <Field id={`${uid}-key`} label="Another automation" hint="It runs after that one has finished, with how it went.">
334
+ <Select
335
+ id={`${uid}-key`}
336
+ value={current.key ?? ""}
337
+ disabled={readOnly}
338
+ options={[{ value: "", label: others.length ? "Pick one" : "No other automation yet" }, ...others.map((a) => ({ value: a.key, label: a.name }))]}
339
+ onChange={(e) => onChange({ ...current, key: e.target.value })}
340
+ />
341
+ </Field>
342
+ <Field id={`${uid}-when`} label="When it">
343
+ <Select
344
+ id={`${uid}-when`}
345
+ value={current.when ?? "done"}
346
+ disabled={readOnly}
347
+ options={[
348
+ { value: "done", label: "finishes well" },
349
+ { value: "failed", label: "fails" },
350
+ { value: "any", label: "ends either way" },
351
+ ]}
352
+ onChange={(e) => onChange({ ...current, when: e.target.value })}
353
+ />
354
+ </Field>
355
+ <p className="m-0 text-xs text-muted-foreground">Two automations cannot start each other: the platform refuses a loop when you save.</p>
356
+ </>
357
+ ) : null}
358
+
359
+ {soon.length ? (
360
+ <ul className={cx("m-0 grid list-none gap-1.5 border-t border-border p-0 pt-3")} aria-label="Coming later">
361
+ {soon.map((l) => (
362
+ <li key={l.type} className="flex items-start justify-between gap-2 text-sm text-muted-foreground">
363
+ <span className="grid gap-0.5">
364
+ <span>{l.label}</span>
365
+ {l.why || l.hint ? <span className="text-xs">{l.why || l.hint}</span> : null}
366
+ </span>
367
+ <span className="shrink-0 rounded-full border border-border px-1.5 text-2xs">soon</span>
368
+ </li>
369
+ ))}
370
+ </ul>
371
+ ) : null}
372
+ </SidePanel>
373
+ );
374
+ }
@@ -93,8 +93,11 @@ for agents.
93
93
  receives the canvas handle: `exportImage()`, `getScene()`,
94
94
  `insertElements()`… (sketch-canvas README, "The handle").
95
95
  - `className` — layout: width, margin, height. The default height is
96
- `h-[40rem]`; a height class of yours (`h-dvh` for a full page, `h-full`,
97
- `flex-1`) replaces it. Never colour.
96
+ `h-[40rem]`; a height class of yours (`h-full`, `min-h-0 flex-1`)
97
+ replaces it. A board that is the whole surface sits in an `AppLayout
98
+ contentMode="fill"` from the kit with `min-h-0 flex-1` (the Example):
99
+ never `h-dvh` or a `vh` height, which `npm run check` refuses. Never
100
+ colour.
98
101
 
99
102
  ### Templates
100
103
 
@@ -118,6 +121,7 @@ A board page that saves itself:
118
121
  import { useSearchParams } from "next/navigation";
119
122
  import { useRow, whenLanded } from "../lib/data";
120
123
  import { updateRow } from "../lib/actions";
124
+ import { AppLayout } from "../components/ui";
121
125
  import { Whiteboard } from "../components/blocks/whiteboard";
122
126
  import { sketchToText } from "../components/blocks/sketch-canvas";
123
127
 
@@ -126,18 +130,20 @@ export default function BoardPage() {
126
130
  const { row: board, loading } = useRow({ source: "boards", id });
127
131
  if (loading || !board) return null;
128
132
  return (
129
- <Whiteboard
130
- key={board.id}
131
- title={board.title}
132
- onRename={async (next) => {
133
- const res = await updateRow({ source: "boards", id: board.id, patch: { title: next } });
134
- if (res.ok) await whenLanded(); // the board is read again: the title is the new one
135
- return res;
136
- }}
137
- defaultValue={board.sketch} // jsonb, may be null; read once per board
138
- onSave={(sketch) => updateRow({ source: "boards", id: board.id, patch: { sketch, sketch_text: sketchToText(sketch) } })}
139
- className="h-dvh rounded-none border-0"
140
- />
133
+ <AppLayout contentMode="fill">
134
+ <Whiteboard
135
+ key={board.id}
136
+ title={board.title}
137
+ onRename={async (next) => {
138
+ const res = await updateRow({ source: "boards", id: board.id, patch: { title: next } });
139
+ if (res.ok) await whenLanded(); // the board is read again: the title is the new one
140
+ return res;
141
+ }}
142
+ defaultValue={board.sketch} // jsonb, may be null; read once per board
143
+ onSave={(sketch) => updateRow({ source: "boards", id: board.id, patch: { sketch, sketch_text: sketchToText(sketch) } })}
144
+ className="min-h-0 flex-1 rounded-none border-0"
145
+ />
146
+ </AppLayout>
141
147
  );
142
148
  }
143
149
  ```
@@ -0,0 +1,123 @@
1
+ # WorkflowView
2
+
3
+ > **Superseded** (0.8.1, the automations engine, D26). One job drawn top to bottom, from `useJobs`, `useRuns` and `useRun`. For an app whose jobs run on the automations engine, use `automation-editor` (a node canvas a member can edit, test and switch on) and `run-view` (one run on the same canvas, the path taken lit). Keep using this block for an app that has not moved: it works as it did.
4
+
5
+
6
+ One job of the app's agent, drawn as a graph on a dotted ground. Part of
7
+ the agent kit (0.8.1): the app shows its agent's work itself; the
8
+ window's Runs tab stays as the full history.
9
+
10
+ - **The graph**: the Trigger ("Every weekday at 07:00", "When a deal is
11
+ created", "Run by Owen") → each step of the chosen run, with how it
12
+ went as a mark and a word → the result (what it wrote, what needs
13
+ you).
14
+ - **Over it**: the run picker ("Run #7 · Tue 29 Sep, 07:02") and Re-run.
15
+ - **In its head**: the Live switch and "Trigger manually · about 700 cr".
16
+ - **Beside it**: the run history and the overview (the `run-history`
17
+ block's RunHistory and RunOverview).
18
+ - **Before any run**: the job's declared steps (`plan`) drawn in pencil,
19
+ dashed, with an honest line ("No runs yet. The first runs Mon 12 Oct,
20
+ 07:00, once a mailbox is connected."). A job not set up still has
21
+ something to look at.
22
+
23
+ ```jsx
24
+ import { WorkflowView } from "../components/blocks/workflow-view"; // a Makersclaw app
25
+ import { WorkflowView } from "@/components/makersclaw/blocks/workflow-view"; // a shadcn project
26
+ ```
27
+
28
+ A client component. `makersclaw add workflow-view` lays `run-history`
29
+ with it. Its own width decides its layout: under about 768 px the
30
+ history and the overview stack under the graph. The graph always runs
31
+ top to bottom, every step a full-width node with its whole title (a
32
+ left-to-right strip scrolled sideways and cut titles at a desk window's
33
+ width, 2026-10-11). It never scrolls sideways. It formats nothing.
34
+
35
+ ## Props
36
+
37
+ - `title` — the job's name.
38
+ - `trigger` — `{ label, detail }`: what starts it, in words.
39
+ - `steps` — the chosen run's steps, `[{ label, status, detail? }]`.
40
+ `status` is `done` · `failed` · `running` · `needs_you` · `stopped` ·
41
+ `skipped` · `waiting` (not reached yet). useRun's `steps` pass as
42
+ they are.
43
+ - `result` — `{ label, detail, status }`: what the run wrote, or what
44
+ waits on the member.
45
+ - `runs` — RunHistory's rows (`{ id, status, title, line, when, cost }`),
46
+ newest first. `selected`, `onSelect(run)` — the run drawn; the picker
47
+ and the history both choose it.
48
+ - `overview` — RunOverview's props (`{ completed, failed, running, avg,
49
+ credits }`), or null.
50
+ - `live` — `{ on, onToggle(next), busy }`: the app's Live switch. Null:
51
+ no switch.
52
+ - `run` — `{ label, price, onRun, loading, disabled, why }`: "Trigger
53
+ manually" with its price on the button. Null: no button.
54
+ - `rerun` — `{ onRun, loading, label? }`: Re-run beside the picker.
55
+ - `plan` — the job's declared steps (useJobs' `job.plan`), drawn in
56
+ pencil before any run.
57
+ - `empty` — the honest line before any run: when it will first run, and
58
+ what it waits on.
59
+ - `className` — layout around it. Never colour.
60
+
61
+ ## Hooks (lib/hooks.js)
62
+
63
+ - `useJobs()` — the job (`words`, `plan`, `enabled`), the app's `live`,
64
+ `may`, `runNow(id)`, `pause()`, `resume()`.
65
+ - `useRuns({ job })` — the runs and the overview.
66
+ - `useRun(id)` — the chosen run's `steps`, `text` and `needs`.
67
+
68
+ ## Who may do what
69
+
70
+ - Any member reads the graph, the runs and the overview (a teammate's
71
+ ask is never among the runs: the door leaves it out).
72
+ - **Trigger manually**, **Re-run** and **Live**: the app's owner, a
73
+ workspace owner or an admin — `may.run` and `may.pause`. Pass `run`,
74
+ `rerun` and `live` only when they are true. The door refuses the
75
+ others anyway; a hidden button is never the guard.
76
+
77
+ ## Never
78
+
79
+ - Never a press that spends without its price on it.
80
+ - Never an Approve: a step that needs the member says "Needs you" and
81
+ the screen opens the desk (`openRequest`).
82
+ - Never a status by colour alone: each comes with its mark and its
83
+ word.
84
+ - Never a steps list made up when the run has none: pass the `plan`, or
85
+ nothing, and the empty line.
86
+
87
+ ## Example
88
+
89
+ ```jsx
90
+ "use client";
91
+ import { useState } from "react";
92
+ import { useJobs, useRun, useRuns } from "../lib/hooks";
93
+ import { WorkflowView } from "../components/blocks/workflow-view";
94
+
95
+ const at = (iso) => new Date(iso).toLocaleString("en-GB", { weekday: "short", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
96
+
97
+ export default function MorningReadFlow({ jobId }) {
98
+ const { jobs, app, may, busy, appBusy, runNow, pause, resume } = useJobs();
99
+ const job = jobs.find((j) => j.id === jobId);
100
+ const { runs, overview } = useRuns({ job: jobId });
101
+ const [picked, setPicked] = useState(null);
102
+ const selected = picked ?? runs[0]?.id ?? null;
103
+ const { run, steps } = useRun(selected);
104
+ if (!job) return null;
105
+ return (
106
+ <WorkflowView
107
+ title={job.name}
108
+ trigger={{ label: job.words ?? "On its schedule", detail: job.does }}
109
+ steps={steps}
110
+ result={run ? { label: run.state === "needs_you" ? "Waiting for your yes on the desk" : run.report ?? "Done", status: run.state } : null}
111
+ runs={runs.map((r) => ({ id: r.id, status: r.state, title: `Run #${r.number}`, when: at(r.started_at) }))}
112
+ selected={selected}
113
+ onSelect={(r) => setPicked(r.id)}
114
+ overview={overview && { completed: overview.completed, failed: overview.failed, running: overview.running, avg: overview.avg_ms == null ? null : `${Math.round(overview.avg_ms / 1000)} s` }}
115
+ live={may.pause ? { on: Boolean(app?.live), busy: Boolean(appBusy), onToggle: (on) => (on ? resume() : pause()) } : null}
116
+ run={may.run ? { label: "Trigger manually", price: "about 700 cr", onRun: () => runNow(job.id), loading: busy[job.id] === "run" } : null}
117
+ rerun={may.run ? { onRun: () => runNow(job.id), loading: busy[job.id] === "run" } : null}
118
+ plan={job.plan}
119
+ empty={job.next_run_at ? `No runs yet. The first runs ${at(job.next_run_at)}.` : "No runs yet. It starts once it is switched on."}
120
+ />
121
+ );
122
+ }
123
+ ```
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "workflow-view",
3
+ "title": "WorkflowView",
4
+ "description": "One job of the app's agent drawn as a graph on a dotted ground: the Trigger (\"Every weekday at 07:00\", \"When a deal is created\") → each step of the chosen run with how it went, as a mark and a word → the result. Over it a run picker with Re-run; in its head the Live switch and \"Trigger manually\" with its price; beside it the run history and the overview (run-history). Before any run it draws the job's declared steps in pencil, with an honest empty line. Fed by useJobs, useRuns and useRun (lib/hooks.js). Under about 768 px of its own width the history stacks under the graph and the graph runs top to bottom.",
5
+ "useWhen": "Superseded by automation-editor and run-view for an app whose jobs run on the automations engine; still the block for an app that has not moved (its jobs are the agent's wakes). A job's own page: the founder opens an automation to see what it does, how its last runs went and to run it now — a morning read, an inbox sweep, a nightly enrichment, an event-triggered workflow. For the job as a card beside the day's work use schedule-card; for a plain list of runs use run-history.",
6
+ "tags": ["workflow", "automation", "graph", "pipeline", "steps", "trigger", "runs", "run history", "re-run", "live", "schedule", "agent", "nodes", "kit"],
7
+ "exports": ["WorkflowView"],
8
+ "files": ["index.js", "workflow-view.jsx"],
9
+ "requires": ["run-history"]
10
+ }
@@ -0,0 +1,90 @@
1
+ "use client";
2
+
3
+ // WorkflowView with a pretend job — the gallery's and the smoke test's
4
+ // surface. Not installed into apps. A job with runs (one going, one
5
+ // failed): pick a run, Re-run, Trigger manually, switch Live. Then the
6
+ // same job before any run, its plan in pencil. A width picker shows the
7
+ // layout at 1280, 800, 368 and 320 px of the block's own width.
8
+ import { useState } from "react";
9
+ import { Button, ButtonGroup } from "../components/ui";
10
+ import { WorkflowView } from "../components/blocks/workflow-view";
11
+
12
+ const STEPS = {
13
+ r14: [
14
+ { label: "Read mail", status: "running", detail: "12 of 40 emails since yesterday" },
15
+ { label: "Find people", status: "waiting" },
16
+ { label: "Draft follow-ups", status: "waiting" },
17
+ ],
18
+ r13: [
19
+ { label: "Read mail", status: "done", detail: "38 emails, 3 meetings" },
20
+ { label: "Find people", status: "done", detail: "4 new, 3 details" },
21
+ { label: "Draft follow-ups", status: "failed", detail: "The model timed out after 60 s; nothing was sent" },
22
+ ],
23
+ r12: [
24
+ { label: "Read mail", status: "done", detail: "22 emails" },
25
+ { label: "Find people", status: "done", detail: "1 new" },
26
+ { label: "Draft follow-ups", status: "needs_you", detail: "3 drafts wait for your yes" },
27
+ ],
28
+ };
29
+ const RESULTS = {
30
+ r14: { label: "Writing as it reads", detail: "People and deals appear on Today as they are found", status: "running" },
31
+ r13: { label: "Wrote 4 people, 1 deal move", detail: "Follow-ups not drafted", status: "failed" },
32
+ r12: { label: "Waiting for your yes on the desk", detail: "3 follow-ups to send", status: "needs_you" },
33
+ };
34
+ const RUNS = [
35
+ { id: "r14", status: "running", title: "Run #14 · Wed 30 Sep, 07:00", when: "now" },
36
+ { id: "r13", status: "failed", title: "Run #13 · Tue 29 Sep, 07:02", line: "Drafting failed: the model timed out", when: "yesterday", cost: "640 cr" },
37
+ { id: "r12", status: "needs_you", title: "Run #12 · Mon 28 Sep, 16:10", line: "Run now, by Owen", when: "2 days ago", cost: "420 cr" },
38
+ ];
39
+ const PLAN = ["Read mail since the last read", "Find people and details", "Draft follow-ups owed"];
40
+ const WIDTHS = [1280, 800, 368, 320];
41
+
42
+ export default function WorkflowViewDemo() {
43
+ const [width, setWidth] = useState(800);
44
+ const [selected, setSelected] = useState("r13");
45
+ const [live, setLive] = useState(true);
46
+ const [busy, setBusy] = useState(null);
47
+ const press = (what, then) => {
48
+ setBusy(what);
49
+ setTimeout(() => {
50
+ then?.();
51
+ setBusy(null);
52
+ }, 800);
53
+ };
54
+ return (
55
+ <div className="grid gap-6 p-4">
56
+ <ButtonGroup aria-label="The block's width">
57
+ {WIDTHS.map((w) => (
58
+ <Button key={w} size="sm" variant={w === width ? "primary" : "secondary"} onClick={() => setWidth(w)}>
59
+ {w} px
60
+ </Button>
61
+ ))}
62
+ </ButtonGroup>
63
+ <div className="w-full" style={{ maxWidth: width }}>
64
+ <WorkflowView
65
+ title="Morning read"
66
+ trigger={{ label: "Every weekday at 07:00", detail: "Starts on its own; Owen can run it now" }}
67
+ steps={STEPS[selected]}
68
+ result={RESULTS[selected]}
69
+ runs={RUNS}
70
+ selected={selected}
71
+ onSelect={(r) => setSelected(r.id)}
72
+ overview={{ completed: 149, failed: 2, running: 1, avg: "1 min 52 s", credits: { used: 4180, of: 10000, words: "4,180 of 10,000 this week" } }}
73
+ live={{ on: live, busy: busy === "live", onToggle: (on) => press("live", () => setLive(on)) }}
74
+ run={{ label: "Trigger manually", price: "about 700 cr", onRun: () => press("run"), loading: busy === "run" }}
75
+ rerun={{ onRun: () => press("rerun"), loading: busy === "rerun" }}
76
+ />
77
+ </div>
78
+ <div className="w-full" style={{ maxWidth: width }}>
79
+ <WorkflowView
80
+ title="Friday review"
81
+ trigger={{ label: "Fridays at 16:00" }}
82
+ plan={PLAN}
83
+ empty="No runs yet. The first runs Fri 9 Oct, 16:00, once a mailbox is connected."
84
+ live={{ on: false, onToggle: () => {} }}
85
+ run={{ label: "Trigger manually", price: "about 900 cr", disabled: true, why: "Connect a mailbox first" }}
86
+ />
87
+ </div>
88
+ </div>
89
+ );
90
+ }
@@ -0,0 +1,3 @@
1
+ // The WorkflowView block — `makersclaw add workflow-view`. Fixed: compose
2
+ // it through its props (README.md beside this file).
3
+ export { WorkflowView } from "./workflow-view";