makersclaw 0.8.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 (401) hide show
  1. package/README.md +9 -3
  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 +3 -3
  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 +2 -2
  26. package/r/chat-pane.json +84 -0
  27. package/r/chat.json +2 -2
  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 +13 -7
  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 +2 -2
  46. package/r/flow-editor.json +79 -0
  47. package/r/footer.json +2 -2
  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 +3 -3
  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 +3 -3
  60. package/r/pace-bar.json +69 -0
  61. package/r/page-builder.json +2 -2
  62. package/r/payment-methods.json +2 -2
  63. package/r/pdf-document.json +2 -2
  64. package/r/pdf-viewer.json +2 -2
  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 +4086 -1512
  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 +2 -2
  82. package/r/signature-pad.json +2 -2
  83. package/r/sketch-canvas.json +2 -2
  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 +3 -3
  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/approval/README.md +145 -0
  159. package/registry/blocks/approval/approval.jsx +163 -0
  160. package/registry/blocks/approval/block.json +31 -0
  161. package/registry/blocks/approval/demo.jsx +121 -0
  162. package/registry/blocks/approval/index.js +3 -0
  163. package/registry/blocks/ask-bar/README.md +105 -0
  164. package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
  165. package/registry/blocks/ask-bar/block.json +26 -0
  166. package/registry/blocks/ask-bar/demo.jsx +78 -0
  167. package/registry/blocks/ask-bar/index.js +3 -0
  168. package/registry/blocks/automation-editor/README.md +291 -0
  169. package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
  170. package/registry/blocks/automation-editor/block.json +39 -0
  171. package/registry/blocks/automation-editor/demo.jsx +284 -0
  172. package/registry/blocks/automation-editor/index.js +4 -0
  173. package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
  174. package/registry/blocks/automation-list/README.md +129 -0
  175. package/registry/blocks/automation-list/automation-list.jsx +476 -0
  176. package/registry/blocks/automation-list/block.json +35 -0
  177. package/registry/blocks/automation-list/demo.jsx +67 -0
  178. package/registry/blocks/automation-list/index.js +3 -0
  179. package/registry/blocks/automation-model/README.md +109 -0
  180. package/registry/blocks/automation-model/block.json +135 -0
  181. package/registry/blocks/automation-model/catalog.js +256 -0
  182. package/registry/blocks/automation-model/check.js +161 -0
  183. package/registry/blocks/automation-model/demo.jsx +42 -0
  184. package/registry/blocks/automation-model/edit.js +262 -0
  185. package/registry/blocks/automation-model/fixes.js +287 -0
  186. package/registry/blocks/automation-model/glyph.jsx +13 -0
  187. package/registry/blocks/automation-model/graph.js +410 -0
  188. package/registry/blocks/automation-model/index.js +33 -0
  189. package/registry/blocks/automation-model/overlay.js +175 -0
  190. package/registry/blocks/automation-model/parts.jsx +94 -0
  191. package/registry/blocks/automation-model/schedule.js +53 -0
  192. package/registry/blocks/automation-model/templates.js +128 -0
  193. package/registry/blocks/automation-model/values.js +29 -0
  194. package/registry/blocks/automation-model/words.js +439 -0
  195. package/registry/blocks/automations-screen/README.md +207 -0
  196. package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
  197. package/registry/blocks/automations-screen/block.json +47 -0
  198. package/registry/blocks/automations-screen/demo.jsx +364 -0
  199. package/registry/blocks/automations-screen/index.js +4 -0
  200. package/registry/blocks/automations-screen/screen-model.js +129 -0
  201. package/registry/blocks/chat-pane/README.md +143 -0
  202. package/registry/blocks/chat-pane/block.json +48 -0
  203. package/registry/blocks/chat-pane/chat-attach.js +166 -0
  204. package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
  205. package/registry/blocks/chat-pane/chat-context.js +17 -0
  206. package/registry/blocks/chat-pane/chat-model.js +43 -0
  207. package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
  208. package/registry/blocks/chat-pane/chats-list.jsx +52 -0
  209. package/registry/blocks/chat-pane/demo.jsx +103 -0
  210. package/registry/blocks/chat-pane/index.js +9 -0
  211. package/registry/blocks/connect-card/README.md +99 -0
  212. package/registry/blocks/connect-card/block.json +10 -0
  213. package/registry/blocks/connect-card/connect-card.jsx +103 -0
  214. package/registry/blocks/connect-card/demo.jsx +49 -0
  215. package/registry/blocks/connect-card/index.js +3 -0
  216. package/registry/blocks/cost/README.md +115 -0
  217. package/registry/blocks/cost/block.json +10 -0
  218. package/registry/blocks/cost/cost.jsx +176 -0
  219. package/registry/blocks/cost/demo.jsx +66 -0
  220. package/registry/blocks/cost/index.js +3 -0
  221. package/registry/blocks/data-picker/README.md +81 -0
  222. package/registry/blocks/data-picker/block.json +38 -0
  223. package/registry/blocks/data-picker/data-picker.jsx +210 -0
  224. package/registry/blocks/data-picker/demo.jsx +34 -0
  225. package/registry/blocks/data-picker/fields.js +89 -0
  226. package/registry/blocks/data-picker/index.js +4 -0
  227. package/registry/blocks/data-table/demo.jsx +1 -1
  228. package/registry/blocks/first-run/README.md +118 -0
  229. package/registry/blocks/first-run/block.json +11 -0
  230. package/registry/blocks/first-run/demo.jsx +88 -0
  231. package/registry/blocks/first-run/first-run-model.js +51 -0
  232. package/registry/blocks/first-run/first-run.jsx +156 -0
  233. package/registry/blocks/first-run/index.js +5 -0
  234. package/registry/blocks/first-run/probe-rules.js +26 -0
  235. package/registry/blocks/fix-note/README.md +79 -0
  236. package/registry/blocks/fix-note/block.json +35 -0
  237. package/registry/blocks/fix-note/demo.jsx +30 -0
  238. package/registry/blocks/fix-note/fix-note.jsx +235 -0
  239. package/registry/blocks/fix-note/index.js +3 -0
  240. package/registry/blocks/flow-editor/README.md +108 -0
  241. package/registry/blocks/flow-editor/block.json +44 -0
  242. package/registry/blocks/flow-editor/demo.jsx +115 -0
  243. package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
  244. package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
  245. package/registry/blocks/flow-editor/index.js +6 -0
  246. package/registry/blocks/flow-editor/minimap.jsx +78 -0
  247. package/registry/blocks/flow-editor/outline.jsx +134 -0
  248. package/registry/blocks/library-shelf/README.md +117 -0
  249. package/registry/blocks/library-shelf/block.json +28 -0
  250. package/registry/blocks/library-shelf/demo.jsx +68 -0
  251. package/registry/blocks/library-shelf/index.js +3 -0
  252. package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
  253. package/registry/blocks/library-shelf/probe-rules.js +15 -0
  254. package/registry/blocks/margin-notes/README.md +222 -0
  255. package/registry/blocks/margin-notes/block.json +10 -0
  256. package/registry/blocks/margin-notes/demo.jsx +144 -0
  257. package/registry/blocks/margin-notes/index.js +20 -0
  258. package/registry/blocks/margin-notes/margin-model.js +224 -0
  259. package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
  260. package/registry/blocks/needs-you/README.md +177 -0
  261. package/registry/blocks/needs-you/block.json +34 -0
  262. package/registry/blocks/needs-you/demo.jsx +143 -0
  263. package/registry/blocks/needs-you/index.js +3 -0
  264. package/registry/blocks/needs-you/needs-you.jsx +441 -0
  265. package/registry/blocks/pace-bar/README.md +230 -0
  266. package/registry/blocks/pace-bar/block.json +10 -0
  267. package/registry/blocks/pace-bar/demo.jsx +255 -0
  268. package/registry/blocks/pace-bar/index.js +22 -0
  269. package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
  270. package/registry/blocks/pace-bar/pace-model.js +288 -0
  271. package/registry/blocks/record-grid/README.md +100 -0
  272. package/registry/blocks/record-grid/block.json +28 -0
  273. package/registry/blocks/record-grid/demo.jsx +43 -0
  274. package/registry/blocks/record-grid/index.js +3 -0
  275. package/registry/blocks/record-grid/record-grid.jsx +251 -0
  276. package/registry/blocks/run-history/README.md +138 -0
  277. package/registry/blocks/run-history/block.json +10 -0
  278. package/registry/blocks/run-history/demo.jsx +74 -0
  279. package/registry/blocks/run-history/index.js +3 -0
  280. package/registry/blocks/run-history/run-history.jsx +218 -0
  281. package/registry/blocks/run-view/README.md +174 -0
  282. package/registry/blocks/run-view/block.json +50 -0
  283. package/registry/blocks/run-view/demo.jsx +286 -0
  284. package/registry/blocks/run-view/index.js +5 -0
  285. package/registry/blocks/run-view/run-controls.jsx +266 -0
  286. package/registry/blocks/run-view/run-view.jsx +236 -0
  287. package/registry/blocks/run-view/runs-list.jsx +99 -0
  288. package/registry/blocks/schedule-card/README.md +121 -0
  289. package/registry/blocks/schedule-card/block.json +10 -0
  290. package/registry/blocks/schedule-card/demo.jsx +82 -0
  291. package/registry/blocks/schedule-card/index.js +3 -0
  292. package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
  293. package/registry/blocks/schedule-engine/README.md +137 -0
  294. package/registry/blocks/schedule-engine/block.json +10 -0
  295. package/registry/blocks/schedule-engine/demo.jsx +82 -0
  296. package/registry/blocks/schedule-engine/engine.js +769 -0
  297. package/registry/blocks/schedule-engine/index.js +9 -0
  298. package/registry/blocks/schedule-engine/ops.js +71 -0
  299. package/registry/blocks/schedule-engine/place.js +294 -0
  300. package/registry/blocks/schedule-engine/tree.js +79 -0
  301. package/registry/blocks/schedule-engine/waits.js +80 -0
  302. package/registry/blocks/schedule-gantt/README.md +159 -0
  303. package/registry/blocks/schedule-gantt/block.json +10 -0
  304. package/registry/blocks/schedule-gantt/demo.jsx +223 -0
  305. package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
  306. package/registry/blocks/schedule-gantt/geometry.js +176 -0
  307. package/registry/blocks/schedule-gantt/index.js +26 -0
  308. package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
  309. package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
  310. package/registry/blocks/schedule-gantt/track.jsx +190 -0
  311. package/registry/blocks/schedule-ruler/README.md +148 -0
  312. package/registry/blocks/schedule-ruler/block.json +10 -0
  313. package/registry/blocks/schedule-ruler/demo.jsx +181 -0
  314. package/registry/blocks/schedule-ruler/index.js +21 -0
  315. package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
  316. package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
  317. package/registry/blocks/source-receipt/README.md +97 -0
  318. package/registry/blocks/source-receipt/block.json +30 -0
  319. package/registry/blocks/source-receipt/demo.jsx +71 -0
  320. package/registry/blocks/source-receipt/index.js +3 -0
  321. package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
  322. package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
  323. package/registry/blocks/step-picker/README.md +78 -0
  324. package/registry/blocks/step-picker/block.json +31 -0
  325. package/registry/blocks/step-picker/demo.jsx +23 -0
  326. package/registry/blocks/step-picker/index.js +3 -0
  327. package/registry/blocks/step-picker/step-picker.jsx +144 -0
  328. package/registry/blocks/step-settings/README.md +100 -0
  329. package/registry/blocks/step-settings/block.json +44 -0
  330. package/registry/blocks/step-settings/demo.jsx +93 -0
  331. package/registry/blocks/step-settings/fields.jsx +58 -0
  332. package/registry/blocks/step-settings/flow-settings.jsx +115 -0
  333. package/registry/blocks/step-settings/index.js +5 -0
  334. package/registry/blocks/step-settings/step-settings.jsx +290 -0
  335. package/registry/blocks/suggestion/README.md +171 -0
  336. package/registry/blocks/suggestion/block.json +40 -0
  337. package/registry/blocks/suggestion/demo.jsx +91 -0
  338. package/registry/blocks/suggestion/index.js +3 -0
  339. package/registry/blocks/suggestion/suggestion.jsx +436 -0
  340. package/registry/blocks/sum-bar/README.md +122 -0
  341. package/registry/blocks/sum-bar/block.json +10 -0
  342. package/registry/blocks/sum-bar/demo.jsx +110 -0
  343. package/registry/blocks/sum-bar/index.js +5 -0
  344. package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
  345. package/registry/blocks/sum-bar/sum-model.js +126 -0
  346. package/registry/blocks/tier-map/README.md +217 -0
  347. package/registry/blocks/tier-map/block.json +10 -0
  348. package/registry/blocks/tier-map/demo.jsx +222 -0
  349. package/registry/blocks/tier-map/index.js +24 -0
  350. package/registry/blocks/tier-map/tier-map.jsx +574 -0
  351. package/registry/blocks/tier-map/tier-model.js +318 -0
  352. package/registry/blocks/time-grid/README.md +305 -0
  353. package/registry/blocks/time-grid/block.json +10 -0
  354. package/registry/blocks/time-grid/demo.jsx +279 -0
  355. package/registry/blocks/time-grid/grid-model.js +322 -0
  356. package/registry/blocks/time-grid/index.js +25 -0
  357. package/registry/blocks/time-grid/time-grid.jsx +1325 -0
  358. package/registry/blocks/time-strip/README.md +141 -0
  359. package/registry/blocks/time-strip/block.json +10 -0
  360. package/registry/blocks/time-strip/demo.jsx +129 -0
  361. package/registry/blocks/time-strip/index.js +19 -0
  362. package/registry/blocks/time-strip/strip-model.js +178 -0
  363. package/registry/blocks/time-strip/time-strip.jsx +260 -0
  364. package/registry/blocks/top-bar/README.md +149 -0
  365. package/registry/blocks/top-bar/block.json +35 -0
  366. package/registry/blocks/top-bar/demo.jsx +78 -0
  367. package/registry/blocks/top-bar/index.js +5 -0
  368. package/registry/blocks/top-bar/probe-rules.js +74 -0
  369. package/registry/blocks/top-bar/top-bar-model.js +152 -0
  370. package/registry/blocks/top-bar/top-bar.jsx +244 -0
  371. package/registry/blocks/trigger-picker/README.md +98 -0
  372. package/registry/blocks/trigger-picker/block.json +38 -0
  373. package/registry/blocks/trigger-picker/demo.jsx +59 -0
  374. package/registry/blocks/trigger-picker/index.js +3 -0
  375. package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
  376. package/registry/blocks/workflow-view/README.md +123 -0
  377. package/registry/blocks/workflow-view/block.json +10 -0
  378. package/registry/blocks/workflow-view/demo.jsx +90 -0
  379. package/registry/blocks/workflow-view/index.js +3 -0
  380. package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
  381. package/src/install.mjs +77 -16
  382. package/src/registry.mjs +3 -0
  383. package/templates/next/browser/lib/data.js +6 -1
  384. package/templates/next/files/README.md +627 -24
  385. package/templates/next/files/check/automation-format.ts +2103 -0
  386. package/templates/next/files/check/automation-package.ts +142 -0
  387. package/templates/next/files/check/run.mjs +968 -9
  388. package/templates/next/files/components/ui/field.jsx +17 -4
  389. package/templates/next/files/components/ui/icon.jsx +13 -0
  390. package/templates/next/files/components/ui/index.js +2 -1
  391. package/templates/next/files/components/ui/layout.jsx +77 -2
  392. package/templates/next/files/components/ui/notice.jsx +70 -0
  393. package/templates/next/files/components/ui/page.jsx +124 -0
  394. package/templates/next/files/components/ui/stat.jsx +22 -7
  395. package/templates/next/files/components/ui/toast.jsx +6 -3
  396. package/templates/next/files/lib/automations.js +660 -0
  397. package/templates/next/files/lib/claw.js +241 -5
  398. package/templates/next/files/lib/door.js +92 -0
  399. package/templates/next/files/lib/hooks.js +1627 -8
  400. package/templates/next/files/lib/platform.js +529 -21
  401. package/templates/next/template.json +13 -3
