makersclaw 0.1.0 → 0.3.0

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 (478) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -1
  3. package/THIRD-PARTY-NOTICES.md +180 -0
  4. package/package.json +15 -8
  5. package/r/annotate.json +62 -0
  6. package/r/approval-request.json +52 -0
  7. package/r/audio-player.json +74 -0
  8. package/r/auth-form.json +55 -0
  9. package/r/board.json +55 -0
  10. package/r/calendar-view.json +105 -0
  11. package/r/cart.json +62 -0
  12. package/r/chart.json +83 -0
  13. package/r/chat.json +95 -0
  14. package/r/code-editor.json +94 -0
  15. package/r/comment-box.json +64 -0
  16. package/r/contact-section.json +53 -0
  17. package/r/core.json +341 -0
  18. package/r/csv-import.json +63 -0
  19. package/r/data-table.json +69 -0
  20. package/r/diagram.json +74 -0
  21. package/r/doc-editor.json +82 -0
  22. package/r/doc-page.json +61 -0
  23. package/r/email-render.json +73 -0
  24. package/r/faq.json +50 -0
  25. package/r/file-upload.json +54 -0
  26. package/r/flow-canvas.json +93 -0
  27. package/r/footer.json +52 -0
  28. package/r/gantt.json +70 -0
  29. package/r/job-panel.json +56 -0
  30. package/r/json-editor.json +66 -0
  31. package/r/map.json +89 -0
  32. package/r/menubar.json +52 -0
  33. package/r/mind-map.json +67 -0
  34. package/r/navigation-menu.json +52 -0
  35. package/r/order-detail.json +54 -0
  36. package/r/org-chart.json +66 -0
  37. package/r/page-builder.json +105 -0
  38. package/r/payment-methods.json +51 -0
  39. package/r/pdf-document.json +79 -0
  40. package/r/pdf-viewer.json +88 -0
  41. package/r/product-detail.json +76 -0
  42. package/r/product-grid.json +65 -0
  43. package/r/record-form.json +67 -0
  44. package/r/record-notes.json +55 -0
  45. package/r/registry.json +3612 -0
  46. package/r/search-dialog.json +51 -0
  47. package/r/settings-list.json +66 -0
  48. package/r/setup-checklist.json +51 -0
  49. package/r/share-dialog.json +52 -0
  50. package/r/sidebar.json +69 -0
  51. package/r/signature-pad.json +72 -0
  52. package/r/sketch-canvas.json +99 -0
  53. package/r/spreadsheet.json +90 -0
  54. package/r/stat-cards.json +66 -0
  55. package/r/task-list.json +63 -0
  56. package/r/task-model.json +98 -0
  57. package/r/testimonials.json +52 -0
  58. package/r/transaction-list.json +53 -0
  59. package/r/whiteboard.json +66 -0
  60. package/registry/blocks/annotate/README.md +179 -0
  61. package/registry/blocks/annotate/annotate-data.js +250 -0
  62. package/registry/blocks/annotate/annotate.jsx +646 -0
  63. package/registry/blocks/annotate/block.json +10 -0
  64. package/registry/blocks/annotate/demo.jsx +135 -0
  65. package/registry/blocks/annotate/index.js +15 -0
  66. package/registry/blocks/approval-request/README.md +116 -0
  67. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  68. package/registry/blocks/approval-request/block.json +10 -0
  69. package/registry/blocks/approval-request/demo.jsx +127 -0
  70. package/registry/blocks/approval-request/index.js +4 -0
  71. package/registry/blocks/audio-player/README.md +167 -0
  72. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  73. package/registry/blocks/audio-player/block.json +14 -0
  74. package/registry/blocks/audio-player/colors.js +109 -0
  75. package/registry/blocks/audio-player/demo.jsx +209 -0
  76. package/registry/blocks/audio-player/index.js +6 -0
  77. package/registry/blocks/audio-player/time.js +67 -0
  78. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  79. package/registry/blocks/auth-form/README.md +126 -0
  80. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  81. package/registry/blocks/auth-form/block.json +10 -0
  82. package/registry/blocks/auth-form/demo.jsx +131 -0
  83. package/registry/blocks/auth-form/index.js +3 -0
  84. package/registry/blocks/board/README.md +64 -13
  85. package/registry/blocks/board/block.json +2 -2
  86. package/registry/blocks/board/board.jsx +237 -94
  87. package/registry/blocks/board/demo.jsx +103 -24
  88. package/registry/blocks/calendar-view/README.md +180 -0
  89. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  90. package/registry/blocks/calendar-view/block.json +76 -0
  91. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  92. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  93. package/registry/blocks/calendar-view/demo.jsx +195 -0
  94. package/registry/blocks/calendar-view/draft.jsx +49 -0
  95. package/registry/blocks/calendar-view/index.js +39 -0
  96. package/registry/blocks/calendar-view/month.jsx +346 -0
  97. package/registry/blocks/calendar-view/paint.js +69 -0
  98. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  99. package/registry/blocks/calendar-view/tray.jsx +87 -0
  100. package/registry/blocks/cart/README.md +146 -0
  101. package/registry/blocks/cart/block.json +10 -0
  102. package/registry/blocks/cart/cart.jsx +597 -0
  103. package/registry/blocks/cart/demo.jsx +98 -0
  104. package/registry/blocks/cart/index.js +4 -0
  105. package/registry/blocks/cart/money.js +28 -0
  106. package/registry/blocks/chart/README.md +316 -0
  107. package/registry/blocks/chart/block.json +10 -0
  108. package/registry/blocks/chart/cartesian.jsx +642 -0
  109. package/registry/blocks/chart/core.jsx +262 -0
  110. package/registry/blocks/chart/demo.jsx +357 -0
  111. package/registry/blocks/chart/heatmap.jsx +336 -0
  112. package/registry/blocks/chart/index.js +8 -0
  113. package/registry/blocks/chart/pie.jsx +245 -0
  114. package/registry/blocks/chart/sparkline.jsx +88 -0
  115. package/registry/blocks/chat/README.md +273 -0
  116. package/registry/blocks/chat/attachment.jsx +95 -0
  117. package/registry/blocks/chat/block.json +10 -0
  118. package/registry/blocks/chat/chat.jsx +132 -0
  119. package/registry/blocks/chat/composer.jsx +364 -0
  120. package/registry/blocks/chat/demo.jsx +578 -0
  121. package/registry/blocks/chat/header.jsx +34 -0
  122. package/registry/blocks/chat/index.js +9 -0
  123. package/registry/blocks/chat/message.jsx +450 -0
  124. package/registry/blocks/chat/scroller.jsx +247 -0
  125. package/registry/blocks/chat/text.jsx +104 -0
  126. package/registry/blocks/code-editor/README.md +210 -0
  127. package/registry/blocks/code-editor/block.json +22 -0
  128. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  129. package/registry/blocks/code-editor/codemirror.js +38 -0
  130. package/registry/blocks/code-editor/demo.jsx +205 -0
  131. package/registry/blocks/code-editor/index.js +8 -0
  132. package/registry/blocks/code-editor/json.js +317 -0
  133. package/registry/blocks/code-editor/sql.js +136 -0
  134. package/registry/blocks/code-editor/text.js +101 -0
  135. package/registry/blocks/code-editor/theme.js +186 -0
  136. package/registry/blocks/comment-box/README.md +123 -0
  137. package/registry/blocks/comment-box/block.json +10 -0
  138. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  139. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  140. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  141. package/registry/blocks/comment-box/demo.jsx +141 -0
  142. package/registry/blocks/comment-box/index.js +8 -0
  143. package/registry/blocks/contact-section/README.md +152 -0
  144. package/registry/blocks/contact-section/block.json +11 -0
  145. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  146. package/registry/blocks/contact-section/demo.jsx +93 -0
  147. package/registry/blocks/contact-section/index.js +4 -0
  148. package/registry/blocks/csv-import/README.md +133 -0
  149. package/registry/blocks/csv-import/block.json +13 -0
  150. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  151. package/registry/blocks/csv-import/demo.jsx +106 -0
  152. package/registry/blocks/csv-import/import.js +200 -0
  153. package/registry/blocks/csv-import/index.js +7 -0
  154. package/registry/blocks/data-table/README.md +386 -0
  155. package/registry/blocks/data-table/block.json +10 -0
  156. package/registry/blocks/data-table/data-table.jsx +1164 -0
  157. package/registry/blocks/data-table/demo.jsx +588 -0
  158. package/registry/blocks/data-table/index.js +5 -0
  159. package/registry/blocks/data-table/model.js +169 -0
  160. package/registry/blocks/diagram/README.md +108 -0
  161. package/registry/blocks/diagram/block.json +13 -0
  162. package/registry/blocks/diagram/demo.jsx +113 -0
  163. package/registry/blocks/diagram/diagram.jsx +481 -0
  164. package/registry/blocks/diagram/index.js +7 -0
  165. package/registry/blocks/diagram/mermaid.js +52 -0
  166. package/registry/blocks/diagram/palette.js +313 -0
  167. package/registry/blocks/diagram/source.js +98 -0
  168. package/registry/blocks/doc-editor/README.md +215 -0
  169. package/registry/blocks/doc-editor/block.json +15 -0
  170. package/registry/blocks/doc-editor/demo.jsx +225 -0
  171. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  172. package/registry/blocks/doc-editor/doc.js +309 -0
  173. package/registry/blocks/doc-editor/index.js +7 -0
  174. package/registry/blocks/doc-editor/schema.jsx +56 -0
  175. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  176. package/registry/blocks/doc-editor/theme.js +82 -0
  177. package/registry/blocks/doc-page/README.md +119 -0
  178. package/registry/blocks/doc-page/autosave.js +104 -0
  179. package/registry/blocks/doc-page/block.json +10 -0
  180. package/registry/blocks/doc-page/demo.jsx +137 -0
  181. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  182. package/registry/blocks/doc-page/index.js +4 -0
  183. package/registry/blocks/email-render/README.md +151 -0
  184. package/registry/blocks/email-render/block.json +14 -0
  185. package/registry/blocks/email-render/demo.jsx +153 -0
  186. package/registry/blocks/email-render/doc-email.jsx +210 -0
  187. package/registry/blocks/email-render/email.jsx +221 -0
  188. package/registry/blocks/email-render/index.js +10 -0
  189. package/registry/blocks/email-render/render.js +50 -0
  190. package/registry/blocks/email-render/theme.js +215 -0
  191. package/registry/blocks/faq/README.md +101 -0
  192. package/registry/blocks/faq/block.json +11 -0
  193. package/registry/blocks/faq/demo.jsx +89 -0
  194. package/registry/blocks/faq/faq.jsx +220 -0
  195. package/registry/blocks/faq/index.js +4 -0
  196. package/registry/blocks/file-upload/README.md +138 -0
  197. package/registry/blocks/file-upload/block.json +10 -0
  198. package/registry/blocks/file-upload/demo.jsx +204 -0
  199. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  200. package/registry/blocks/file-upload/index.js +4 -0
  201. package/registry/blocks/flow-canvas/README.md +420 -0
  202. package/registry/blocks/flow-canvas/block.json +13 -0
  203. package/registry/blocks/flow-canvas/board.js +819 -0
  204. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  205. package/registry/blocks/flow-canvas/context.jsx +35 -0
  206. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  207. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  208. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  209. package/registry/blocks/flow-canvas/index.js +41 -0
  210. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  211. package/registry/blocks/flow-canvas/theme.js +174 -0
  212. package/registry/blocks/footer/README.md +133 -0
  213. package/registry/blocks/footer/block.json +11 -0
  214. package/registry/blocks/footer/demo.jsx +119 -0
  215. package/registry/blocks/footer/footer.jsx +406 -0
  216. package/registry/blocks/footer/index.js +4 -0
  217. package/registry/blocks/gantt/README.md +220 -0
  218. package/registry/blocks/gantt/block.json +10 -0
  219. package/registry/blocks/gantt/demo.jsx +148 -0
  220. package/registry/blocks/gantt/gantt.jsx +923 -0
  221. package/registry/blocks/gantt/index.js +7 -0
  222. package/registry/blocks/gantt/rows.jsx +468 -0
  223. package/registry/blocks/gantt/schedule.js +278 -0
  224. package/registry/blocks/job-panel/README.md +86 -2
  225. package/registry/blocks/job-panel/block.json +3 -3
  226. package/registry/blocks/job-panel/demo.jsx +230 -3
  227. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  228. package/registry/blocks/json-editor/README.md +133 -0
  229. package/registry/blocks/json-editor/block.json +10 -0
  230. package/registry/blocks/json-editor/demo.jsx +92 -0
  231. package/registry/blocks/json-editor/index.js +7 -0
  232. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  233. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  234. package/registry/blocks/json-editor/tree.js +225 -0
  235. package/registry/blocks/map/README.md +221 -0
  236. package/registry/blocks/map/block.json +14 -0
  237. package/registry/blocks/map/demo.jsx +201 -0
  238. package/registry/blocks/map/geo.js +198 -0
  239. package/registry/blocks/map/index.js +8 -0
  240. package/registry/blocks/map/list.jsx +128 -0
  241. package/registry/blocks/map/map-view.jsx +715 -0
  242. package/registry/blocks/map/maplibre.js +30 -0
  243. package/registry/blocks/map/marks.jsx +146 -0
  244. package/registry/blocks/map/theme.js +142 -0
  245. package/registry/blocks/menubar/README.md +109 -0
  246. package/registry/blocks/menubar/block.json +10 -0
  247. package/registry/blocks/menubar/demo.jsx +128 -0
  248. package/registry/blocks/menubar/index.js +4 -0
  249. package/registry/blocks/menubar/menubar.jsx +199 -0
  250. package/registry/blocks/mind-map/README.md +206 -0
  251. package/registry/blocks/mind-map/block.json +10 -0
  252. package/registry/blocks/mind-map/demo.jsx +103 -0
  253. package/registry/blocks/mind-map/index.js +31 -0
  254. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  255. package/registry/blocks/mind-map/topic.jsx +143 -0
  256. package/registry/blocks/mind-map/tree.js +645 -0
  257. package/registry/blocks/navigation-menu/README.md +124 -0
  258. package/registry/blocks/navigation-menu/block.json +10 -0
  259. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  260. package/registry/blocks/navigation-menu/index.js +4 -0
  261. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  262. package/registry/blocks/order-detail/README.md +109 -0
  263. package/registry/blocks/order-detail/block.json +10 -0
  264. package/registry/blocks/order-detail/demo.jsx +88 -0
  265. package/registry/blocks/order-detail/index.js +4 -0
  266. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  267. package/registry/blocks/org-chart/README.md +145 -0
  268. package/registry/blocks/org-chart/block.json +10 -0
  269. package/registry/blocks/org-chart/demo.jsx +94 -0
  270. package/registry/blocks/org-chart/index.js +7 -0
  271. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  272. package/registry/blocks/org-chart/org.js +245 -0
  273. package/registry/blocks/org-chart/person.jsx +96 -0
  274. package/registry/blocks/page-builder/README.md +257 -0
  275. package/registry/blocks/page-builder/block.json +14 -0
  276. package/registry/blocks/page-builder/demo.jsx +145 -0
  277. package/registry/blocks/page-builder/grapes.js +18 -0
  278. package/registry/blocks/page-builder/index.js +11 -0
  279. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  280. package/registry/blocks/page-builder/page-view.jsx +33 -0
  281. package/registry/blocks/page-builder/page.js +118 -0
  282. package/registry/blocks/page-builder/panels.jsx +588 -0
  283. package/registry/blocks/page-builder/sections.js +209 -0
  284. package/registry/blocks/page-builder/theme.js +87 -0
  285. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  286. package/registry/blocks/page-builder/tokens.js +329 -0
  287. package/registry/blocks/payment-methods/README.md +104 -0
  288. package/registry/blocks/payment-methods/block.json +10 -0
  289. package/registry/blocks/payment-methods/demo.jsx +71 -0
  290. package/registry/blocks/payment-methods/index.js +4 -0
  291. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  292. package/registry/blocks/pdf-document/README.md +213 -0
  293. package/registry/blocks/pdf-document/block.json +13 -0
  294. package/registry/blocks/pdf-document/demo.jsx +136 -0
  295. package/registry/blocks/pdf-document/index.js +33 -0
  296. package/registry/blocks/pdf-document/money.js +83 -0
  297. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  298. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  299. package/registry/blocks/pdf-document/quote.jsx +179 -0
  300. package/registry/blocks/pdf-document/theme.js +193 -0
  301. package/registry/blocks/pdf-viewer/README.md +191 -0
  302. package/registry/blocks/pdf-viewer/block.json +14 -0
  303. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  304. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  305. package/registry/blocks/pdf-viewer/index.js +8 -0
  306. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  307. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  308. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  309. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  310. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  311. package/registry/blocks/product-detail/README.md +217 -0
  312. package/registry/blocks/product-detail/block.json +10 -0
  313. package/registry/blocks/product-detail/demo.jsx +233 -0
  314. package/registry/blocks/product-detail/index.js +7 -0
  315. package/registry/blocks/product-detail/price.jsx +115 -0
  316. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  317. package/registry/blocks/product-detail/product-media.jsx +102 -0
  318. package/registry/blocks/product-detail/product-options.jsx +144 -0
  319. package/registry/blocks/product-grid/README.md +162 -0
  320. package/registry/blocks/product-grid/block.json +10 -0
  321. package/registry/blocks/product-grid/demo.jsx +255 -0
  322. package/registry/blocks/product-grid/index.js +5 -0
  323. package/registry/blocks/product-grid/product-card.jsx +232 -0
  324. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  325. package/registry/blocks/record-form/README.md +196 -0
  326. package/registry/blocks/record-form/block.json +10 -0
  327. package/registry/blocks/record-form/demo.jsx +525 -0
  328. package/registry/blocks/record-form/index.js +4 -0
  329. package/registry/blocks/record-form/record-fields.jsx +457 -0
  330. package/registry/blocks/record-form/record-form.jsx +415 -0
  331. package/registry/blocks/record-form/rules.js +81 -0
  332. package/registry/blocks/record-notes/README.md +139 -0
  333. package/registry/blocks/record-notes/block.json +10 -0
  334. package/registry/blocks/record-notes/demo.jsx +179 -0
  335. package/registry/blocks/record-notes/index.js +4 -0
  336. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  337. package/registry/blocks/search-dialog/README.md +108 -0
  338. package/registry/blocks/search-dialog/block.json +10 -0
  339. package/registry/blocks/search-dialog/demo.jsx +116 -0
  340. package/registry/blocks/search-dialog/index.js +3 -0
  341. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  342. package/registry/blocks/settings-list/README.md +171 -0
  343. package/registry/blocks/settings-list/block.json +10 -0
  344. package/registry/blocks/settings-list/demo.jsx +333 -0
  345. package/registry/blocks/settings-list/index.js +4 -0
  346. package/registry/blocks/settings-list/row-state.jsx +93 -0
  347. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  348. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  349. package/registry/blocks/setup-checklist/README.md +142 -0
  350. package/registry/blocks/setup-checklist/block.json +10 -0
  351. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  352. package/registry/blocks/setup-checklist/index.js +4 -0
  353. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  354. package/registry/blocks/share-dialog/README.md +113 -0
  355. package/registry/blocks/share-dialog/block.json +10 -0
  356. package/registry/blocks/share-dialog/demo.jsx +140 -0
  357. package/registry/blocks/share-dialog/index.js +3 -0
  358. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  359. package/registry/blocks/sidebar/README.md +190 -0
  360. package/registry/blocks/sidebar/block.json +43 -0
  361. package/registry/blocks/sidebar/demo.jsx +577 -0
  362. package/registry/blocks/sidebar/index.js +4 -0
  363. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  364. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  365. package/registry/blocks/signature-pad/README.md +137 -0
  366. package/registry/blocks/signature-pad/block.json +13 -0
  367. package/registry/blocks/signature-pad/colors.js +115 -0
  368. package/registry/blocks/signature-pad/demo.jsx +94 -0
  369. package/registry/blocks/signature-pad/index.js +6 -0
  370. package/registry/blocks/signature-pad/pad.js +7 -0
  371. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  372. package/registry/blocks/signature-pad/signature.js +68 -0
  373. package/registry/blocks/sketch-canvas/README.md +280 -0
  374. package/registry/blocks/sketch-canvas/block.json +13 -0
  375. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  376. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  377. package/registry/blocks/sketch-canvas/index.js +9 -0
  378. package/registry/blocks/sketch-canvas/palette.js +226 -0
  379. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  380. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  381. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  382. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  383. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  384. package/registry/blocks/sketch-canvas/theme.js +131 -0
  385. package/registry/blocks/spreadsheet/README.md +307 -0
  386. package/registry/blocks/spreadsheet/block.json +13 -0
  387. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  388. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  389. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  390. package/registry/blocks/spreadsheet/grid.js +387 -0
  391. package/registry/blocks/spreadsheet/index.js +34 -0
  392. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  393. package/registry/blocks/spreadsheet/types.js +473 -0
  394. package/registry/blocks/stat-cards/README.md +173 -0
  395. package/registry/blocks/stat-cards/block.json +10 -0
  396. package/registry/blocks/stat-cards/demo.jsx +257 -0
  397. package/registry/blocks/stat-cards/index.js +4 -0
  398. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  399. package/registry/blocks/stat-cards/usage.jsx +243 -0
  400. package/registry/blocks/task-list/README.md +176 -0
  401. package/registry/blocks/task-list/block.json +10 -0
  402. package/registry/blocks/task-list/demo.jsx +134 -0
  403. package/registry/blocks/task-list/index.js +5 -0
  404. package/registry/blocks/task-list/task-list.jsx +907 -0
  405. package/registry/blocks/task-model/README.md +455 -0
  406. package/registry/blocks/task-model/block.json +167 -0
  407. package/registry/blocks/task-model/changes.js +89 -0
  408. package/registry/blocks/task-model/dates.js +371 -0
  409. package/registry/blocks/task-model/demo.jsx +215 -0
  410. package/registry/blocks/task-model/dnd.jsx +240 -0
  411. package/registry/blocks/task-model/index.js +97 -0
  412. package/registry/blocks/task-model/model.js +919 -0
  413. package/registry/blocks/task-model/parts.jsx +449 -0
  414. package/registry/blocks/task-model/toolbar.jsx +271 -0
  415. package/registry/blocks/testimonials/README.md +139 -0
  416. package/registry/blocks/testimonials/block.json +11 -0
  417. package/registry/blocks/testimonials/demo.jsx +137 -0
  418. package/registry/blocks/testimonials/index.js +4 -0
  419. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  420. package/registry/blocks/transaction-list/README.md +126 -0
  421. package/registry/blocks/transaction-list/block.json +10 -0
  422. package/registry/blocks/transaction-list/demo.jsx +79 -0
  423. package/registry/blocks/transaction-list/index.js +4 -0
  424. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  425. package/registry/blocks/whiteboard/README.md +179 -0
  426. package/registry/blocks/whiteboard/block.json +10 -0
  427. package/registry/blocks/whiteboard/demo.jsx +169 -0
  428. package/registry/blocks/whiteboard/index.js +6 -0
  429. package/registry/blocks/whiteboard/templates.js +150 -0
  430. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  431. package/src/install.mjs +18 -0
  432. package/src/shadcn.mjs +171 -0
  433. package/templates/next/files/README.md +145 -11
  434. package/templates/next/files/app/globals.css +55 -4
  435. package/templates/next/files/check/run.mjs +3 -3
  436. package/templates/next/files/components/parts/fixture.jsx +1 -1
  437. package/templates/next/files/components/parts/sample.js +15 -0
  438. package/templates/next/files/components/ui/avatar.jsx +141 -0
  439. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  440. package/templates/next/files/components/ui/button-group.jsx +70 -0
  441. package/templates/next/files/components/ui/button.jsx +132 -12
  442. package/templates/next/files/components/ui/calendar.jsx +609 -0
  443. package/templates/next/files/components/ui/carousel.jsx +281 -0
  444. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  445. package/templates/next/files/components/ui/combobox.jsx +608 -0
  446. package/templates/next/files/components/ui/command.jsx +577 -0
  447. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  448. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  449. package/templates/next/files/components/ui/distribution.jsx +117 -0
  450. package/templates/next/files/components/ui/feedback.jsx +143 -0
  451. package/templates/next/files/components/ui/field.jsx +115 -3
  452. package/templates/next/files/components/ui/file-input.jsx +234 -0
  453. package/templates/next/files/components/ui/icon.jsx +130 -8
  454. package/templates/next/files/components/ui/image.jsx +143 -0
  455. package/templates/next/files/components/ui/index.js +47 -2
  456. package/templates/next/files/components/ui/input-group.jsx +213 -0
  457. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  458. package/templates/next/files/components/ui/item.jsx +206 -0
  459. package/templates/next/files/components/ui/menu.jsx +454 -82
  460. package/templates/next/files/components/ui/notice.jsx +126 -14
  461. package/templates/next/files/components/ui/pagination.jsx +156 -0
  462. package/templates/next/files/components/ui/popover.jsx +284 -0
  463. package/templates/next/files/components/ui/radio.jsx +193 -0
  464. package/templates/next/files/components/ui/rating.jsx +131 -0
  465. package/templates/next/files/components/ui/resizable.jsx +338 -0
  466. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  467. package/templates/next/files/components/ui/separator.jsx +119 -0
  468. package/templates/next/files/components/ui/sheet.jsx +96 -11
  469. package/templates/next/files/components/ui/slider.jsx +174 -0
  470. package/templates/next/files/components/ui/stat.jsx +574 -0
  471. package/templates/next/files/components/ui/steps.jsx +338 -0
  472. package/templates/next/files/components/ui/swatch.jsx +33 -0
  473. package/templates/next/files/components/ui/table.jsx +130 -0
  474. package/templates/next/files/components/ui/toast.jsx +440 -0
  475. package/templates/next/files/components/ui/toggle.jsx +195 -0
  476. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  477. package/templates/next/files/lib/sample.js +4 -12
  478. package/templates/next/template.json +264 -8
