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,159 @@
1
+ # ScheduleGantt
2
+
3
+ A Gantt for dated work with dependencies, where the question is "when do we
4
+ finish, and what decides it?". The task sheet on the left and a working-day
5
+ time scale on the right are one picture, row for row.
6
+
7
+ - **Bars** in steel grey with their progress inside; finished work full; a
8
+ phase a bracket over its work (it folds); a milestone a diamond.
9
+ - **Links of all four kinds** (finish to start, start to start, finish to
10
+ finish, start to finish) with lag, drawn as elbows. A link the dates break
11
+ is dashed with a cross. The critical path turns red when the page switches
12
+ it on.
13
+ - **The header says the news**: today, the target (dashed), the finish
14
+ (solid), and the gap between them in working days ("Finish Nov 3 · 7 wd
15
+ late").
16
+ - **Drag a bar** to move it (several selected move together), **an end** to
17
+ change its length, **the dot past its end onto another bar** to link them.
18
+ Everything that waits on it moves with it while you drag, the finish slides
19
+ away from the target, and a note by the bar says what it costs. Let go and
20
+ one `onMove` carries every changed date.
21
+ - **Dashed outlines** show where a bar was (`ghosts`) or where a suggestion
22
+ would put it (`pencil`); a thin bar under each shows a baseline.
23
+ - **Lanes under the rows** (who is on what) share the scale.
24
+ - **Type into the sheet**: double-click a name, a length, a percentage or
25
+ what a task waits on (`2.4FS+2d`); the last row adds a task (Enter) or a
26
+ milestone (Shift+Enter, Tab makes it a sub-task).
27
+
28
+ Born in a Gantt planner's app, which drew all of it by hand beside its own
29
+ engine. The template's `gantt` block is the neighbour for calendar-day work
30
+ with finish-to-start links only; this one is for working days, four link
31
+ kinds, lag, slack, a critical path and a baseline.
32
+
33
+ ```jsx
34
+ import { ScheduleGantt } from "../components/blocks/schedule-gantt"; // a Makersclaw app ("./blocks/schedule-gantt" from components/)
35
+ // shadcn project: import { ScheduleGantt } from "@/components/makersclaw/blocks/schedule-gantt"
36
+ ```
37
+
38
+ A client component; it needs the `schedule-engine` block (added with it). The
39
+ size is the parent's: put it where a height is set (the app's `AppLayout`
40
+ content) and it fills it, the sheet and the bars scrolling together, the time
41
+ scale scrolling inside the chart.
42
+
43
+ ## Rows in
44
+
45
+ - `tasks`: `{ id, parent_id, title, start_date, due_date, is_milestone,
46
+ progress, status, position, assignee_id, assignee_name, created_at }`
47
+ (dates `'YYYY-MM-DD'`). A parent with children is a phase.
48
+ - `links`: `{ id, task_id, depends_on_id, kind, lag_days }`: `task_id` waits
49
+ on `depends_on_id`.
50
+ - `people`: `Map(id → { name, left? })`; `left: true` writes "(left)" after
51
+ the name.
52
+
53
+ ## Props
54
+
55
+ - `today`, `target`: `'YYYY-MM-DD'`. `showToday` (true).
56
+ - `zoom`: `"day" | "week" | "month" | "fit"` (`fit`: the whole span in the
57
+ width). `fitWidth`: the width to fit, default the container's.
58
+ - `columns`: the sheet's columns, in order, from `outline`, `title`,
59
+ `start`, `due`, `days`, `done`, `who`, `waits`, `slack`, `vs`. Default
60
+ `["outline","title","who","days","done"]`. `vsLabel`: the baseline
61
+ column's heading ("vs Kickoff"). Under 760px of its own width the sheet
62
+ keeps the number and the title.
63
+ - `gridWidth`: the sheet's width, 470 (the divider drags it);
64
+ `onGridWidth(w)` when it is let go. `rowH`: 30.
65
+ - `height`: `"fill"` (default; the parent sets it) or a pixel number.
66
+ - `critical`: draw the critical path in red.
67
+ - `selectedId`, `selectedIds` (a Set: with more than one, dragging one moves
68
+ them all), `onSelect(id | null, { additive })`; `collapsed` (a Set of phase
69
+ ids), `onToggle(id)`; `highlight` (a Set of ids; the rest fade).
70
+ - `ghosts`: `Map(id → { start, due })` where bars were. `pencil`: the same
71
+ for where a suggestion would put them. `baseline`: the same for a saved
72
+ baseline, a thin bar under each. `guesses`: a Set of ids whose length is a
73
+ guess ("5 wd?", in blue). `moving`: a Set of ids whose dates are changing.
74
+ - `notes`: `Map(id → { text, tone? })` words after a bar (`tone: "crit"` red,
75
+ `"problem"` red and bold); on a row with no bar, the words stand where
76
+ the bar would. `tags`: `Map(id → [{ label, kind }])` in the row, `kind`:
77
+ `late`, `pole`, `unsaved`, `crit`, `blue`, `ink`, `quiet`, or
78
+ `agent` (a small filled badge, `title` on hover) and `dot` (a warning dot).
79
+ - `lanes`: `[{ id, label, sub, items: [{ id, title, start, due }], marks:
80
+ [{ from, to, count, title }] }]` under the rows; `lanesTitle`: the heading
81
+ node of that section.
82
+ - `rowMenu(task, { row, plan })` → Menu items for the row's "…" (built for
83
+ the hovered or selected row only).
84
+ - `addUnder`: `{ id (a parent) | null, afterId, milestone, nonce }` opens
85
+ the add row under a row; `editRequest`: `{ id, field, nonce }` opens a
86
+ cell; `jump`: `{ date, nonce }` scrolls to a day.
87
+ - `loading` (skeleton rows), `error` (a line above the chart), `emptyText`,
88
+ `label` (a screen reader's name for the chart), `className`.
89
+
90
+ ## Callbacks
91
+
92
+ Every write answers `{ ok: true }` or `{ ok: false, error }`; a failure puts
93
+ the chart back and says so above it. Without a callback that part is
94
+ read-only: no drag, no link, no typing.
95
+
96
+ - `onMove(moves, preview)`: a finished drag or an Alt+arrow. `moves` is
97
+ `[{ id, start, due }]` (what was asked); `preview.changes` is every date
98
+ the engine shifted, `[{ id, start_date, due_date, from, summary? }]`, so
99
+ the page can show them at once and save them in one write.
100
+ - `onLink({ taskId, dependsOnId, kind }, preview)`: the dot dropped on a bar.
101
+ The kind comes from which ends were joined. A link that would loop is
102
+ refused in words before the drop.
103
+ - `onEdit(task, field, value)`: `title`, `days`, `progress`, `waits` (the
104
+ short form; parse it with the engine's `parseWaits`).
105
+ - `onAdd({ title, days, milestone, parentId, afterId })` → `{ ok, id }`.
106
+ - `onOpen(task)`: Enter or a double-click. `onOpenLink(link)`: a double-click
107
+ on a link line, or Ctrl-click on a waits-on cell.
108
+ - `onPreview(info | null)`: while a drag or a pulled link runs: `{ mode:
109
+ "move" | "stretch" | "link", task, cost (working days the finish moves),
110
+ followers, startShift, lengthShift, slack, critical, duration, start, due,
111
+ finishBefore, finishAfter, finishTitle, clamped }`. The page shows the
112
+ finish counting up in its top bar.
113
+
114
+ ## Keys
115
+
116
+ ↑ ↓ move the selection; Enter opens; F2 renames; Alt+← → moves the task a
117
+ working day with everything that waits on it; Esc drops a drag or clears the
118
+ selection; in the add row Enter adds a task, Shift+Enter a milestone, Tab
119
+ makes it a sub-task of the row above.
120
+
121
+ ## Example
122
+
123
+ ```jsx
124
+ <ScheduleGantt
125
+ tasks={tasks}
126
+ links={links}
127
+ people={people}
128
+ today="2026-09-24"
129
+ target="2026-10-23"
130
+ zoom="week"
131
+ columns={["outline", "title", "start", "due", "days", "done", "who", "waits"]}
132
+ critical={showCritical}
133
+ selectedId={selectedId}
134
+ onSelect={setSelectedId}
135
+ onOpen={(t) => open(t.id)}
136
+ onMove={(moves, preview) => save(preview.changes)}
137
+ onLink={(link) => addLink(link)}
138
+ onEdit={(task, field, value) => edit(task, field, value)}
139
+ onAdd={(draft) => addTask(draft)}
140
+ onPreview={setLive}
141
+ />
142
+ ```
143
+
144
+ ## States drawn in the demo
145
+
146
+ A plan with every kind of row; the critical path on; a baseline and its
147
+ column; ghosts and pencil; a loop; a plan with no dates; lanes; the whole
148
+ project at once; loading; failed; empty; read-only; a narrow (320px)
149
+ container.
150
+
151
+ ## Notes
152
+
153
+ - Dates are days, never instants, so the server and the browser draw the same
154
+ picture. Weekends are shaded and skipped; there are no holidays.
155
+ - Positions are measured in pixels per day by zoom; a very long plan scrolls
156
+ inside the chart. 300 rows is fine; virtualise past a few thousand.
157
+ - Colour is a signal: red is the critical path or a broken link, amber is
158
+ late or the gap past the target, green the gap in front of it, blue the
159
+ agent (a guess, a suggestion), the accent today and the selection.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "schedule-gantt",
3
+ "title": "ScheduleGantt",
4
+ "description": "A Gantt for dated work with dependencies: the task sheet beside a working-day time scale, one picture row for row. Outline numbers, phases that fold into a bracket over their work, milestones as diamonds, bars in steel grey with their progress, links of all four kinds with lag drawn as elbows (a broken one dashed with a cross), weekends shaded, today a line, the target a dashed line and the finish a solid one with the gap between them counted in working days in the header. The critical path turns red when switched on; slack, the start and finish, the length in working days, the owner, what a task waits on in the short form (2.4FS+2d) and its distance from a baseline are columns the page picks, and the divider between sheet and bars drags. Drag a bar to move it (several selected move together), an end to change its length, the dot past its end onto another bar to link them: every task that waits on it moves while you drag, the finish in the header slides off the target and a note by the bar says what it costs. Dashed outlines show where bars were and where a suggestion would put them; a thin bar under each shows a baseline; lanes under the rows show who is on what, on the same scale. Type into the sheet: names, lengths, percentages, what a task waits on, and a last row that adds a task (Enter) or a milestone (Shift+Enter). Built on schedule-engine.",
5
+ "useWhen": "A project plan where the question is 'when do we finish and what decides it': tasks with lengths in working days, links of four kinds with lag, slack, a critical path, a target date, a saved baseline, and dates that must move when something slips. Not for calendar-day work with finish-to-start links only (gantt), phases against gates (schedule-ruler), stage columns (board) or undated to-dos (task-list).",
6
+ "tags": ["gantt", "schedule", "project plan", "critical path", "slack", "dependencies", "working days", "baseline", "lag", "milestones", "drag", "slip", "ripple", "ms project", "teamgantt", "workload", "target", "timeline"],
7
+ "exports": ["ScheduleGantt", "TagChip", "CellInput", "ROW", "ZOOMS", "axisFor", "rangeFor", "routeLink", "shortDate", "isoToday", "COLUMNS", "DEFAULT_COLUMNS", "MONTHS", "WEEKDAYS", "baselineDelta", "barLabel", "columnsFor", "describeDrag", "dayWords", "dragLines", "fixedWidth", "gapOf", "lengthWords", "linkLines", "loopWords", "monthDay", "selectionMoves", "slackWords"],
8
+ "files": ["index.js", "schedule-gantt.jsx", "sheet.jsx", "track.jsx", "geometry.js", "gantt-model.js"],
9
+ "requires": ["schedule-engine"]
10
+ }
@@ -0,0 +1,223 @@
1
+ "use client";
2
+
3
+ // ScheduleGantt in every state — the gallery's and the smoke test's surface.
4
+ // Not installed into apps: `makersclaw add schedule-gantt` lays index.js,
5
+ // schedule-gantt.jsx, sheet.jsx, track.jsx, geometry.js and gantt-model.js
6
+ // only.
7
+ // Plan a launch plan with phases, a milestone, links of all four
8
+ // kinds, lag, a late task; drag, link, type, add; the critical
9
+ // path and slack switches; a baseline and its column; zoom
10
+ // Ghosts where the agent moved things, and where it would put them
11
+ // People lanes under the rows: who is on two things at once
12
+ // Loop two tasks that wait on each other
13
+ // No dates a list with lengths and no dates
14
+ // Whole the whole project at once
15
+ // Narrow a 320px container: the number and the title
16
+ // Loading, failed, empty and read-only
17
+ import { useMemo, useState } from "react";
18
+ import { Button, Notice, Switch } from "../components/ui";
19
+ import { ScheduleGantt } from "../components/blocks/schedule-gantt";
20
+ import { shiftDependents } from "../components/blocks/schedule-engine";
21
+
22
+ const TODAY = "2026-09-24";
23
+ const TARGET = "2026-10-23";
24
+
25
+ const t = (id, title, start, due, extra = {}) => ({ id, parent_id: null, title, start_date: start, due_date: due, is_milestone: false, progress: 0, status: "todo", position: Number(id.replace(/\D/g, "")) || 1, ...extra });
26
+ const PEOPLE = new Map([
27
+ ["maya", { name: "Maya Chen" }],
28
+ ["tom", { name: "Tom Okafor" }],
29
+ ["priya", { name: "Priya Raman" }],
30
+ ["dana", { name: "Dana Ferreira", left: true }],
31
+ ]);
32
+ const TASKS = [
33
+ t("p1", "Design", "2026-09-07", "2026-09-25", { progress: 90 }),
34
+ t("t11", "Resource model and naming", "2026-09-07", "2026-09-11", { parent_id: "p1", progress: 100, status: "done", assignee_id: "tom" }),
35
+ t("t12", "OpenAPI draft", "2026-09-14", "2026-09-18", { parent_id: "p1", position: 2, progress: 100, status: "done", assignee_id: "priya" }),
36
+ t("t13", "API review with partners", "2026-09-21", "2026-09-25", { parent_id: "p1", position: 3, progress: 80, assignee_id: "maya" }),
37
+ t("m1", "Design frozen", "2026-09-25", "2026-09-25", { parent_id: "p1", position: 4, is_milestone: true }),
38
+ t("p2", "Build", "2026-09-28", "2026-10-16", { position: 2 }),
39
+ t("t21", "Invoices", "2026-09-28", "2026-10-02", { parent_id: "p2", assignee_id: "tom" }),
40
+ t("t22", "Webhooks delivery", "2026-10-05", "2026-10-09", { parent_id: "p2", position: 2, assignee_id: "tom" }),
41
+ t("t23", "Sandbox environment", "2026-09-17", "2026-09-24", { parent_id: "p2", position: 3, progress: 35, assignee_id: "priya" }),
42
+ t("t24", "Nightly CSV export", "2026-10-01", "2026-10-07", { parent_id: "p2", position: 4, assignee_id: "priya" }),
43
+ t("t25", "Idempotency keys", "2026-10-12", "2026-10-13", { parent_id: "p2", position: 5 }),
44
+ t("m2", "Feature complete", "2026-10-14", "2026-10-14", { parent_id: "p2", position: 6, is_milestone: true }),
45
+ t("p3", "Launch", "2026-10-15", "2026-10-23", { position: 3 }),
46
+ t("t31", "Support playbook", "2026-10-15", "2026-10-19", { parent_id: "p3", assignee_id: "dana" }),
47
+ t("t32", "Switch the API to general availability", "2026-10-20", "2026-10-22", { parent_id: "p3", position: 2, assignee_id: "tom" }),
48
+ t("m3", "Public launch", "2026-10-23", "2026-10-23", { parent_id: "p3", position: 3, is_milestone: true }),
49
+ ];
50
+ const L = (id, task, dep, kind = "finish_to_start", lag = 0) => ({ id, task_id: task, depends_on_id: dep, kind, lag_days: lag });
51
+ const LINKS = [
52
+ L("l1", "t12", "t11"),
53
+ L("l2", "t13", "t12"),
54
+ L("l3", "m1", "t13"),
55
+ L("l4", "t21", "m1"),
56
+ L("l5", "t22", "t21"),
57
+ L("l6", "t23", "t12", "start_to_start", 3),
58
+ L("l7", "t24", "t22", "start_to_finish"),
59
+ L("l8", "t25", "t22", "finish_to_start", 1),
60
+ L("l9", "m2", "t25"),
61
+ L("l10", "t31", "m2"),
62
+ L("l11", "t32", "t31", "finish_to_finish", 1),
63
+ L("l12", "m3", "t32"),
64
+ ];
65
+ const BASELINE = new Map([
66
+ ["t13", { start: "2026-09-21", due: "2026-09-23" }],
67
+ ["t22", { start: "2026-10-01", due: "2026-10-05" }],
68
+ ["t32", { start: "2026-10-12", due: "2026-10-14" }],
69
+ ["m3", { start: "2026-10-15", due: "2026-10-15" }],
70
+ ]);
71
+ const GHOSTS = new Map([
72
+ ["t13", { start: "2026-09-14", due: "2026-09-18" }],
73
+ ["t24", { start: "2026-09-23", due: "2026-09-29" }],
74
+ ]);
75
+ const PENCIL = new Map([["t25", { start: "2026-10-09", due: "2026-10-12" }]]);
76
+ const LANES = [
77
+ { id: "tom", label: "Tom Okafor", sub: "3 open", items: [{ id: "a", title: "Invoices", start: "2026-09-28", due: "2026-10-02" }, { id: "b", title: "Webhooks delivery", start: "2026-10-05", due: "2026-10-09" }, { id: "c", title: "Switch the API", start: "2026-10-20", due: "2026-10-22" }], marks: [] },
78
+ { id: "priya", label: "Priya Raman", sub: "2 open", items: [{ id: "d", title: "Sandbox", start: "2026-09-17", due: "2026-09-24" }, { id: "e", title: "CSV export", start: "2026-10-01", due: "2026-10-07" }], marks: [] },
79
+ ];
80
+ const LOOP = [t("a", "Cabling and server closet", "2026-10-12", "2026-10-16"), t("b", "Pack and label", "2026-10-19", "2026-10-23", { position: 2 })];
81
+ const LOOP_LINKS = [L("x", "a", "b"), L("y", "b", "a")];
82
+ const NO_DATES = [t("n1", "Survey current pick paths", null, null), t("n2", "Rank SKUs by velocity", null, null, { position: 2 }), t("n3", "Re-slotting done", null, null, { position: 3, is_milestone: true })];
83
+
84
+ function Frame({ title, note, children, height = 380, width }) {
85
+ return (
86
+ <section className="grid gap-2">
87
+ <h3 className="text-sm font-semibold">{title}</h3>
88
+ {note ? <p className="text-xs text-muted-foreground">{note}</p> : null}
89
+ <div className="overflow-hidden border border-border" style={{ height, width }}>
90
+ {children}
91
+ </div>
92
+ </section>
93
+ );
94
+ }
95
+
96
+ export default function ScheduleGanttDemo() {
97
+ const [tasks, setTasks] = useState(TASKS);
98
+ const [links, setLinks] = useState(LINKS);
99
+ const [selected, setSelected] = useState("t22");
100
+ const [collapsed, setCollapsed] = useState(() => new Set(["p1"]));
101
+ const [critical, setCritical] = useState(true);
102
+ const [baseline, setBaseline] = useState(true);
103
+ const [zoom, setZoom] = useState("week");
104
+ const [live, setLive] = useState(null);
105
+ const [said, setSaid] = useState("Drag a bar, pull the dot at its end onto another, or type in the sheet.");
106
+
107
+ const apply = (changes) => setTasks((cur) => cur.map((x) => { const c = changes.find((y) => String(y.id) === x.id); return c ? { ...x, start_date: c.start_date, due_date: c.due_date } : x; }));
108
+ const onMove = async (moves, preview) => {
109
+ apply(preview.changes);
110
+ setSaid(`Moved ${moves[0].id}; ${preview.changes.length} dates saved at once.`);
111
+ return { ok: true };
112
+ };
113
+ const onLink = async ({ taskId, dependsOnId, kind }, preview) => {
114
+ setLinks((cur) => [...cur, { id: `new${cur.length}`, task_id: taskId, depends_on_id: dependsOnId, kind, lag_days: 0 }]);
115
+ if (preview?.changes) apply(preview.changes);
116
+ setSaid(`Linked ${taskId} to wait on ${dependsOnId} (${kind}).`);
117
+ return { ok: true };
118
+ };
119
+ const onEdit = async (task, field, value) => {
120
+ if (field === "title") setTasks((cur) => cur.map((x) => (x.id === task.id ? { ...x, title: value } : x)));
121
+ if (field === "progress") setTasks((cur) => cur.map((x) => (x.id === task.id ? { ...x, progress: Number(value) || 0 } : x)));
122
+ if (field === "days") {
123
+ const r = shiftDependents(tasks, links, [{ id: task.id, start: task.start_date, due: task.due_date }]);
124
+ apply(r.changes);
125
+ }
126
+ setSaid(`Changed ${field} of ${task.title}.`);
127
+ return { ok: true };
128
+ };
129
+ const onAdd = async ({ title, days, milestone }) => {
130
+ const id = `new${tasks.length}`;
131
+ setTasks((cur) => [...cur, { ...t(id, title, "2026-10-26", "2026-10-28", { position: cur.length + 1, is_milestone: Boolean(milestone) }), progress: 0, days }]);
132
+ return { ok: true, id };
133
+ };
134
+ const failing = async () => ({ ok: false, error: "Three dates didn't save: the plan's records did not answer." });
135
+ const people = useMemo(() => PEOPLE, []);
136
+
137
+ return (
138
+ <div className="grid gap-6 p-4">
139
+ <Notice>{live ? `Dragging ${live.task?.title}: the finish moves ${live.cost} wd (${live.finishBefore} to ${live.finishAfter}).` : said}</Notice>
140
+ <div className="grid gap-2 sm:grid-cols-[auto_auto_auto_auto_1fr] sm:items-center">
141
+ <Switch id="gantt-demo-critical" checked={critical} onChange={(e) => setCritical(e.target.checked)} label="Critical path" />
142
+ <Switch id="gantt-demo-baseline" checked={baseline} onChange={(e) => setBaseline(e.target.checked)} label="Baseline" />
143
+ <div className="flex gap-1">
144
+ {["day", "week", "month", "fit"].map((z) => (
145
+ <Button key={z} size="sm" variant={zoom === z ? "primary" : "quiet"} onClick={() => setZoom(z)}>{z}</Button>
146
+ ))}
147
+ </div>
148
+ </div>
149
+
150
+ <Frame title="Plan" note="Phase 1 is folded. Alt+arrows move the selected task a working day." height={460}>
151
+ <ScheduleGantt
152
+ tasks={tasks}
153
+ links={links}
154
+ people={people}
155
+ today={TODAY}
156
+ target={TARGET}
157
+ zoom={zoom}
158
+ columns={baseline ? ["outline", "title", "start", "due", "days", "done", "who", "waits", "slack", "vs"] : ["outline", "title", "start", "due", "days", "done", "who", "waits"]}
159
+ vsLabel="vs Kickoff"
160
+ critical={critical}
161
+ baseline={baseline ? BASELINE : undefined}
162
+ selectedId={selected}
163
+ onSelect={setSelected}
164
+ collapsed={collapsed}
165
+ onToggle={(id) => setCollapsed((cur) => { const n = new Set(cur); if (n.has(id)) n.delete(id); else n.add(id); return n; })}
166
+ onOpen={(task) => setSaid(`Open ${task.title}`)}
167
+ onMove={onMove}
168
+ onLink={onLink}
169
+ onEdit={onEdit}
170
+ onAdd={onAdd}
171
+ onPreview={setLive}
172
+ onOpenLink={(l) => setSaid(`Change the link ${l.id}`)}
173
+ tags={new Map([["t22", [{ kind: "pole", label: "long pole" }]], ["t13", [{ kind: "agent", title: "Re-planned from today" }]], ["t23", [{ kind: "dot", title: "Due today, 35% done" }]]])}
174
+ label="The plan of Public API v1"
175
+ />
176
+ </Frame>
177
+
178
+ <Frame title="Where it was, where it would go" note="Dashed grey: this morning's check moved these. Dashed blue: a suggestion's place for Idempotency keys." height={320}>
179
+ <ScheduleGantt tasks={TASKS} links={LINKS} people={people} today={TODAY} target={TARGET} ghosts={GHOSTS} pencil={PENCIL} critical selectedId="t13" columns={["outline", "title", "who", "waits"]} />
180
+ </Frame>
181
+
182
+ <Frame title="People" note="Lanes under the rows, on the same scale." height={380}>
183
+ <ScheduleGantt tasks={TASKS} links={LINKS} people={people} today={TODAY} target={TARGET} lanes={LANES} lanesTitle="People's load" columns={["outline", "title", "who"]} />
184
+ </Frame>
185
+
186
+ <Frame title="A loop" note="Two tasks wait on each other: they are drawn dashed and not placed." height={200}>
187
+ <ScheduleGantt tasks={LOOP} links={LOOP_LINKS} today={TODAY} columns={["outline", "title", "due", "waits"]} notes={new Map([["a", { text: "Not placed: waits on 2, which waits on 1", tone: "problem" }]])} onOpenLink={() => {}} />
188
+ </Frame>
189
+
190
+ <Frame title="No dates" note="Lengths first; a start date works the dates out." height={200}>
191
+ <ScheduleGantt tasks={NO_DATES} links={[]} today={TODAY} columns={["outline", "title", "days"]} guesses={new Set(["n2"])} onEdit={onEdit} onAdd={onAdd} />
192
+ </Frame>
193
+
194
+ <Frame title="The whole project" note="Folded to its phases, in the width there is." height={260}>
195
+ <ScheduleGantt tasks={TASKS} links={LINKS} today={TODAY} target={TARGET} zoom="fit" collapsed={new Set(["p1", "p2", "p3"])} columns={["outline", "title"]} />
196
+ </Frame>
197
+
198
+ <Frame title="Narrow (320px)" height={260} width={320}>
199
+ <ScheduleGantt tasks={TASKS} links={LINKS} people={people} today={TODAY} target={TARGET} columns={["outline", "title", "who", "days"]} />
200
+ </Frame>
201
+
202
+ <Frame title="Loading" height={200}>
203
+ <ScheduleGantt tasks={[]} links={[]} today={TODAY} loading />
204
+ </Frame>
205
+
206
+ <Frame title="Failed" height={200}>
207
+ <ScheduleGantt tasks={[]} links={[]} today={TODAY} error="The plan could not be read: the records did not answer." />
208
+ </Frame>
209
+
210
+ <Frame title="Empty" height={200}>
211
+ <ScheduleGantt tasks={[]} links={[]} today={TODAY} onAdd={onAdd} />
212
+ </Frame>
213
+
214
+ <Frame title="A save that fails" note="Drag any bar: the chart puts it back and says why." height={280}>
215
+ <ScheduleGantt tasks={TASKS} links={LINKS} today={TODAY} target={TARGET} onMove={failing} columns={["outline", "title", "due"]} />
216
+ </Frame>
217
+
218
+ <Frame title="Read-only" note="No callbacks: no drag, no link, no typing." height={260}>
219
+ <ScheduleGantt tasks={TASKS} links={LINKS} people={people} today={TODAY} target={TARGET} columns={["outline", "title", "who", "days"]} />
220
+ </Frame>
221
+ </div>
222
+ );
223
+ }
@@ -0,0 +1,219 @@
1
+ // The chart's arithmetic and words, with no React: the columns of the sheet,
2
+ // how a date is written, the gap between the finish and the target, what a
3
+ // baseline says about a row, and what a drag costs. Pure, so it is tested
4
+ // under node and the chart only draws what it says.
5
+
6
+ import { dayOf, linkKind, workdaysBetween } from "../schedule-engine";
7
+
8
+ export const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
9
+ export const WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
10
+ const DAY_MS = 86400000;
11
+
12
+ /** "Oct 23" */
13
+ export function monthDay(iso) {
14
+ const d = dayOf(iso);
15
+ if (d == null) return "";
16
+ const x = new Date(d * DAY_MS);
17
+ return `${MONTHS[x.getUTCMonth()]} ${x.getUTCDate()}`;
18
+ }
19
+
20
+ /** "Fri Oct 23" */
21
+ export function dayWords(iso) {
22
+ const d = dayOf(iso);
23
+ if (d == null) return "";
24
+ const x = new Date(d * DAY_MS);
25
+ return `${WEEKDAYS[(((d + 3) % 7) + 7) % 7]} ${MONTHS[x.getUTCMonth()]} ${x.getUTCDate()}`;
26
+ }
27
+
28
+ /** The sheet's columns: label, width in px (the title takes the rest), and which side its text sits. */
29
+ export const COLUMNS = {
30
+ outline: { label: "#", w: 50 },
31
+ title: { label: "Task" },
32
+ start: { label: "Start", w: 56 },
33
+ due: { label: "Finish", w: 56 },
34
+ days: { label: "Length", w: 50, right: true },
35
+ done: { label: "Done", w: 44, right: true },
36
+ who: { label: "Owner", w: 62 },
37
+ waits: { label: "Waits on", w: 88 },
38
+ slack: { label: "Slack", w: 50, right: true },
39
+ vs: { label: "vs baseline", w: 66, right: true },
40
+ };
41
+ export const DEFAULT_COLUMNS = ["outline", "title", "who", "days", "done"];
42
+
43
+ /**
44
+ * The columns to draw: the keys asked for that exist, the title always
45
+ * there (after the outline number), a narrow container only the number and
46
+ * the title.
47
+ */
48
+ export function columnsFor(keys, { vsLabel = "vs baseline", narrow = false, outlineWidth } = {}) {
49
+ const want = (Array.isArray(keys) && keys.length ? keys : DEFAULT_COLUMNS).filter((k) => COLUMNS[k]);
50
+ const list = want.includes("title") ? want : ["outline", "title", ...want.filter((k) => k !== "outline")];
51
+ const out = (narrow ? list.filter((k) => k === "outline" || k === "title") : list).map((key) => ({ key, ...COLUMNS[key], ...(key === "vs" ? { label: vsLabel } : {}), ...(key === "outline" && outlineWidth ? { w: outlineWidth } : {}) }));
52
+ return out;
53
+ }
54
+
55
+ /** The width the fixed columns take, so the sheet knows what is left for the title. */
56
+ export const fixedWidth = (cols) => cols.reduce((n, c) => n + (c.w ?? 0), 0);
57
+
58
+ /**
59
+ * The finish against the target: { state: "late" | "early" | "on" | null,
60
+ * n (working days), text }. Null with no finish. "Finish Nov 3 · 7 wd late".
61
+ */
62
+ export function gapOf(finish, target) {
63
+ if (!finish) return { state: null, n: 0, text: "" };
64
+ const head = `Finish ${monthDay(finish)}`;
65
+ if (!target) return { state: null, n: 0, text: head };
66
+ const a = dayOf(finish);
67
+ const b = dayOf(target);
68
+ if (a > b) {
69
+ const n = workdaysBetween(target, finish);
70
+ return { state: "late", n, text: `${head} · ${n} wd late` };
71
+ }
72
+ if (a < b) {
73
+ const n = workdaysBetween(finish, target);
74
+ return { state: "early", n, text: `${head} · ${n} wd to spare` };
75
+ }
76
+ return { state: "on", n: 0, text: `${head} · on the target` };
77
+ }
78
+
79
+ /**
80
+ * A row against its baseline: days later (+) or earlier (-) at the finish,
81
+ * { text, tone: "late" | "early" | "same" | "new" | null }. `base` is
82
+ * { start, due } or undefined (the task is new since); a summary with no
83
+ * baseline row says nothing.
84
+ */
85
+ export function baselineDelta(row, base) {
86
+ if (!row?.dated || row.summary) return { text: row?.summary ? "" : "", tone: null };
87
+ if (!base) return { text: "new", tone: "new" };
88
+ const a = dayOf(row.due);
89
+ const b = dayOf(base.due);
90
+ if (a == null || b == null) return { text: "", tone: null };
91
+ if (a === b) return { text: "0", tone: "same" };
92
+ const n = a > b ? workdaysBetween(base.due, row.due) : -workdaysBetween(row.due, base.due);
93
+ return { text: `${n > 0 ? "+" : n < 0 ? "-" : ""}${Math.abs(n)} wd`, tone: n > 0 ? "late" : n < 0 ? "early" : "same" };
94
+ }
95
+
96
+ /** A row's length words: "5 wd", "3 wd?" for a guess, "" for a phase or milestone, null when undated. */
97
+ export function lengthWords(row, guessed = false) {
98
+ if (!row || row.summary || row.milestone) return "";
99
+ if (row.duration == null) return null;
100
+ return `${row.duration} wd${guessed ? "?" : ""}`;
101
+ }
102
+
103
+ /** The slack words: "0 wd" on a critical row, "" for finished work and phases. */
104
+ export function slackWords(row) {
105
+ if (!row || row.summary || row.pinned || row.slack == null) return "";
106
+ return `${row.slack} wd`;
107
+ }
108
+
109
+ /** What a task is called to a screen reader. */
110
+ export function barLabel(task, row) {
111
+ if (!task || !row) return "";
112
+ const when = row.start ? `${dayWords(row.start)}${row.due && row.due !== row.start ? ` to ${dayWords(row.due)}` : ""}` : "no dates";
113
+ const len = row.milestone || row.summary || row.duration == null ? "" : `, ${row.duration} working ${row.duration === 1 ? "day" : "days"}`;
114
+ const state = row.pinned ? ", done" : row.critical ? ", on the critical path" : row.slack > 0 ? `, ${row.slack} days of slack` : "";
115
+ return `${task.title}: ${when}${len}${state}`;
116
+ }
117
+
118
+ /**
119
+ * What a drag costs, for the note by the bar and the page's top bar.
120
+ * `before` / `after` are plans (engine `schedule` results), `changes` the
121
+ * engine's shifted dates, `id` the dragged row.
122
+ * → { id, cost (working days the finish moves), followers, startShift,
123
+ * lengthShift, slack, critical, duration, oldDuration, start, due,
124
+ * finishBefore, finishAfter, finishTitle, clamped }
125
+ */
126
+ export function describeDrag({ before, after, changes, clamped = [], id, titleOf = () => "" }) {
127
+ const b = before.rows.get(id);
128
+ const a = after.rows.get(id);
129
+ const cost = before.finish && after.finish ? workdaysBetween(before.finish, after.finish) : 0;
130
+ const followers = (changes ?? []).filter((c) => String(c.id) !== id && !c.summary).length;
131
+ const startShift = b?.start && a?.planStart ? workdaysBetween(b.start, a.planStart) : 0;
132
+ const lengthShift = b?.duration != null && a?.duration != null ? a.duration - b.duration : 0;
133
+ // The row the finish waits on: a milestone that ends on it, else the first task that does.
134
+ let finishTitle = "";
135
+ if (after.finish) {
136
+ let hit = null;
137
+ for (const r of after.rows.values()) {
138
+ if (r.summary || !r.dated || r.planDue !== after.finish) continue;
139
+ if (!hit || (r.milestone && !hit.milestone)) hit = r;
140
+ }
141
+ finishTitle = hit ? titleOf(hit.id) : "";
142
+ }
143
+ return {
144
+ id,
145
+ cost,
146
+ followers,
147
+ startShift,
148
+ lengthShift,
149
+ slack: b?.slack ?? null,
150
+ critical: Boolean(b?.critical),
151
+ duration: a?.duration,
152
+ oldDuration: b?.duration,
153
+ start: a?.planStart,
154
+ due: a?.planDue,
155
+ finishBefore: before.finish,
156
+ finishAfter: after.finish,
157
+ finishTitle,
158
+ clamped,
159
+ };
160
+ }
161
+
162
+ /** The lines of the note by a moving bar, in the canvas's words. */
163
+ export function dragLines(info, task, { nextTitle = null } = {}) {
164
+ const shift = info.lengthShift || info.startShift;
165
+ const signed = shift ? `${shift > 0 ? "+" : "-"}${Math.abs(shift)}` : "";
166
+ const first = info.lengthShift
167
+ ? `Finish ${dayWords(info.due)} · ${info.duration} wd, was ${info.oldDuration}`
168
+ : `${dayWords(info.start)}${info.due !== info.start ? ` to ${dayWords(info.due)}` : ""}${shift ? ` · moved ${signed} wd` : ""}`;
169
+ const second = info.followers ? `Moves ${info.followers} ${info.followers === 1 ? "task" : "tasks"} with it` : "Nothing else moves";
170
+ const left = info.slack != null ? Math.max(0, info.slack - Math.max(0, info.startShift + info.lengthShift)) : null;
171
+ const slackLine = !info.followers && left != null ? `${left} wd of slack left${nextTitle ? ` before ${nextTitle} needs it` : ""}` : null;
172
+ const third =
173
+ info.cost > 0
174
+ ? { text: `${info.finishTitle ? `${info.finishTitle} ` : "Finish "}${dayWords(info.finishAfter)} · +${info.cost} wd`, tone: "late" }
175
+ : info.cost < 0
176
+ ? { text: `${info.finishTitle ? `${info.finishTitle} ` : "Finish "}${dayWords(info.finishAfter)} · ${info.cost} wd`, tone: "early" }
177
+ : { text: "The finish holds", tone: null };
178
+ return { title: task?.title ?? "", first, second, slack: slackLine, third, last: "Let go to save · Esc puts it back" };
179
+ }
180
+
181
+ /** The note by a link being pulled: what it would say, and what it costs. */
182
+ export function linkLines({ task, predecessor, kind, info, problem }) {
183
+ if (problem) return { text: problem, tone: "problem" };
184
+ const k = linkKind(kind);
185
+ const clause = { FS: "finish to start", SS: "start to start", FF: "finish to finish", SF: "start to finish" }[k];
186
+ const head = `Let go to link: ${task?.title ?? "it"} waits on ${predecessor?.title ?? "it"}, ${clause}`;
187
+ const cost = info?.cost ?? 0;
188
+ const tail = cost > 0 ? `Finish moves ${cost} wd later` : info?.followers ? `${info.followers} ${info.followers === 1 ? "task moves" : "tasks move"}; the finish holds` : `Finish unchanged${predecessor && info?.slack != null ? `: ${predecessor.title} has ${info.slack} wd of slack` : ""}`;
189
+ return { text: head, tail, tone: cost > 0 ? "late" : null };
190
+ }
191
+
192
+ /**
193
+ * The moves for a drag of one bar or of every selected bar by `delta`
194
+ * calendar days of the track (`movesOf(id)` makes one bar's move). A row
195
+ * that is finished, undated or a summary of a selected child is left out.
196
+ */
197
+ export function selectionMoves(ids, movesOf) {
198
+ const out = [];
199
+ const seen = new Set();
200
+ for (const id of ids) {
201
+ for (const m of movesOf(id)) {
202
+ if (seen.has(m.id)) continue;
203
+ seen.add(m.id);
204
+ out.push(m);
205
+ }
206
+ }
207
+ return out;
208
+ }
209
+
210
+ /** "Not placed: waits on 5, which waits on 4" for a row a loop holds. */
211
+ export function loopWords(row, plan, outlineOf) {
212
+ if (!row?.stuck) return "";
213
+ const waits = [];
214
+ for (const l of plan.links.values()) if (l.taskId === row.id && l.valid) waits.push(l);
215
+ const first = waits[0];
216
+ if (!first) return "Not placed: a loop";
217
+ const out = outlineOf(first.dependsOnId);
218
+ return out ? `Not placed: waits on ${out}, which is in a loop` : "Not placed: a loop";
219
+ }