@@ -0,0 +1,476 @@
1
+ "use client";
2
+
3
+ // The list: every automation, each a WHOLE row you press to open. A row
4
+ // says what it does, when it runs, how its last run went, when the next is
5
+ // due (in the automation's own zone) and what the last one cost, and
6
+ // carries its on and off switch. The switch and the row keep their own
7
+ // press: the row is a stretched button under the switch.
8
+ //
9
+ // With none yet, the screen is the starting points: a few ready-made flows
10
+ // and a "New automation" button. With `onDescribe` it also opens with
11
+ // "Describe it": a sentence in a box, and the platform drafts the automation
12
+ // for the member to read, test and switch on. Props in, callbacks out; it
13
+ // formats nothing it was not given a clock for (`now`), and reads no door.
14
+
15
+ import { useMemo, useRef, useState } from "react";
16
+ import { Button, Confirm, Icon, Menu, Sheet, Switch, cx } from "../../ui";
17
+ import { Dot, Glyph, STARTING_POINTS, agoWords, clockWords, creditsWords, deleteWords, healthOf, originWords, startsFromPlatform, summaryOf, triggerWords } from "../automation-model";
18
+
19
+ const DESCRIBE_PRICE = "1 call · about 1 cr";
20
+ const DESCRIBE_CHIPS = ["Every Monday, mail me…", "When a deal is won, tell…", "When a message arrives, sort it…"];
21
+
22
+ /** Starting points as the card draws them: the app's own (`build`) as they are,
23
+ * the platform's raw ones (`definition`) turned into the same shape. */
24
+ function ready(starts) {
25
+ const out = [];
26
+ for (const s of starts ?? []) {
27
+ if (s && typeof s.build === "function") out.push(s);
28
+ else if (s && s.definition) out.push(...startsFromPlatform([s]));
29
+ }
30
+ return out;
31
+ }
32
+
33
+ /** "needs payments, a mailbox · a model writes three lines · about 6 cr" (or "free"). */
34
+ function startLine(s) {
35
+ const n = Number(s.price?.credits ?? 0);
36
+ const price = n > 0 ? `about ${creditsWords(n)}${s.price?.per === "each" ? " each" : ""}` : "free";
37
+ return [s.needs ? `needs ${s.needs}` : null, s.ai || null, price].filter(Boolean).join(" · ");
38
+ }
39
+
40
+ /** "Describe it": say what it should do in a sentence; the platform drafts it.
41
+ * On success the new automation opens; a question is listed under the box. */
42
+ function DescribeIt({ onDescribe, onOpen, price, chips, className }) {
43
+ const [text, setText] = useState("");
44
+ const [busy, setBusy] = useState(false);
45
+ const [said, setSaid] = useState(null);
46
+ const box = useRef(null);
47
+ const draft = async () => {
48
+ const ask = text.trim();
49
+ if (!ask || busy) return;
50
+ setBusy(true);
51
+ setSaid(null);
52
+ try {
53
+ const r = await onDescribe(ask);
54
+ if (r && r.ok) {
55
+ // An id opens the new automation; none means the sentence was handed on
56
+ // (to an agent beside the list, say): the box is empty for the next one.
57
+ if (r.id !== undefined && r.id !== null) onOpen?.(r.id);
58
+ else setText("");
59
+ } else if (r && Array.isArray(r.questions) && r.questions.length > 0) {
60
+ setSaid({ questions: r.questions });
61
+ } else {
62
+ setSaid({ error: (r && r.error) || "That did not work. Try saying it another way." });
63
+ }
64
+ } catch (e) {
65
+ setSaid({ error: e instanceof Error && e.message ? e.message : "That did not work. Try saying it another way." });
66
+ } finally {
67
+ setBusy(false);
68
+ }
69
+ };
70
+ return (
71
+ <section aria-label="Describe it" className={cx("grid gap-2 rounded-lg border border-border bg-card p-3 text-card-foreground", className)}>
72
+ <h3 className="m-0 flex items-center gap-1.5 text-sm font-semibold">
73
+ <Icon name="wand" size={15} className="text-primary" /> Describe it
74
+ </h3>
75
+ <p className="m-0 text-xs text-muted-foreground">Say what you want in a sentence. It draws the steps for you to read, test and switch on.</p>
76
+ <textarea
77
+ ref={box}
78
+ rows={2}
79
+ value={text}
80
+ disabled={busy}
81
+ aria-label="What should it do?"
82
+ placeholder="Every Monday morning, mail me the deals that have gone quiet"
83
+ onChange={(e) => setText(e.target.value)}
84
+ onKeyDown={(e) => {
85
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
86
+ e.preventDefault();
87
+ void draft();
88
+ }
89
+ }}
90
+ className="min-h-16 w-full resize-y rounded-md border border-input bg-background px-3 py-2 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60"
91
+ />
92
+ <div className="flex flex-wrap items-center gap-2">
93
+ <Button variant="primary" icon="wand" aria-busy={busy || undefined} disabled={busy || !text.trim()} onClick={() => void draft()}>
94
+ {busy ? "Drawing it…" : "Draft it"}
95
+ {!busy && price ? <span className="font-normal opacity-80">{price}</span> : null}
96
+ </Button>
97
+ {chips.map((c) => (
98
+ <button
99
+ key={c}
100
+ type="button"
101
+ disabled={busy}
102
+ onClick={() => {
103
+ setText(c);
104
+ box.current?.focus();
105
+ }}
106
+ className="inline-flex min-h-8 items-center rounded-full border border-border px-3 text-xs text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-60"
107
+ >
108
+ {c}
109
+ </button>
110
+ ))}
111
+ </div>
112
+ {said?.questions ? (
113
+ <div role="status" className="grid gap-1 text-[13px]">
114
+ <b className="font-semibold">Ask me about:</b>
115
+ <ul className="m-0 list-disc pl-5">
116
+ {said.questions.map((q) => (
117
+ <li key={q}>{q}</li>
118
+ ))}
119
+ </ul>
120
+ </div>
121
+ ) : null}
122
+ {said?.error ? (
123
+ <p role="alert" className="m-0 rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-[13px]">
124
+ {said.error}
125
+ </p>
126
+ ) : null}
127
+ </section>
128
+ );
129
+ }
130
+
131
+ function groupRows(rows, appName) {
132
+ const team = rows.filter((r) => r.owner_kind === "workspace");
133
+ const byApp = new Map();
134
+ for (const r of rows) if (r.owner_kind === "app" && r.app_id) byApp.set(r.app_id, [...(byApp.get(r.app_id) ?? []), r]);
135
+ const groups = [];
136
+ if (team.length) groups.push({ key: "team", title: "Team", rows: team });
137
+ [...byApp.entries()]
138
+ .map(([id, rs]) => ({ key: id, title: `From ${appName?.(id) ?? "an app"}`, rows: rs }))
139
+ .sort((a, b) => a.title.localeCompare(b.title))
140
+ .forEach((g) => groups.push(g));
141
+ return groups;
142
+ }
143
+
144
+ /** The sources the platform never deletes from here: an app's own job and what it shipped. */
145
+ const KEEPS = new Set(["legacy", "package"]);
146
+
147
+ /** The row's menu: Delete automation, or why it cannot be. */
148
+ function rowMenu(row, onDelete) {
149
+ if (!onDelete) return null;
150
+ if (KEEPS.has(row.source)) {
151
+ return [{ label: "Delete automation", icon: "trash", disabled: true, description: "Comes with the app. Switch it off, or remove it in the app's settings." }];
152
+ }
153
+ return [{ label: "Delete automation", icon: "trash", tone: "danger", onSelect: () => onDelete(row) }];
154
+ }
155
+
156
+ function Row({ row, appName, now, busy, canToggle, showOrigin, onOpen, onToggle, onDelete }) {
157
+ const menu = rowMenu(row, onDelete);
158
+ const health = healthOf(row);
159
+ const trig = triggerWords(row.trigger);
160
+ const last = row.last_run;
161
+ const next = row.status === "on" ? clockWords(row.next_run_at, row.tz, now) : null;
162
+ const lastWhen = last ? (agoWords(last.started_at ?? row.last_run_at, now) ?? "") : "";
163
+ return (
164
+ <li className={cx("@container relative flex min-w-0 items-center gap-3 rounded-lg border border-border bg-card px-3 py-2.5 text-card-foreground hover:bg-accent/30", row.status === "off" && "opacity-75")}>
165
+ {canToggle ? (
166
+ <span className="relative z-10 shrink-0">
167
+ <Switch
168
+ checked={row.status === "on"}
169
+ disabled={busy || row.live_version === null || row.live_version === undefined}
170
+ label={<span className="sr-only">{`${row.name} is ${row.status === "on" ? "on" : "off"}`}</span>}
171
+ onChange={(e) => onToggle(row, e.target.checked)}
172
+ />
173
+ </span>
174
+ ) : null}
175
+ <button
176
+ type="button"
177
+ data-card-link
178
+ onClick={() => onOpen(row.id)}
179
+ className="grid min-w-0 flex-1 items-center gap-x-4 gap-y-1 text-left after:absolute after:inset-0 after:content-[''] focus-visible:outline-none focus-visible:after:ring-2 focus-visible:after:ring-ring after:rounded-lg @xl:grid-cols-[minmax(0,2fr)_minmax(0,1.2fr)_minmax(0,0.9fr)_auto]"
180
+ >
181
+ <span className="grid min-w-0 gap-0.5">
182
+ <b className="truncate text-sm font-semibold">{row.live_name ?? row.name}</b>
183
+ <span className="truncate text-xs text-muted-foreground">
184
+ {showOrigin ? `${originWords(row, appName)} · ` : ""}
185
+ {trig}
186
+ {row.edited ? " · edited" : ""}
187
+ </span>
188
+ </span>
189
+ <span className="grid min-w-0 gap-0.5">
190
+ <span className="inline-flex min-w-0 items-center gap-1.5 text-[13px]">
191
+ <Dot tone={health.tone} />
192
+ <span className="truncate">{health.text}</span>
193
+ </span>
194
+ {lastWhen ? <span className="text-xs text-muted-foreground">{lastWhen}</span> : null}
195
+ </span>
196
+ <span className="grid min-w-0 gap-0.5">
197
+ <span className="text-xs text-muted-foreground">Next</span>
198
+ <b className="truncate text-[13px] font-medium">{next ?? "—"}</b>
199
+ </span>
200
+ <span className="font-mono text-xs text-muted-foreground @xl:text-right">{last ? creditsWords(last.credits) : ""}</span>
201
+ </button>
202
+ {menu ? (
203
+ <span className="relative z-10 shrink-0">
204
+ <Menu label={`More for ${row.name}`} items={menu} />
205
+ </span>
206
+ ) : null}
207
+ <Icon name="chevron-right" size={16} className="shrink-0 text-muted-foreground" />
208
+ </li>
209
+ );
210
+ }
211
+
212
+ function Start({ s, onPick, autoFocus }) {
213
+ return (
214
+ <button type="button" onClick={() => onPick(s)} autoFocus={autoFocus} className="flex min-w-0 items-start gap-3 rounded-lg border border-border bg-card p-3 text-left text-card-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring">
215
+ <span className="inline-flex size-10 shrink-0 items-center justify-center rounded-lg border border-border text-muted-foreground">{s.glyph ? <Glyph name={s.glyph} size={20} /> : <Icon name="plus" size={20} />}</span>
216
+ <span className="grid min-w-0 gap-0.5">
217
+ <b className="text-sm font-semibold">{s.name}</b>
218
+ <span className="text-xs text-muted-foreground">{s.blurb}</span>
219
+ {s.price ? <span className="text-xs text-muted-foreground">{startLine(s)}</span> : s.needs ? <span className="text-xs text-muted-foreground">You add: {s.needs}</span> : null}
220
+ </span>
221
+ </button>
222
+ );
223
+ }
224
+
225
+ /**
226
+ * The picker "New automation" opens when there are already some.
227
+ * open, onClose
228
+ * starts the starting points (default automation-model's STARTING_POINTS);
229
+ * [{ id, name, blurb, glyph, needs, build(taken) }], or the platform's
230
+ * (startsFromPlatform): plus { ai, price: { credits, per } }, drawn as
231
+ * "needs payments, a mailbox · a model writes three lines · about 6 cr"
232
+ * onPick(s), onBlank()
233
+ * onDescribe, onOpen, describePrice, describeChips as AutomationList's: "Describe it" at the top
234
+ */
235
+ export function StartingPoints({ open, onClose, starts = STARTING_POINTS, onPick, onBlank, onDescribe, onOpen, describePrice = DESCRIBE_PRICE, describeChips = DESCRIBE_CHIPS }) {
236
+ const list = useMemo(() => ready(starts), [starts]);
237
+ return (
238
+ <Sheet open={open} onClose={onClose} side="center" title="New automation">
239
+ <div className="grid gap-2">
240
+ {onDescribe ? <DescribeIt onDescribe={onDescribe} onOpen={onOpen} price={describePrice} chips={describeChips} /> : null}
241
+ <Start s={{ name: "Start empty", blurb: "A trigger and a blank canvas." }} onPick={() => onBlank?.()} autoFocus={!onDescribe} />
242
+ {onDescribe && list.length > 0 ? <h3 className="m-0 mt-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground">Start from a ready one</h3> : null}
243
+ {list.map((s) => (
244
+ <Start key={s.id} s={s} onPick={onPick} />
245
+ ))}
246
+ </div>
247
+ </Sheet>
248
+ );
249
+ }
250
+
251
+ /**
252
+ * rows the list: useAutomations().automations
253
+ * appName(id) an app's name, or null (a team list names apps)
254
+ * appFilter the app the list is filtered to, if any
255
+ * grouped group by Team and each app (default true); an app's own
256
+ * page passes false
257
+ * starts the first-run starting points (default automation-model's), or the
258
+ * platform's (useAutomations().starts, raw or through startsFromPlatform):
259
+ * each card also says what it needs, what a model does and what it costs
260
+ * onDescribe(ask) async: "Describe it". Resolves { ok, id? } (the new automation opens through
261
+ * onOpen(id)), { ok: false, questions: [..] } (listed under the box: "Ask me
262
+ * about: ...") or { ok: false, error } (shown). Without it, no Describe it card
263
+ * describePrice what the button says it costs (default "1 call · about 1 cr")
264
+ * describeChips sentences that start the box (default three: Monday mail, a won deal, a message)
265
+ * onOpen(id) a whole row opens
266
+ * onNew(start?) New automation, or a starting point from the first-run screen
267
+ * onToggle(row, on) async: the switch; a refusal throws its words
268
+ * onDelete(row) async: "Delete automation", in each row's menu, after a question that says what it does
269
+ * (Deletes "<name>". Its runs stay in history.; and, for one that is on, that it is
270
+ * switched off). Resolves { ok: true } (the screen says what followed: Undo, the
271
+ * automations that followed it) or { ok: false, error } (shown as it is). An app's own
272
+ * job and what an app shipped (`row.source` legacy, package) get the item disabled,
273
+ * pointing at the app's settings. Without it, no menu
274
+ * canDelete offer Delete automation at all (default true; hide it where the member may not)
275
+ * canToggle draw the switch (default true; hide it where the member may not)
276
+ * canCreate draw New automation (default true)
277
+ * onClearFilter "Showing one app. Show all"
278
+ * query the search box's words to start with (default ""). A screen that leaves the list
279
+ * (to open an automation) and comes back hands back what the member typed
280
+ * onQueryChange(text) the search box changed: keep it where the screen keeps its place
281
+ * title, intro the head's words
282
+ * now the clock (a test hands one in)
283
+ */
284
+ export function AutomationList({ rows, appName, appFilter = null, grouped = true, starts = STARTING_POINTS, onDescribe, describePrice = DESCRIBE_PRICE, describeChips = DESCRIBE_CHIPS, onOpen, onNew, onToggle, canToggle = true, canCreate = true, onDelete, canDelete = true, onClearFilter, query = "", onQueryChange, title = "Automations", intro = "What runs on its own, for your team and for each app.", now: nowProp, className }) {
285
+ const [q, setQ] = useState(typeof query === "string" ? query : "");
286
+ const [pending, setPending] = useState(null);
287
+ const [error, setError] = useState(null);
288
+ const [choosing, setChoosing] = useState(false);
289
+ const [deleting, setDeleting] = useState(null);
290
+ const [deletingBusy, setDeletingBusy] = useState(false);
291
+ const now = useMemo(() => nowProp ?? new Date(), [nowProp]);
292
+ const startList = useMemo(() => ready(starts), [starts]);
293
+ const describeBox = onDescribe && canCreate ? <DescribeIt onDescribe={onDescribe} onOpen={onOpen} price={describePrice} chips={describeChips} /> : null;
294
+ const shown = useMemo(() => {
295
+ const t = q.trim().toLowerCase();
296
+ return t ? rows.filter((r) => `${r.name} ${r.key}`.toLowerCase().includes(t)) : rows;
297
+ }, [rows, q]);
298
+ const groups = useMemo(() => (grouped ? groupRows(shown, appName) : [{ key: "all", title: "", rows: shown }]), [shown, appName, grouped]);
299
+ const sum = useMemo(() => summaryOf(rows, now), [rows, now]);
300
+
301
+ const toggle = async (row, on) => {
302
+ setPending(row.id);
303
+ setError(null);
304
+ try {
305
+ await onToggle?.(row, on);
306
+ } catch (e) {
307
+ setError(e instanceof Error ? e.message : "That did not work.");
308
+ } finally {
309
+ setPending(null);
310
+ }
311
+ };
312
+
313
+ const askDelete = onDelete && canDelete ? (row) => setDeleting(row) : null;
314
+ const confirmDelete = async () => {
315
+ const row = deleting;
316
+ if (!row) return;
317
+ setDeletingBusy(true);
318
+ setError(null);
319
+ try {
320
+ const r = await onDelete(row);
321
+ if (r && r.ok === false) setError(r.error || "That did not work.");
322
+ } catch (e) {
323
+ setError(e instanceof Error && e.message ? e.message : "That did not work.");
324
+ } finally {
325
+ setDeletingBusy(false);
326
+ setDeleting(null);
327
+ }
328
+ };
329
+
330
+ const newButton = canCreate ? (
331
+ <Button variant="primary" icon="plus" onClick={() => (rows.length ? setChoosing(true) : onNew?.())}>
332
+ New automation
333
+ </Button>
334
+ ) : null;
335
+
336
+ if (rows.length === 0) {
337
+ return (
338
+ <div className={cx("grid min-w-0 content-start gap-4 p-4", className)}>
339
+ <header className="flex flex-wrap items-start justify-between gap-3">
340
+ <div className="grid gap-0.5">
341
+ <h2 className="m-0 text-lg font-semibold">{title}</h2>
342
+ <p className="m-0 text-sm text-muted-foreground">{appFilter ? "This app has none yet." : "Nothing runs on its own yet."}</p>
343
+ </div>
344
+ {canCreate ? (
345
+ <Button variant="primary" icon="plus" onClick={() => onNew?.()}>
346
+ New automation
347
+ </Button>
348
+ ) : null}
349
+ </header>
350
+ {canCreate ? (
351
+ <>
352
+ {describeBox}
353
+ <section className="grid gap-1 rounded-lg border border-dashed border-border p-4">
354
+ <h3 className="m-0 text-sm font-semibold">Start from a ready one</h3>
355
+ <p className="m-0 text-sm text-muted-foreground">{onDescribe ? "Pick one, change what you like, test it with real data, then switch it on." : "Pick one, change what you like, test it with real data, then switch it on. Or ask the agent to draw one from a sentence."}</p>
356
+ </section>
357
+ <div className="@container">
358
+ <div className="grid gap-2 @xl:grid-cols-2">
359
+ {startList.map((s) => (
360
+ <Start key={s.id} s={s} onPick={onNew} />
361
+ ))}
362
+ </div>
363
+ </div>
364
+ </>
365
+ ) : null}
366
+ </div>
367
+ );
368
+ }
369
+
370
+ return (
371
+ <div className={cx("@container grid min-w-0 content-start gap-3 p-4", className)}>
372
+ <header className="flex flex-wrap items-start justify-between gap-3">
373
+ <div className="grid gap-0.5">
374
+ <h2 className="m-0 text-lg font-semibold">{title}</h2>
375
+ <p className="m-0 text-sm text-muted-foreground">{intro}</p>
376
+ </div>
377
+ {newButton}
378
+ </header>
379
+
380
+ {describeBox}
381
+
382
+ <div role="status" className="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground">
383
+ <span>
384
+ <b className="font-semibold text-foreground">{sum.on}</b> on
385
+ </span>
386
+ {sum.failing > 0 ? (
387
+ <span className="text-destructive">
388
+ <b className="font-semibold">{sum.failing}</b> failed last time
389
+ </span>
390
+ ) : null}
391
+ {sum.needs > 0 ? (
392
+ <span className="text-warning">
393
+ <b className="font-semibold">{sum.needs}</b> need{sum.needs === 1 ? "s" : ""} their owner
394
+ </span>
395
+ ) : null}
396
+ {sum.next ? (
397
+ <span>
398
+ Next: <b className="font-semibold text-foreground">{sum.next.name}</b>, {clockWords(sum.next.next_run_at, sum.next.tz, now)}
399
+ </span>
400
+ ) : null}
401
+ </div>
402
+
403
+ <div className="flex flex-wrap items-center gap-2">
404
+ <label className="relative block min-w-0 max-w-sm flex-1">
405
+ <Icon name="search" size={14} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
406
+ <input
407
+ type="search"
408
+ placeholder="Search automations"
409
+ aria-label="Search automations"
410
+ value={q}
411
+ onChange={(e) => {
412
+ setQ(e.target.value);
413
+ onQueryChange?.(e.target.value);
414
+ }}
415
+ className="min-h-9 w-full rounded-md border border-input bg-background pl-9 pr-3 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring"
416
+ />
417
+ </label>
418
+ {appFilter && onClearFilter ? (
419
+ <Button size="sm" variant="secondary" onClick={onClearFilter}>
420
+ Showing one app. Show all
421
+ </Button>
422
+ ) : null}
423
+ </div>
424
+
425
+ {error ? (
426
+ <p role="alert" className="m-0 rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm">
427
+ {error}
428
+ </p>
429
+ ) : null}
430
+
431
+ {shown.length === 0 ? <p className="m-0 text-sm text-muted-foreground">No automation matches “{q}”.</p> : null}
432
+ {groups.map((g) => (
433
+ <section key={g.key} aria-label={g.title || "Automations"} className="grid gap-1.5">
434
+ {g.title ? <h3 className="m-0 text-xs font-semibold uppercase tracking-wide text-muted-foreground">{g.title}</h3> : null}
435
+ <ul className="m-0 grid list-none gap-1.5 p-0">
436
+ {g.rows.map((r) => (
437
+ <Row key={r.id} row={r} appName={appName} now={now} busy={pending === r.id} canToggle={canToggle} showOrigin={grouped && !appFilter} onOpen={onOpen} onToggle={toggle} onDelete={askDelete} />
438
+ ))}
439
+ </ul>
440
+ </section>
441
+ ))}
442
+
443
+ <Confirm
444
+ open={deleting !== null}
445
+ onClose={() => (deletingBusy ? undefined : setDeleting(null))}
446
+ onConfirm={() => void confirmDelete()}
447
+ title="Delete this automation?"
448
+ body={deleting ? deleteWords(deleting.name, deleting.status) : ""}
449
+ confirmLabel="Delete"
450
+ tone="danger"
451
+ busy={deletingBusy}
452
+ />
453
+
454
+ <StartingPoints
455
+ open={choosing}
456
+ onClose={() => setChoosing(false)}
457
+ starts={startList}
458
+ onDescribe={onDescribe}
459
+ describePrice={describePrice}
460
+ describeChips={describeChips}
461
+ onOpen={(id) => {
462
+ setChoosing(false);
463
+ onOpen?.(id);
464
+ }}
465
+ onBlank={() => {
466
+ setChoosing(false);
467
+ onNew?.();
468
+ }}
469
+ onPick={(s) => {
470
+ setChoosing(false);
471
+ onNew?.(s);
472
+ }}
473
+ />
474
+ </div>
475
+ );
476
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "automation-list",
3
+ "title": "AutomationList",
4
+ "description": "An app's automations as rows, each a WHOLE row you press to open: what it is called, when it runs (in words, in the automation's own time zone), how its last run went as a dot and a word, when the next is due, what the last one cost, and an on/off switch that keeps its own press. A line above counts what is on, what failed and what waits for its owner; a search box; grouping into Team and each app when asked. With none yet it is the first-run screen: a few ready-made starting points. StartingPoints is the picker New automation opens. With onDescribe it opens with \"Describe it\": a sentence in a box that the platform turns into a draft; the platform's own starting points say what they need and cost. Each row has a menu with Delete automation, which asks first, says what it does and leaves the runs in history.",
5
+ "useWhen": "The Automations page of an app, or of the desk's own Automations window: the rows a member opens, switches and starts from. It replaces schedule-card for an app whose jobs run on the automations engine.",
6
+ "tags": [
7
+ "automation",
8
+ "workflow",
9
+ "list",
10
+ "rows",
11
+ "schedule",
12
+ "job",
13
+ "health",
14
+ "next run",
15
+ "last run",
16
+ "cost",
17
+ "switch",
18
+ "enabled",
19
+ "starting points",
20
+ "templates",
21
+ "n8n",
22
+ "make"
23
+ ],
24
+ "exports": [
25
+ "AutomationList",
26
+ "StartingPoints"
27
+ ],
28
+ "files": [
29
+ "index.js",
30
+ "automation-list.jsx"
31
+ ],
32
+ "requires": [
33
+ "automation-model"
34
+ ]
35
+ }
@@ -0,0 +1,67 @@
1
+ "use client";
2
+
3
+ // AutomationList with pretend automations — the gallery's and the smoke
4
+ // test's surface. Not installed into apps. Whole rows open, the switches
5
+ // work, New automation opens the starting points; then the same list with
6
+ // none (the first-run screen). A width picker shows 1280, 800, 368, 320.
7
+ import { useState } from "react";
8
+ import { Button, ButtonGroup } from "../components/ui";
9
+ import { AutomationList } from "../components/blocks/automation-list";
10
+ import { startsFromPlatform } from "../components/blocks/automation-model";
11
+
12
+ const NOW = new Date("2026-10-11T12:00:00.000Z");
13
+ const ROWS = [
14
+ { id: "a1", key: "morning-read", name: "Morning read", status: "on", live_version: 3, draft_version: 3, edited: true, owner_kind: "app", app_id: "crm", trigger: { type: "schedule", cron: "0 7 * * 1-5", tz: "team" }, tz: "America/New_York", next_run_at: "2026-10-12T11:00:00.000Z", last_run: { status: "done", started_at: "2026-10-09T11:00:03.000Z", credits: 4.2 }, active_runs: 0 },
15
+ { id: "a2", key: "friday-review", name: "Friday review", status: "on", live_version: 1, trigger: { type: "schedule", cron: "0 15 * * 5", tz: "team" }, tz: "America/New_York", next_run_at: "2026-10-16T19:00:00.000Z", last_run: { status: "failed", started_at: "2026-10-09T19:00:03.000Z", credits: 0.8 }, active_runs: 0, owner_kind: "app", app_id: "crm" },
16
+ { id: "a3", key: "weekly-signups", name: "Weekly signups", status: "off", live_version: 2, trigger: { type: "schedule", cron: "0 9 * * 1", tz: "team" }, tz: "UTC", next_run_at: null, last_run: null, owner_kind: "workspace", app_id: null },
17
+ { id: "a4", key: "new-one", name: "A draft I started", status: "draft", live_version: null, draft_version: 1, trigger: { type: "manual" }, tz: "UTC", last_run: null, owner_kind: "workspace", app_id: null },
18
+ ];
19
+ // What the desk's GET automation-starts sends, turned into the cards' shape.
20
+ const STARTS = startsFromPlatform([
21
+ { id: "weekly-digest", name: "A weekly digest by mail", blurb: "Collects the week and mails it to you.", needs: ["a mailbox"], ai: "a model writes three lines", credits: 6, glyph: "llm", definition: { format: 1, key: "weekly-digest", name: "Weekly digest", trigger: { type: "manual" }, inputs: {}, settings: {}, steps: [{ id: "tell", kind: "notify", message: "Hi" }] } },
22
+ { id: "monday-note", name: "A note every Monday", blurb: "Leaves a note at the start of each week.", needs: [], ai: "", credits: 0, glyph: "trigger-schedule", definition: { format: 1, key: "monday-note", name: "Monday note", trigger: { type: "manual" }, inputs: {}, settings: {}, steps: [{ id: "tell", kind: "notify", message: "Hi" }] } },
23
+ ]);
24
+ // A pretend "Describe it": a short sentence gets questions back, a longer one gets drawn.
25
+ const describe = async (ask) => {
26
+ await new Promise((r) => setTimeout(r, 700));
27
+ return ask.length < 24 ? { ok: false, code: "needs_answer", questions: ["Who should it tell?", "How often should it run?"] } : { ok: true, id: "a1" };
28
+ };
29
+ const WIDTHS = [1280, 800, 368, 320];
30
+
31
+ export default function AutomationListDemo() {
32
+ const [width, setWidth] = useState(800);
33
+ const [rows, setRows] = useState(ROWS);
34
+ const [said, setSaid] = useState("Nothing pressed.");
35
+ return (
36
+ <div className="grid gap-4 p-4">
37
+ <ButtonGroup aria-label="The block's width">
38
+ {WIDTHS.map((w) => (
39
+ <Button key={w} size="sm" variant={w === width ? "primary" : "secondary"} onClick={() => setWidth(w)}>
40
+ {w} px
41
+ </Button>
42
+ ))}
43
+ </ButtonGroup>
44
+ <p className="m-0 text-sm" role="status">
45
+ {said}
46
+ </p>
47
+ <div className="w-full rounded-lg border border-border" style={{ maxWidth: width }}>
48
+ <AutomationList
49
+ rows={rows}
50
+ now={NOW}
51
+ appName={(id) => (id === "crm" ? "CRM" : null)}
52
+ starts={STARTS}
53
+ onDescribe={describe}
54
+ onOpen={(id) => setSaid(`Opened ${id}.`)}
55
+ onNew={(s) => setSaid(s ? `New from “${s.name}”.` : "New, blank.")}
56
+ onToggle={async (row, on) => {
57
+ await new Promise((r) => setTimeout(r, 400));
58
+ setRows(rows.map((x) => (x.id === row.id ? { ...x, status: on ? "on" : "off" } : x)));
59
+ }}
60
+ />
61
+ </div>
62
+ <div className="w-full rounded-lg border border-border" style={{ maxWidth: width }}>
63
+ <AutomationList rows={[]} appFilter="crm" starts={STARTS} onDescribe={describe} onOpen={(id) => setSaid(`Opened ${id}.`)} onNew={(s) => setSaid(s ? `New from “${s.name}”.` : "New, blank.")} />
64
+ </div>
65
+ </div>
66
+ );
67
+ }
@@ -0,0 +1,3 @@
1
+ // The AutomationList block — `makersclaw add automation-list`. Fixed:
2
+ // compose it through its props (README.md beside this file).
3
+ export { AutomationList, StartingPoints } from "./automation-list";