@@ -0,0 +1,278 @@
1
+ // The gantt's arithmetic — pure, no React, no pixels read from the DOM.
2
+ // The zoom levels, the window a timeline covers, its two header tiers,
3
+ // where a day sits in pixels, what a drag or a resize saves (and which
4
+ // waiting tasks it pushes along), and the elbow a dependency arrow takes.
5
+ // The dates are task-model's: wall-calendar strings, day numbers for math.
6
+
7
+ import {
8
+ addDays,
9
+ descendantIds,
10
+ diffDays,
11
+ endOfMonth,
12
+ formatDate,
13
+ isWeekend,
14
+ shiftDates,
15
+ spanOf,
16
+ spanPatch,
17
+ startOfMonth,
18
+ startOfWeek,
19
+ timeScale,
20
+ } from "../task-model";
21
+
22
+ /** The zoom levels: how wide a day is, what the columns are, how much
23
+ * room the window keeps either side of the work, and its least length. */
24
+ export const ZOOMS = {
25
+ day: { key: "day", label: "Day", unit: "day", dayWidth: 36, pad: 7, min: 56, top: "month" },
26
+ week: { key: "week", label: "Week", unit: "week", dayWidth: 16, pad: 14, min: 150, top: "month" },
27
+ month: { key: "month", label: "Month", unit: "month", dayWidth: 5, pad: 45, min: 420, top: "year" },
28
+ quarter: { key: "quarter", label: "Quarter", unit: "quarter", dayWidth: 1.75, pad: 90, min: 900, top: "year" },
29
+ };
30
+
31
+ export const zoomOf = (key) => ZOOMS[key] ?? ZOOMS.week;
32
+
33
+ /** The first day of `day`'s column at `unit`. */
34
+ export function unitStart(day, unit, weekStartsOn = 1) {
35
+ if (unit === "day" || unit === "week") return startOfWeek(day, weekStartsOn);
36
+ if (unit === "month") return startOfMonth(day);
37
+ return timeScale(day, day, "quarter")[0]?.start ?? day;
38
+ }
39
+
40
+ /** The last day of `day`'s column at `unit`. */
41
+ export function unitEnd(day, unit, weekStartsOn = 1) {
42
+ if (unit === "day" || unit === "week") return addDays(startOfWeek(day, weekStartsOn), 6);
43
+ if (unit === "month") return endOfMonth(day);
44
+ return timeScale(day, day, "quarter")[0]?.end ?? day;
45
+ }
46
+
47
+ /** The window a timeline covers: every task's span and today, padded by
48
+ * the zoom, snapped to whole columns, at least the zoom's `min` days.
49
+ * → { from, to, days } */
50
+ export function ganttRange(tasks, zoomKey, today, { weekStartsOn = 1 } = {}) {
51
+ const z = zoomOf(zoomKey);
52
+ let lo = null;
53
+ let hi = null;
54
+ for (const t of tasks ?? []) {
55
+ const s = spanOf(t);
56
+ if (!s) continue;
57
+ if (lo === null || s.start < lo) lo = s.start;
58
+ if (hi === null || s.end > hi) hi = s.end;
59
+ }
60
+ if (today) {
61
+ if (lo === null || today < lo) lo = today;
62
+ if (hi === null || today > hi) hi = today;
63
+ }
64
+ if (lo === null) return { from: null, to: null, days: 0 };
65
+ let from = unitStart(addDays(lo, -z.pad), z.unit, weekStartsOn);
66
+ let to = unitEnd(addDays(hi, z.pad), z.unit, weekStartsOn);
67
+ if (diffDays(from, to) + 1 < z.min) to = unitEnd(addDays(from, z.min - 1), z.unit, weekStartsOn);
68
+ return { from, to, days: diffDays(from, to) + 1 };
69
+ }
70
+
71
+ /** A day's left edge in pixels from the window's first day. */
72
+ export function xOf(day, from, dayWidth) {
73
+ const d = diffDays(from, day);
74
+ return d === null ? null : d * dayWidth;
75
+ }
76
+
77
+ /** The two header tiers over [from, to], in pixels: `top` (months, or
78
+ * years when zoomed out) and `bottom` (the zoom's columns), each
79
+ * { key, start, end, x, w, label, weekend?, today? }. */
80
+ export function headerTiers(from, to, zoomKey, { today, weekStartsOn = 1, locale } = {}) {
81
+ const z = zoomOf(zoomKey);
82
+ const place = (start, end) => {
83
+ const a = start < from ? from : start;
84
+ const b = end > to ? to : end;
85
+ return { x: xOf(a, from, z.dayWidth), w: (diffDays(a, b) + 1) * z.dayWidth };
86
+ };
87
+ const bottom = timeScale(from, to, z.unit, { weekStartsOn, locale }).map((c) => {
88
+ let label = c.label;
89
+ if (z.unit === "month") label = formatDate(c.start, { month: "short" }, { locale });
90
+ if (z.unit === "quarter") label = c.label.split(" ")[0];
91
+ return {
92
+ key: c.key,
93
+ start: c.start,
94
+ end: c.end,
95
+ label,
96
+ weekend: z.unit === "day" && isWeekend(c.start),
97
+ today: Boolean(today) && c.start <= today && today <= c.end,
98
+ ...place(c.start, c.end),
99
+ };
100
+ });
101
+ let top;
102
+ if (z.top === "month") {
103
+ top = timeScale(from, to, "month", { locale }).map((c) => ({
104
+ key: c.key,
105
+ start: c.start,
106
+ end: c.end,
107
+ label: formatDate(c.start, { month: "long", year: "numeric" }, { locale }),
108
+ ...place(c.start, c.end),
109
+ }));
110
+ } else {
111
+ top = [];
112
+ for (let y = +from.slice(0, 4); y <= +to.slice(0, 4); y++) {
113
+ const start = `${y}-01-01`;
114
+ const end = `${y}-12-31`;
115
+ top.push({ key: String(y), start, end, label: String(y), ...place(start, end) });
116
+ }
117
+ }
118
+ return { top, bottom };
119
+ }
120
+
121
+ /** The weekend columns of the window (day and week zoom), for shading. */
122
+ export function weekendBands(from, to, zoomKey, weekend) {
123
+ const z = zoomOf(zoomKey);
124
+ if (z.unit !== "day" && z.unit !== "week") return [];
125
+ const out = [];
126
+ const n = diffDays(from, to);
127
+ for (let i = 0; i <= n; i++) {
128
+ const d = addDays(from, i);
129
+ if (!isWeekend(d, weekend)) continue;
130
+ const last = out[out.length - 1];
131
+ if (last && last.end === addDays(d, -1)) last.end = d;
132
+ else out.push({ start: d, end: d });
133
+ }
134
+ return out.map((b) => ({ ...b, x: xOf(b.start, from, z.dayWidth), w: (diffDays(b.start, b.end) + 1) * z.dayWidth }));
135
+ }
136
+
137
+ /** A milestone: a task marked `milestone: true` (or `type: "milestone"`).
138
+ * It sits on one day, its due date (else its start). */
139
+ export function isMilestone(task) {
140
+ return task?.milestone === true || task?.type === "milestone";
141
+ }
142
+
143
+ /** The span a row draws: its own, or — for a task with subtasks — the
144
+ * union of its own and every descendant's (a summary bar). */
145
+ export function summarySpan(task, tasks) {
146
+ let span = spanOf(task);
147
+ for (const id of descendantIds(tasks, task.id)) {
148
+ const s = spanOf(tasks.find((t) => t.id === id));
149
+ if (!s) continue;
150
+ span = span ? { start: s.start < span.start ? s.start : span.start, end: s.end > span.end ? s.end : span.end } : s;
151
+ }
152
+ return span;
153
+ }
154
+
155
+ /** What moving or stretching a task saves, as [{ id, patch }]:
156
+ * - kind "move": its dates shift by `days` (its subtasks with it);
157
+ * - kind "start" / "end": that edge moves by `days` (never past the other);
158
+ * - with `push` (default), every task waiting on a moved one that would
159
+ * now start on or before it ends slides later just enough, keeping its
160
+ * length — and so on down the chain. Nothing is ever pulled earlier.
161
+ * `days` 0 → []. The same answer drives the live preview and the save. */
162
+ export function planMove(tasks, id, kind, days, { push = true } = {}) {
163
+ if (!days) return [];
164
+ const byId = new Map(tasks.map((t) => [t.id, t]));
165
+ const task = byId.get(id);
166
+ const span = spanOf(task);
167
+ if (!task || (!span && kind !== "move")) return [];
168
+ const patches = new Map();
169
+ const current = (tid) => ({ ...byId.get(tid), ...patches.get(tid) });
170
+ const set = (tid, patch) => patches.set(tid, { ...patches.get(tid), ...patch });
171
+
172
+ if (kind === "move") {
173
+ if (span) set(id, shiftDates(task, days));
174
+ for (const d of descendantIds(tasks, id)) if (spanOf(byId.get(d))) set(d, shiftDates(byId.get(d), days));
175
+ } else if (kind === "start") {
176
+ const next = addDays(span.start, days);
177
+ set(id, spanPatch(task, next > span.end ? span.end : next, span.end));
178
+ } else if (kind === "end") {
179
+ const next = addDays(span.end, days);
180
+ set(id, spanPatch(task, span.start, next < span.start ? span.start : next));
181
+ } else return [];
182
+
183
+ if (push) {
184
+ const waiting = new Map();
185
+ for (const t of tasks) for (const d of t.dependsOn ?? []) (waiting.get(d) ?? waiting.set(d, []).get(d)).push(t.id);
186
+ const queue = [...patches.keys()];
187
+ let guard = 0;
188
+ while (queue.length && guard++ < 5000) {
189
+ const from = queue.shift();
190
+ const fs = spanOf(current(from));
191
+ if (!fs) continue;
192
+ for (const to of waiting.get(from) ?? []) {
193
+ const ts = spanOf(current(to));
194
+ if (!ts || ts.start > fs.end) continue;
195
+ const by = diffDays(ts.start, fs.end) + 1;
196
+ set(to, shiftDates(current(to), by));
197
+ queue.push(to);
198
+ }
199
+ }
200
+ }
201
+ return [...patches].map(([pid, patch]) => ({ id: pid, patch }));
202
+ }
203
+
204
+ /** The patch that starts a task the day after the last of its blockers
205
+ * ends, keeping its length (a date conflict's fix). null when it has no
206
+ * scheduled blockers or already starts after them. */
207
+ export function afterBlockersPatch(task, tasks) {
208
+ const span = spanOf(task);
209
+ if (!span) return null;
210
+ let last = null;
211
+ for (const d of task.dependsOn ?? []) {
212
+ const s = spanOf(tasks.find((t) => t.id === d));
213
+ if (s && (last === null || s.end > last)) last = s.end;
214
+ }
215
+ if (last === null || span.start > last) return null;
216
+ return shiftDates(task, diffDays(span.start, last) + 1);
217
+ }
218
+
219
+ /** A task's length in calendar days (1 for a one-day task), null when
220
+ * it has no dates. */
221
+ export function lengthOf(span) {
222
+ return span ? diffDays(span.start, span.end) + 1 : null;
223
+ }
224
+
225
+ /** An SVG path through `points` ([x, y] pairs) with its corners rounded
226
+ * by `r` (less where a leg is short). */
227
+ export function roundedPath(points, r = 4) {
228
+ const pts = points.filter((p, i) => i === 0 || p[0] !== points[i - 1][0] || p[1] !== points[i - 1][1]);
229
+ if (pts.length < 2) return "";
230
+ const f = (n) => Math.round(n * 10) / 10;
231
+ let d = `M${f(pts[0][0])} ${f(pts[0][1])}`;
232
+ for (let i = 1; i < pts.length - 1; i++) {
233
+ const [px, py] = pts[i - 1];
234
+ const [x, y] = pts[i];
235
+ const [nx, ny] = pts[i + 1];
236
+ const inLen = Math.hypot(x - px, y - py);
237
+ const outLen = Math.hypot(nx - x, ny - y);
238
+ const k = Math.min(r, inLen / 2, outLen / 2);
239
+ const ax = x - ((x - px) / (inLen || 1)) * k;
240
+ const ay = y - ((y - py) / (inLen || 1)) * k;
241
+ const bx = x + ((nx - x) / (outLen || 1)) * k;
242
+ const by = y + ((ny - y) / (outLen || 1)) * k;
243
+ d += ` L${f(ax)} ${f(ay)} Q${f(x)} ${f(y)} ${f(bx)} ${f(by)}`;
244
+ }
245
+ const last = pts[pts.length - 1];
246
+ return `${d} L${f(last[0])} ${f(last[1])}`;
247
+ }
248
+
249
+ /** The elbow from a finished task to the one waiting on it (finish to
250
+ * start). Boxes are what the rows draw: { x0, x1, y (centre) }. When the
251
+ * waiting task starts far enough right, the line runs out, turns and
252
+ * enters from the left; when it does not (or it starts too early — a
253
+ * conflict), it steps out, drops between the rows and comes back in.
254
+ * → { d, head } — the line, and the arrowhead's path at its end. */
255
+ export function arrowPath(a, b, { rowHeight = 36, gap = 10, radius = 4 } = {}) {
256
+ const sx = a.x1;
257
+ const sy = a.y;
258
+ const ex = b.x0;
259
+ const ey = b.y;
260
+ let points;
261
+ if (Math.abs(ey - sy) < 1) points = [[sx, sy], [ex, ey]];
262
+ else if (ex - gap >= sx + gap) points = [[sx, sy], [ex - gap, sy], [ex - gap, ey], [ex, ey]];
263
+ else {
264
+ const mid = sy + (ey > sy ? rowHeight / 2 : -rowHeight / 2);
265
+ points = [[sx, sy], [sx + gap, sy], [sx + gap, mid], [ex - gap, mid], [ex - gap, ey], [ex, ey]];
266
+ }
267
+ const f = (n) => Math.round(n * 10) / 10;
268
+ const head = `M${f(ex - 5)} ${f(ey - 3.5)} L${f(ex)} ${f(ey)} L${f(ex - 5)} ${f(ey + 3.5)} Z`;
269
+ return { d: roundedPath(points, radius), head };
270
+ }
271
+
272
+ /** Pixels → whole days at a zoom (a drag's delta, rounded to the nearest
273
+ * day; never -0). */
274
+ export function daysFromPixels(px, dayWidth) {
275
+ const n = Math.round((px || 0) / dayWidth);
276
+ return n === 0 ? 0 : n;
277
+ }
278
+
@@ -7,16 +7,26 @@ stopped. When no job runs it renders nothing — a panel that is always
7
7
  there is a monitoring console, and apps do not have one.
8
8
 
9
9
  ```jsx
10
- import { JobPanel } from "../components/blocks/job-panel"; // "./blocks/job-panel" from components/
10
+ import { JobPanel } from "../components/blocks/job-panel"; // a Makersclaw app ("./blocks/job-panel" from components/)
11
+ import { JobPanel } from "@/components/makersclaw/blocks/job-panel"; // a shadcn project
11
12
  ```
12
13
 
13
14
  A client component. It takes the object `useJob()` returns (lib/hooks.js,
14
15
  README §5 "Commissioning work") and draws it; starting the job stays with
15
16
  your surface.
16
17
 
18
+ `variant="generator"` is the panel inside a small studio: a prompt, your
19
+ options, Generate, the running job, and a shelf of what it made. It holds
20
+ no model, provider or API key: Generate hands the prompt to the app's
21
+ agent (`job.start`, or your `onGenerate`), the agent writes rows, and you
22
+ pass those rows back in as `results`.
23
+
17
24
  ## Props
18
25
 
19
- - `job` — what `useJob()` returns. Required.
26
+ - `job` — what `useJob()` returns. Required. Outside Makersclaw, any
27
+ object of the same shape: `running`, `steps` (`[{ name, label, status:
28
+ "running" | "done" | "failed" }]`), `text`, `error`, `finishedAt`, and
29
+ `cancel()` / `reset()`.
20
30
  - `title` — while it runs, what the agent is doing, in the founder's
21
31
  words: `"Drafting the launch plan"`. Default `"Working on it"`.
22
32
  - `doneTitle` — after a clean finish: `"Launch plan drafted"`.
@@ -32,6 +42,36 @@ your surface.
32
42
  is what the agent says it did, never the result: the result is rows.
33
43
  - `className` — layout around it. Never colour.
34
44
 
45
+ ### The generator (`variant="generator"`)
46
+
47
+ Everything above (`job`, `title`, `doneTitle`, `failedTitle`, `onRetry`,
48
+ `autoClose`, `maxSteps`, `showText`) goes to the panel inside it. Then:
49
+
50
+ - `onGenerate(prompt)` — start the job. Build the ask from the prompt and
51
+ your options and call `job.start(ask)`; return what it returns, or
52
+ `{ ok: false, error }` and the reason shows under the prompt. Default:
53
+ `job.start(prompt)`. Cmd/Ctrl+Enter in the prompt presses Generate.
54
+ Without `onRetry`, the panel's "Try again" re-runs the last prompt.
55
+ - `prompt` / `onPromptChange(text)` — control the prompt; or
56
+ `defaultPrompt`. `promptLabel` ("What should it make?"), `placeholder`,
57
+ `promptHint`, `promptRows` (4).
58
+ - `options` — your fields, in a two-column grid under the prompt (one
59
+ column on a phone): a size `Select`, a style `ToggleGroup`, a `Slider`.
60
+ Their values are yours; read them in `onGenerate`.
61
+ - `generateLabel` ("Generate") · `generateIcon` ("wand") ·
62
+ `canGenerateEmpty` (false) · `disabled` (false).
63
+ - `heading` · `description` — the form card's title and line under it.
64
+ - `aside` — a node under the form: tips, a note on cost.
65
+ - `results` — what the job made, as nodes (an array of cards, say). The
66
+ shelf draws them in `resultsColumns` columns (1–4; fewer on a phone).
67
+ `resultsTitle` ("Results") and `resultsActions` (nodes beside it).
68
+ - `placeholderResult` — drawn at the top of the shelf while the job runs
69
+ (default a skeleton); the shelf is `aria-busy` meanwhile.
70
+ - `emptyTitle` · `emptyBody` · `emptyState` — the shelf before anything
71
+ is made.
72
+ - `layout` — `"stacked"` (default: the form, then the shelf) or
73
+ `"split"` (side by side from lg up; stacked on a phone).
74
+
35
75
  ## Example
36
76
 
37
77
  ```jsx
@@ -63,6 +103,50 @@ export default function Launches({ launches, reload }) {
63
103
  The verb sits on the object list beside the manual "New" (README §5, rule
64
104
  1), and the panel sits where the result will appear.
65
105
 
106
+ A generator for product photos:
107
+
108
+ ```jsx
109
+ "use client";
110
+ import { useEffect, useState } from "react";
111
+ import { useJob } from "../lib/hooks";
112
+ import { Field, Image, Select } from "./ui";
113
+ import { JobPanel } from "./blocks/job-panel";
114
+
115
+ export default function PhotoStudio({ photos, reload }) {
116
+ const job = useJob();
117
+ const [size, setSize] = useState("square");
118
+ useEffect(() => { reload?.(); }, [job.progress]); // new photos appear as they land
119
+
120
+ return (
121
+ <JobPanel
122
+ variant="generator"
123
+ job={job}
124
+ heading="New product photo"
125
+ promptLabel="Describe the photo"
126
+ options={
127
+ <Field id="size" label="Size">
128
+ <Select id="size" value={size} onChange={(e) => setSize(e.target.value)}
129
+ options={[{ value: "square", label: "Square" }, { value: "portrait", label: "Portrait" }]} />
130
+ </Field>
131
+ }
132
+ onGenerate={(prompt) => job.start(`Make one ${size} product photo: ${prompt}. Save it to public.photos.`)}
133
+ title="Making the photo"
134
+ doneTitle="Photo saved"
135
+ results={photos.map((p) => <Image key={p.id} src={p.url} alt={p.prompt} ratio="square" rounded="lg" />)}
136
+ resultsColumns={3}
137
+ />
138
+ );
139
+ }
140
+ ```
141
+
142
+ What it will not do: call a model, hold a provider or an API key, or
143
+ keep what was made. The agent does the work through the job; the rows
144
+ are the results.
145
+
66
146
  Its files are fixed: `npm run check` refuses a change, and `makersclaw add
67
147
  job-panel` restores them. A different panel is your own component in
68
148
  `components/`, built from the kit.
149
+
150
+ ## Credits
151
+
152
+ The generator variant is ported from Creative Tim UI (https://github.com/creativetimofficial/ui, ai-image-generator-01 and ai-video-generator-01, MIT), rewritten on the Makersclaw kit without its provider and API-key fields.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "job-panel",
3
3
  "title": "JobPanel",
4
- "description": "The panel that follows work the founder asked the app's agent for (useJob): each step's label as it runs, Stop, then done or the reason it stopped — and nothing on screen when no job runs.",
5
- "useWhen": "A surface has a verb that asks the agent to make or find something (\"Generate a launch plan\", \"Find 20 leads\", \"Plan next sprint\") and the founder should watch it happen where the result will land.",
6
- "tags": ["job", "agent", "generate", "progress", "steps", "running", "working", "commission", "ai", "stop", "status"],
4
+ "description": "The panel that follows work the founder asked the app's agent for (useJob): each step's label as it runs, Stop, then done or the reason it stopped — and nothing on screen when no job runs. variant=\"generator\" wraps it in a prompt, the surface's options, Generate and a results shelf, with no model, provider or API key of its own.",
5
+ "useWhen": "A surface has a verb that asks the agent to make or find something (\"Generate a launch plan\", \"Find 20 leads\", \"Plan next sprint\") and the founder should watch it happen where the result will land. variant=\"generator\" when the screen IS the place to ask: a prompt and a few options, the results under them (product photos, ad copy, names).",
6
+ "tags": ["job", "agent", "generate", "progress", "steps", "running", "working", "commission", "ai", "stop", "status", "generator", "prompt", "results", "image", "studio"],
7
7
  "exports": ["JobPanel"],
8
8
  "files": ["index.js", "job-panel.jsx"],
9
9
  "requires": []
@@ -1,9 +1,14 @@
1
1
  "use client";
2
2
 
3
3
  // JobPanel driven by a pretend job — the gallery's and the smoke test's
4
- // surface. Not installed into apps.
4
+ // surface. Not installed into apps. Three variants behind the switcher:
5
+ // Panel the panel under a verb; one run succeeds, one fails
6
+ // Photos variant="generator", stacked: a prompt, size and style, a
7
+ // grid of results
8
+ // Copy variant="generator", split: ad headlines as text results,
9
+ // tips beside the form
5
10
  import { useEffect, useRef, useState } from "react";
6
- import { Button } from "../components/ui";
11
+ import { Badge, Button, Card, Field, Icon, IconButton, Select, ToggleGroup, Switch } from "../components/ui";
7
12
  import { JobPanel } from "../components/blocks/job-panel";
8
13
 
9
14
  const STEPS = ["Reading the product list", "Searching the web", "Drafting the plan", "Saving 6 tasks"];
@@ -57,7 +62,7 @@ function usePretendJob() {
57
62
  };
58
63
  }
59
64
 
60
- export default function JobPanelDemo() {
65
+ function PanelDemo() {
61
66
  const job = usePretendJob();
62
67
  return (
63
68
  <div className="grid max-w-xl gap-4">
@@ -73,3 +78,225 @@ export default function JobPanelDemo() {
73
78
  </div>
74
79
  );
75
80
  }
81
+
82
+ // A pretend job for the generators: the steps tick by, then `onDone` adds
83
+ // the results (the rows the agent would have written).
84
+ function useGeneratorJob() {
85
+ const [state, setState] = useState(IDLE);
86
+ const timers = useRef([]);
87
+ const clear = () => {
88
+ timers.current.forEach(clearTimeout);
89
+ timers.current = [];
90
+ };
91
+ useEffect(() => clear, []);
92
+ const later = (ms, fn) => timers.current.push(setTimeout(fn, ms));
93
+ function start(steps, { fail = false, onDone } = {}) {
94
+ clear();
95
+ setState({ ...IDLE, running: true });
96
+ steps.forEach((label, i) =>
97
+ later(650 * i + 200, () =>
98
+ setState((s) => ({
99
+ ...s,
100
+ steps: [...s.steps.map((x) => ({ ...x, status: "done" })), { name: `step_${i}`, label, status: "running" }],
101
+ })),
102
+ ),
103
+ );
104
+ later(650 * steps.length + 300, () => {
105
+ if (!fail) onDone?.();
106
+ setState((s) =>
107
+ fail
108
+ ? { ...s, running: false, steps: s.steps.map((x, i) => ({ ...x, status: i === s.steps.length - 1 ? "failed" : "done" })), error: "The image service is busy. Nothing was saved." }
109
+ : { ...s, running: false, steps: s.steps.map((x) => ({ ...x, status: "done" })), finishedAt: new Date().toISOString(), progress: s.progress + 1 },
110
+ );
111
+ });
112
+ return { ok: true };
113
+ }
114
+ return {
115
+ ...state,
116
+ start,
117
+ cancel: () => {
118
+ clear();
119
+ setState((s) => ({ ...s, running: false, finishedAt: new Date().toISOString() }));
120
+ },
121
+ reset: () => {
122
+ clear();
123
+ setState(IDLE);
124
+ },
125
+ };
126
+ }
127
+
128
+ const SIZES = [
129
+ { value: "square", label: "Square · shop grid" },
130
+ { value: "portrait", label: "Portrait · story" },
131
+ { value: "wide", label: "Wide · banner" },
132
+ ];
133
+ const RATIO_CLASS = { square: "aspect-square", portrait: "aspect-3/4", wide: "aspect-video" };
134
+
135
+ function PhotosDemo() {
136
+ const job = useGeneratorJob();
137
+ const [size, setSize] = useState("square");
138
+ const [style, setStyle] = useState("daylight");
139
+ const [fail, setFail] = useState(false);
140
+ const [photos, setPhotos] = useState([
141
+ { id: "ph1", prompt: "Stoneware bowl on a linen cloth, morning window light", size: "square", style: "daylight" },
142
+ { id: "ph2", prompt: "Oak wall shelf with three plants and a clay jug", size: "square", style: "studio" },
143
+ ]);
144
+
145
+ return (
146
+ <div className="grid gap-3">
147
+ <Switch id="job-demo-fail" label="The next run fails" checked={fail} onChange={(e) => setFail(e.target.checked)} />
148
+ <JobPanel
149
+ variant="generator"
150
+ job={job}
151
+ heading="New product photo"
152
+ description="Pip makes it from your product photos and saves it to the catalogue."
153
+ promptLabel="Describe the photo"
154
+ placeholder="The large stoneware bowl on a kitchen table, lemons beside it…"
155
+ defaultPrompt="Linen apron hanging on a hook by a sunny window"
156
+ options={
157
+ <>
158
+ <Field id="job-demo-size" label="Size">
159
+ <Select id="job-demo-size" value={size} onChange={(e) => setSize(e.target.value)} options={SIZES} />
160
+ </Field>
161
+ <div className="grid gap-1.5">
162
+ <span id="job-demo-style" className="text-sm font-medium">
163
+ Light
164
+ </span>
165
+ <ToggleGroup
166
+ aria-label="Light"
167
+ value={style}
168
+ onChange={setStyle}
169
+ items={[
170
+ { value: "daylight", label: "Daylight" },
171
+ { value: "studio", label: "Studio" },
172
+ ]}
173
+ className="w-full"
174
+ />
175
+ </div>
176
+ </>
177
+ }
178
+ onGenerate={(prompt) =>
179
+ job.start(["Reading the product photos", "Composing the scene", "Rendering the picture", "Saving to the catalogue"], {
180
+ fail,
181
+ onDone: () => setPhotos((all) => [{ id: `ph${Date.now()}`, prompt, size, style }, ...all]),
182
+ })
183
+ }
184
+ title="Making the photo"
185
+ doneTitle="Photo saved to the catalogue"
186
+ failedTitle="The photo was not made"
187
+ resultsTitle={`Photos · ${photos.length}`}
188
+ resultsActions={
189
+ photos.length ? (
190
+ <Button size="sm" variant="quiet" onClick={() => setPhotos([])}>
191
+ Clear
192
+ </Button>
193
+ ) : null
194
+ }
195
+ resultsColumns={3}
196
+ results={photos.map((p) => (
197
+ <figure key={p.id} className="grid gap-2">
198
+ <div className={`grid place-items-center rounded-lg border border-border bg-muted text-muted-foreground ${RATIO_CLASS[p.size]}`}>
199
+ <Icon name="image" size={28} />
200
+ </div>
201
+ <figcaption className="flex items-start justify-between gap-2">
202
+ <span className="line-clamp-2 text-xs text-muted-foreground">{p.prompt}</span>
203
+ <Badge>{p.style === "studio" ? "Studio" : "Daylight"}</Badge>
204
+ </figcaption>
205
+ </figure>
206
+ ))}
207
+ emptyTitle="No photos yet"
208
+ emptyBody="Describe a photo and press Generate. It lands here and in the catalogue."
209
+ />
210
+ </div>
211
+ );
212
+ }
213
+
214
+ const TONES = [
215
+ { value: "warm", label: "Warm and plain" },
216
+ { value: "bold", label: "Short and bold" },
217
+ { value: "playful", label: "Playful" },
218
+ ];
219
+ const HEADLINES = {
220
+ warm: ["Made slowly, used every day", "Bowls for the table you actually eat at", "Clay, fire and a little patience"],
221
+ bold: ["Built to last. Priced to use.", "One bowl. Every meal.", "Stoneware that stays."],
222
+ playful: ["Soup's new favourite hangout", "Bowl-ed over yet?", "Your cereal deserves better"],
223
+ };
224
+
225
+ function CopyDemo() {
226
+ const job = useGeneratorJob();
227
+ const [tone, setTone] = useState("warm");
228
+ const [lines, setLines] = useState([]);
229
+ const [copied, setCopied] = useState(null);
230
+
231
+ return (
232
+ <JobPanel
233
+ variant="generator"
234
+ layout="split"
235
+ job={job}
236
+ heading="Ad headlines"
237
+ promptLabel="What are we advertising?"
238
+ placeholder="The stoneware bowl set, spring sale, 20% off…"
239
+ promptHint="Three headlines come back each time."
240
+ options={
241
+ <Field id="job-demo-tone" label="Tone">
242
+ <Select id="job-demo-tone" value={tone} onChange={(e) => setTone(e.target.value)} options={TONES} />
243
+ </Field>
244
+ }
245
+ generateLabel="Write headlines"
246
+ onGenerate={() =>
247
+ job.start(["Reading the product page", "Writing headlines", "Checking the length"], {
248
+ onDone: () => setLines((all) => [...HEADLINES[tone].map((text, i) => ({ id: `${Date.now()}-${i}`, text, tone })), ...all]),
249
+ })
250
+ }
251
+ title="Writing headlines"
252
+ doneTitle="Three headlines written"
253
+ aside={
254
+ <Card title="Tips" padding="sm">
255
+ <ul className="grid gap-1.5 text-sm text-muted-foreground">
256
+ <li>Name the product and the one reason to buy it.</li>
257
+ <li>Give the offer and the date it ends.</li>
258
+ <li>Under 40 characters fits every ad slot.</li>
259
+ </ul>
260
+ </Card>
261
+ }
262
+ resultsTitle="Headlines"
263
+ results={lines.map((l) => (
264
+ <div key={l.id} className="flex min-h-11 items-center justify-between gap-3 rounded-lg border border-border bg-card px-3 py-2">
265
+ <div className="min-w-0">
266
+ <p className="text-sm font-medium">{l.text}</p>
267
+ <p className="text-xs text-muted-foreground">
268
+ {TONES.find((t) => t.value === l.tone)?.label} · {l.text.length} characters
269
+ </p>
270
+ </div>
271
+ <IconButton
272
+ icon={copied === l.id ? "check" : "copy"}
273
+ label={copied === l.id ? "Copied" : "Copy headline"}
274
+ size="sm"
275
+ onClick={() => {
276
+ navigator.clipboard?.writeText(l.text).catch(() => {});
277
+ setCopied(l.id);
278
+ }}
279
+ />
280
+ </div>
281
+ ))}
282
+ />
283
+ );
284
+ }
285
+
286
+ const VARIANTS = [
287
+ { value: "panel", label: "Panel" },
288
+ { value: "photos", label: "Photos" },
289
+ { value: "copy", label: "Copy" },
290
+ ];
291
+
292
+ export default function JobPanelDemo() {
293
+ const [variant, setVariant] = useState("panel");
294
+ return (
295
+ <div className="grid gap-4">
296
+ <ToggleGroup size="sm" aria-label="Variant" value={variant} onChange={setVariant} items={VARIANTS} className="justify-self-start" />
297
+ {variant === "panel" ? <PanelDemo /> : null}
298
+ {variant === "photos" ? <PhotosDemo /> : null}
299
+ {variant === "copy" ? <CopyDemo /> : null}
300
+ </div>
301
+ );
302
+ }