makersclaw 0.2.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 (473) hide show
  1. package/THIRD-PARTY-NOTICES.md +180 -0
  2. package/package.json +3 -2
  3. package/r/annotate.json +62 -0
  4. package/r/approval-request.json +52 -0
  5. package/r/audio-player.json +74 -0
  6. package/r/auth-form.json +55 -0
  7. package/r/board.json +10 -6
  8. package/r/calendar-view.json +105 -0
  9. package/r/cart.json +62 -0
  10. package/r/chart.json +83 -0
  11. package/r/chat.json +95 -0
  12. package/r/code-editor.json +94 -0
  13. package/r/comment-box.json +64 -0
  14. package/r/contact-section.json +53 -0
  15. package/r/core.json +205 -8
  16. package/r/csv-import.json +63 -0
  17. package/r/data-table.json +69 -0
  18. package/r/diagram.json +74 -0
  19. package/r/doc-editor.json +82 -0
  20. package/r/doc-page.json +61 -0
  21. package/r/email-render.json +73 -0
  22. package/r/faq.json +50 -0
  23. package/r/file-upload.json +54 -0
  24. package/r/flow-canvas.json +93 -0
  25. package/r/footer.json +52 -0
  26. package/r/gantt.json +70 -0
  27. package/r/job-panel.json +12 -7
  28. package/r/json-editor.json +66 -0
  29. package/r/map.json +89 -0
  30. package/r/menubar.json +52 -0
  31. package/r/mind-map.json +67 -0
  32. package/r/navigation-menu.json +52 -0
  33. package/r/order-detail.json +54 -0
  34. package/r/org-chart.json +66 -0
  35. package/r/page-builder.json +105 -0
  36. package/r/payment-methods.json +51 -0
  37. package/r/pdf-document.json +79 -0
  38. package/r/pdf-viewer.json +88 -0
  39. package/r/product-detail.json +76 -0
  40. package/r/product-grid.json +65 -0
  41. package/r/record-form.json +67 -0
  42. package/r/record-notes.json +55 -0
  43. package/r/registry.json +3411 -29
  44. package/r/search-dialog.json +51 -0
  45. package/r/settings-list.json +66 -0
  46. package/r/setup-checklist.json +51 -0
  47. package/r/share-dialog.json +52 -0
  48. package/r/sidebar.json +69 -0
  49. package/r/signature-pad.json +72 -0
  50. package/r/sketch-canvas.json +99 -0
  51. package/r/spreadsheet.json +90 -0
  52. package/r/stat-cards.json +66 -0
  53. package/r/task-list.json +63 -0
  54. package/r/task-model.json +98 -0
  55. package/r/testimonials.json +52 -0
  56. package/r/transaction-list.json +53 -0
  57. package/r/whiteboard.json +66 -0
  58. package/registry/blocks/annotate/README.md +179 -0
  59. package/registry/blocks/annotate/annotate-data.js +250 -0
  60. package/registry/blocks/annotate/annotate.jsx +646 -0
  61. package/registry/blocks/annotate/block.json +10 -0
  62. package/registry/blocks/annotate/demo.jsx +135 -0
  63. package/registry/blocks/annotate/index.js +15 -0
  64. package/registry/blocks/approval-request/README.md +116 -0
  65. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  66. package/registry/blocks/approval-request/block.json +10 -0
  67. package/registry/blocks/approval-request/demo.jsx +127 -0
  68. package/registry/blocks/approval-request/index.js +4 -0
  69. package/registry/blocks/audio-player/README.md +167 -0
  70. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  71. package/registry/blocks/audio-player/block.json +14 -0
  72. package/registry/blocks/audio-player/colors.js +109 -0
  73. package/registry/blocks/audio-player/demo.jsx +209 -0
  74. package/registry/blocks/audio-player/index.js +6 -0
  75. package/registry/blocks/audio-player/time.js +67 -0
  76. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  77. package/registry/blocks/auth-form/README.md +126 -0
  78. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  79. package/registry/blocks/auth-form/block.json +10 -0
  80. package/registry/blocks/auth-form/demo.jsx +131 -0
  81. package/registry/blocks/auth-form/index.js +3 -0
  82. package/registry/blocks/board/README.md +55 -5
  83. package/registry/blocks/board/block.json +2 -2
  84. package/registry/blocks/board/board.jsx +230 -86
  85. package/registry/blocks/board/demo.jsx +103 -24
  86. package/registry/blocks/calendar-view/README.md +180 -0
  87. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  88. package/registry/blocks/calendar-view/block.json +76 -0
  89. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  90. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  91. package/registry/blocks/calendar-view/demo.jsx +195 -0
  92. package/registry/blocks/calendar-view/draft.jsx +49 -0
  93. package/registry/blocks/calendar-view/index.js +39 -0
  94. package/registry/blocks/calendar-view/month.jsx +346 -0
  95. package/registry/blocks/calendar-view/paint.js +69 -0
  96. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  97. package/registry/blocks/calendar-view/tray.jsx +87 -0
  98. package/registry/blocks/cart/README.md +146 -0
  99. package/registry/blocks/cart/block.json +10 -0
  100. package/registry/blocks/cart/cart.jsx +597 -0
  101. package/registry/blocks/cart/demo.jsx +98 -0
  102. package/registry/blocks/cart/index.js +4 -0
  103. package/registry/blocks/cart/money.js +28 -0
  104. package/registry/blocks/chart/README.md +316 -0
  105. package/registry/blocks/chart/block.json +10 -0
  106. package/registry/blocks/chart/cartesian.jsx +642 -0
  107. package/registry/blocks/chart/core.jsx +262 -0
  108. package/registry/blocks/chart/demo.jsx +357 -0
  109. package/registry/blocks/chart/heatmap.jsx +336 -0
  110. package/registry/blocks/chart/index.js +8 -0
  111. package/registry/blocks/chart/pie.jsx +245 -0
  112. package/registry/blocks/chart/sparkline.jsx +88 -0
  113. package/registry/blocks/chat/README.md +273 -0
  114. package/registry/blocks/chat/attachment.jsx +95 -0
  115. package/registry/blocks/chat/block.json +10 -0
  116. package/registry/blocks/chat/chat.jsx +132 -0
  117. package/registry/blocks/chat/composer.jsx +364 -0
  118. package/registry/blocks/chat/demo.jsx +578 -0
  119. package/registry/blocks/chat/header.jsx +34 -0
  120. package/registry/blocks/chat/index.js +9 -0
  121. package/registry/blocks/chat/message.jsx +450 -0
  122. package/registry/blocks/chat/scroller.jsx +247 -0
  123. package/registry/blocks/chat/text.jsx +104 -0
  124. package/registry/blocks/code-editor/README.md +210 -0
  125. package/registry/blocks/code-editor/block.json +22 -0
  126. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  127. package/registry/blocks/code-editor/codemirror.js +38 -0
  128. package/registry/blocks/code-editor/demo.jsx +205 -0
  129. package/registry/blocks/code-editor/index.js +8 -0
  130. package/registry/blocks/code-editor/json.js +317 -0
  131. package/registry/blocks/code-editor/sql.js +136 -0
  132. package/registry/blocks/code-editor/text.js +101 -0
  133. package/registry/blocks/code-editor/theme.js +186 -0
  134. package/registry/blocks/comment-box/README.md +123 -0
  135. package/registry/blocks/comment-box/block.json +10 -0
  136. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  137. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  138. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  139. package/registry/blocks/comment-box/demo.jsx +141 -0
  140. package/registry/blocks/comment-box/index.js +8 -0
  141. package/registry/blocks/contact-section/README.md +152 -0
  142. package/registry/blocks/contact-section/block.json +11 -0
  143. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  144. package/registry/blocks/contact-section/demo.jsx +93 -0
  145. package/registry/blocks/contact-section/index.js +4 -0
  146. package/registry/blocks/csv-import/README.md +133 -0
  147. package/registry/blocks/csv-import/block.json +13 -0
  148. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  149. package/registry/blocks/csv-import/demo.jsx +106 -0
  150. package/registry/blocks/csv-import/import.js +200 -0
  151. package/registry/blocks/csv-import/index.js +7 -0
  152. package/registry/blocks/data-table/README.md +386 -0
  153. package/registry/blocks/data-table/block.json +10 -0
  154. package/registry/blocks/data-table/data-table.jsx +1164 -0
  155. package/registry/blocks/data-table/demo.jsx +588 -0
  156. package/registry/blocks/data-table/index.js +5 -0
  157. package/registry/blocks/data-table/model.js +169 -0
  158. package/registry/blocks/diagram/README.md +108 -0
  159. package/registry/blocks/diagram/block.json +13 -0
  160. package/registry/blocks/diagram/demo.jsx +113 -0
  161. package/registry/blocks/diagram/diagram.jsx +481 -0
  162. package/registry/blocks/diagram/index.js +7 -0
  163. package/registry/blocks/diagram/mermaid.js +52 -0
  164. package/registry/blocks/diagram/palette.js +313 -0
  165. package/registry/blocks/diagram/source.js +98 -0
  166. package/registry/blocks/doc-editor/README.md +215 -0
  167. package/registry/blocks/doc-editor/block.json +15 -0
  168. package/registry/blocks/doc-editor/demo.jsx +225 -0
  169. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  170. package/registry/blocks/doc-editor/doc.js +309 -0
  171. package/registry/blocks/doc-editor/index.js +7 -0
  172. package/registry/blocks/doc-editor/schema.jsx +56 -0
  173. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  174. package/registry/blocks/doc-editor/theme.js +82 -0
  175. package/registry/blocks/doc-page/README.md +119 -0
  176. package/registry/blocks/doc-page/autosave.js +104 -0
  177. package/registry/blocks/doc-page/block.json +10 -0
  178. package/registry/blocks/doc-page/demo.jsx +137 -0
  179. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  180. package/registry/blocks/doc-page/index.js +4 -0
  181. package/registry/blocks/email-render/README.md +151 -0
  182. package/registry/blocks/email-render/block.json +14 -0
  183. package/registry/blocks/email-render/demo.jsx +153 -0
  184. package/registry/blocks/email-render/doc-email.jsx +210 -0
  185. package/registry/blocks/email-render/email.jsx +221 -0
  186. package/registry/blocks/email-render/index.js +10 -0
  187. package/registry/blocks/email-render/render.js +50 -0
  188. package/registry/blocks/email-render/theme.js +215 -0
  189. package/registry/blocks/faq/README.md +101 -0
  190. package/registry/blocks/faq/block.json +11 -0
  191. package/registry/blocks/faq/demo.jsx +89 -0
  192. package/registry/blocks/faq/faq.jsx +220 -0
  193. package/registry/blocks/faq/index.js +4 -0
  194. package/registry/blocks/file-upload/README.md +138 -0
  195. package/registry/blocks/file-upload/block.json +10 -0
  196. package/registry/blocks/file-upload/demo.jsx +204 -0
  197. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  198. package/registry/blocks/file-upload/index.js +4 -0
  199. package/registry/blocks/flow-canvas/README.md +420 -0
  200. package/registry/blocks/flow-canvas/block.json +13 -0
  201. package/registry/blocks/flow-canvas/board.js +819 -0
  202. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  203. package/registry/blocks/flow-canvas/context.jsx +35 -0
  204. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  205. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  206. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  207. package/registry/blocks/flow-canvas/index.js +41 -0
  208. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  209. package/registry/blocks/flow-canvas/theme.js +174 -0
  210. package/registry/blocks/footer/README.md +133 -0
  211. package/registry/blocks/footer/block.json +11 -0
  212. package/registry/blocks/footer/demo.jsx +119 -0
  213. package/registry/blocks/footer/footer.jsx +406 -0
  214. package/registry/blocks/footer/index.js +4 -0
  215. package/registry/blocks/gantt/README.md +220 -0
  216. package/registry/blocks/gantt/block.json +10 -0
  217. package/registry/blocks/gantt/demo.jsx +148 -0
  218. package/registry/blocks/gantt/gantt.jsx +923 -0
  219. package/registry/blocks/gantt/index.js +7 -0
  220. package/registry/blocks/gantt/rows.jsx +468 -0
  221. package/registry/blocks/gantt/schedule.js +278 -0
  222. package/registry/blocks/job-panel/README.md +80 -0
  223. package/registry/blocks/job-panel/block.json +3 -3
  224. package/registry/blocks/job-panel/demo.jsx +230 -3
  225. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  226. package/registry/blocks/json-editor/README.md +133 -0
  227. package/registry/blocks/json-editor/block.json +10 -0
  228. package/registry/blocks/json-editor/demo.jsx +92 -0
  229. package/registry/blocks/json-editor/index.js +7 -0
  230. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  231. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  232. package/registry/blocks/json-editor/tree.js +225 -0
  233. package/registry/blocks/map/README.md +221 -0
  234. package/registry/blocks/map/block.json +14 -0
  235. package/registry/blocks/map/demo.jsx +201 -0
  236. package/registry/blocks/map/geo.js +198 -0
  237. package/registry/blocks/map/index.js +8 -0
  238. package/registry/blocks/map/list.jsx +128 -0
  239. package/registry/blocks/map/map-view.jsx +715 -0
  240. package/registry/blocks/map/maplibre.js +30 -0
  241. package/registry/blocks/map/marks.jsx +146 -0
  242. package/registry/blocks/map/theme.js +142 -0
  243. package/registry/blocks/menubar/README.md +109 -0
  244. package/registry/blocks/menubar/block.json +10 -0
  245. package/registry/blocks/menubar/demo.jsx +128 -0
  246. package/registry/blocks/menubar/index.js +4 -0
  247. package/registry/blocks/menubar/menubar.jsx +199 -0
  248. package/registry/blocks/mind-map/README.md +206 -0
  249. package/registry/blocks/mind-map/block.json +10 -0
  250. package/registry/blocks/mind-map/demo.jsx +103 -0
  251. package/registry/blocks/mind-map/index.js +31 -0
  252. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  253. package/registry/blocks/mind-map/topic.jsx +143 -0
  254. package/registry/blocks/mind-map/tree.js +645 -0
  255. package/registry/blocks/navigation-menu/README.md +124 -0
  256. package/registry/blocks/navigation-menu/block.json +10 -0
  257. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  258. package/registry/blocks/navigation-menu/index.js +4 -0
  259. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  260. package/registry/blocks/order-detail/README.md +109 -0
  261. package/registry/blocks/order-detail/block.json +10 -0
  262. package/registry/blocks/order-detail/demo.jsx +88 -0
  263. package/registry/blocks/order-detail/index.js +4 -0
  264. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  265. package/registry/blocks/org-chart/README.md +145 -0
  266. package/registry/blocks/org-chart/block.json +10 -0
  267. package/registry/blocks/org-chart/demo.jsx +94 -0
  268. package/registry/blocks/org-chart/index.js +7 -0
  269. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  270. package/registry/blocks/org-chart/org.js +245 -0
  271. package/registry/blocks/org-chart/person.jsx +96 -0
  272. package/registry/blocks/page-builder/README.md +257 -0
  273. package/registry/blocks/page-builder/block.json +14 -0
  274. package/registry/blocks/page-builder/demo.jsx +145 -0
  275. package/registry/blocks/page-builder/grapes.js +18 -0
  276. package/registry/blocks/page-builder/index.js +11 -0
  277. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  278. package/registry/blocks/page-builder/page-view.jsx +33 -0
  279. package/registry/blocks/page-builder/page.js +118 -0
  280. package/registry/blocks/page-builder/panels.jsx +588 -0
  281. package/registry/blocks/page-builder/sections.js +209 -0
  282. package/registry/blocks/page-builder/theme.js +87 -0
  283. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  284. package/registry/blocks/page-builder/tokens.js +329 -0
  285. package/registry/blocks/payment-methods/README.md +104 -0
  286. package/registry/blocks/payment-methods/block.json +10 -0
  287. package/registry/blocks/payment-methods/demo.jsx +71 -0
  288. package/registry/blocks/payment-methods/index.js +4 -0
  289. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  290. package/registry/blocks/pdf-document/README.md +213 -0
  291. package/registry/blocks/pdf-document/block.json +13 -0
  292. package/registry/blocks/pdf-document/demo.jsx +136 -0
  293. package/registry/blocks/pdf-document/index.js +33 -0
  294. package/registry/blocks/pdf-document/money.js +83 -0
  295. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  296. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  297. package/registry/blocks/pdf-document/quote.jsx +179 -0
  298. package/registry/blocks/pdf-document/theme.js +193 -0
  299. package/registry/blocks/pdf-viewer/README.md +191 -0
  300. package/registry/blocks/pdf-viewer/block.json +14 -0
  301. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  302. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  303. package/registry/blocks/pdf-viewer/index.js +8 -0
  304. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  305. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  306. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  307. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  308. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  309. package/registry/blocks/product-detail/README.md +217 -0
  310. package/registry/blocks/product-detail/block.json +10 -0
  311. package/registry/blocks/product-detail/demo.jsx +233 -0
  312. package/registry/blocks/product-detail/index.js +7 -0
  313. package/registry/blocks/product-detail/price.jsx +115 -0
  314. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  315. package/registry/blocks/product-detail/product-media.jsx +102 -0
  316. package/registry/blocks/product-detail/product-options.jsx +144 -0
  317. package/registry/blocks/product-grid/README.md +162 -0
  318. package/registry/blocks/product-grid/block.json +10 -0
  319. package/registry/blocks/product-grid/demo.jsx +255 -0
  320. package/registry/blocks/product-grid/index.js +5 -0
  321. package/registry/blocks/product-grid/product-card.jsx +232 -0
  322. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  323. package/registry/blocks/record-form/README.md +196 -0
  324. package/registry/blocks/record-form/block.json +10 -0
  325. package/registry/blocks/record-form/demo.jsx +525 -0
  326. package/registry/blocks/record-form/index.js +4 -0
  327. package/registry/blocks/record-form/record-fields.jsx +457 -0
  328. package/registry/blocks/record-form/record-form.jsx +415 -0
  329. package/registry/blocks/record-form/rules.js +81 -0
  330. package/registry/blocks/record-notes/README.md +139 -0
  331. package/registry/blocks/record-notes/block.json +10 -0
  332. package/registry/blocks/record-notes/demo.jsx +179 -0
  333. package/registry/blocks/record-notes/index.js +4 -0
  334. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  335. package/registry/blocks/search-dialog/README.md +108 -0
  336. package/registry/blocks/search-dialog/block.json +10 -0
  337. package/registry/blocks/search-dialog/demo.jsx +116 -0
  338. package/registry/blocks/search-dialog/index.js +3 -0
  339. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  340. package/registry/blocks/settings-list/README.md +171 -0
  341. package/registry/blocks/settings-list/block.json +10 -0
  342. package/registry/blocks/settings-list/demo.jsx +333 -0
  343. package/registry/blocks/settings-list/index.js +4 -0
  344. package/registry/blocks/settings-list/row-state.jsx +93 -0
  345. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  346. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  347. package/registry/blocks/setup-checklist/README.md +142 -0
  348. package/registry/blocks/setup-checklist/block.json +10 -0
  349. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  350. package/registry/blocks/setup-checklist/index.js +4 -0
  351. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  352. package/registry/blocks/share-dialog/README.md +113 -0
  353. package/registry/blocks/share-dialog/block.json +10 -0
  354. package/registry/blocks/share-dialog/demo.jsx +140 -0
  355. package/registry/blocks/share-dialog/index.js +3 -0
  356. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  357. package/registry/blocks/sidebar/README.md +190 -0
  358. package/registry/blocks/sidebar/block.json +43 -0
  359. package/registry/blocks/sidebar/demo.jsx +577 -0
  360. package/registry/blocks/sidebar/index.js +4 -0
  361. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  362. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  363. package/registry/blocks/signature-pad/README.md +137 -0
  364. package/registry/blocks/signature-pad/block.json +13 -0
  365. package/registry/blocks/signature-pad/colors.js +115 -0
  366. package/registry/blocks/signature-pad/demo.jsx +94 -0
  367. package/registry/blocks/signature-pad/index.js +6 -0
  368. package/registry/blocks/signature-pad/pad.js +7 -0
  369. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  370. package/registry/blocks/signature-pad/signature.js +68 -0
  371. package/registry/blocks/sketch-canvas/README.md +280 -0
  372. package/registry/blocks/sketch-canvas/block.json +13 -0
  373. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  374. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  375. package/registry/blocks/sketch-canvas/index.js +9 -0
  376. package/registry/blocks/sketch-canvas/palette.js +226 -0
  377. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  378. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  379. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  380. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  381. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  382. package/registry/blocks/sketch-canvas/theme.js +131 -0
  383. package/registry/blocks/spreadsheet/README.md +307 -0
  384. package/registry/blocks/spreadsheet/block.json +13 -0
  385. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  386. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  387. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  388. package/registry/blocks/spreadsheet/grid.js +387 -0
  389. package/registry/blocks/spreadsheet/index.js +34 -0
  390. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  391. package/registry/blocks/spreadsheet/types.js +473 -0
  392. package/registry/blocks/stat-cards/README.md +173 -0
  393. package/registry/blocks/stat-cards/block.json +10 -0
  394. package/registry/blocks/stat-cards/demo.jsx +257 -0
  395. package/registry/blocks/stat-cards/index.js +4 -0
  396. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  397. package/registry/blocks/stat-cards/usage.jsx +243 -0
  398. package/registry/blocks/task-list/README.md +176 -0
  399. package/registry/blocks/task-list/block.json +10 -0
  400. package/registry/blocks/task-list/demo.jsx +134 -0
  401. package/registry/blocks/task-list/index.js +5 -0
  402. package/registry/blocks/task-list/task-list.jsx +907 -0
  403. package/registry/blocks/task-model/README.md +455 -0
  404. package/registry/blocks/task-model/block.json +167 -0
  405. package/registry/blocks/task-model/changes.js +89 -0
  406. package/registry/blocks/task-model/dates.js +371 -0
  407. package/registry/blocks/task-model/demo.jsx +215 -0
  408. package/registry/blocks/task-model/dnd.jsx +240 -0
  409. package/registry/blocks/task-model/index.js +97 -0
  410. package/registry/blocks/task-model/model.js +919 -0
  411. package/registry/blocks/task-model/parts.jsx +449 -0
  412. package/registry/blocks/task-model/toolbar.jsx +271 -0
  413. package/registry/blocks/testimonials/README.md +139 -0
  414. package/registry/blocks/testimonials/block.json +11 -0
  415. package/registry/blocks/testimonials/demo.jsx +137 -0
  416. package/registry/blocks/testimonials/index.js +4 -0
  417. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  418. package/registry/blocks/transaction-list/README.md +126 -0
  419. package/registry/blocks/transaction-list/block.json +10 -0
  420. package/registry/blocks/transaction-list/demo.jsx +79 -0
  421. package/registry/blocks/transaction-list/index.js +4 -0
  422. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  423. package/registry/blocks/whiteboard/README.md +179 -0
  424. package/registry/blocks/whiteboard/block.json +10 -0
  425. package/registry/blocks/whiteboard/demo.jsx +169 -0
  426. package/registry/blocks/whiteboard/index.js +6 -0
  427. package/registry/blocks/whiteboard/templates.js +150 -0
  428. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  429. package/src/install.mjs +18 -0
  430. package/src/shadcn.mjs +8 -0
  431. package/templates/next/files/README.md +145 -11
  432. package/templates/next/files/app/globals.css +55 -4
  433. package/templates/next/files/check/run.mjs +3 -3
  434. package/templates/next/files/components/ui/avatar.jsx +141 -0
  435. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  436. package/templates/next/files/components/ui/button-group.jsx +70 -0
  437. package/templates/next/files/components/ui/button.jsx +132 -12
  438. package/templates/next/files/components/ui/calendar.jsx +609 -0
  439. package/templates/next/files/components/ui/carousel.jsx +281 -0
  440. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  441. package/templates/next/files/components/ui/combobox.jsx +608 -0
  442. package/templates/next/files/components/ui/command.jsx +577 -0
  443. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  444. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  445. package/templates/next/files/components/ui/distribution.jsx +117 -0
  446. package/templates/next/files/components/ui/feedback.jsx +143 -0
  447. package/templates/next/files/components/ui/field.jsx +115 -3
  448. package/templates/next/files/components/ui/file-input.jsx +234 -0
  449. package/templates/next/files/components/ui/icon.jsx +130 -8
  450. package/templates/next/files/components/ui/image.jsx +143 -0
  451. package/templates/next/files/components/ui/index.js +47 -2
  452. package/templates/next/files/components/ui/input-group.jsx +213 -0
  453. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  454. package/templates/next/files/components/ui/item.jsx +206 -0
  455. package/templates/next/files/components/ui/menu.jsx +454 -82
  456. package/templates/next/files/components/ui/notice.jsx +126 -14
  457. package/templates/next/files/components/ui/pagination.jsx +156 -0
  458. package/templates/next/files/components/ui/popover.jsx +284 -0
  459. package/templates/next/files/components/ui/radio.jsx +193 -0
  460. package/templates/next/files/components/ui/rating.jsx +131 -0
  461. package/templates/next/files/components/ui/resizable.jsx +338 -0
  462. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  463. package/templates/next/files/components/ui/separator.jsx +119 -0
  464. package/templates/next/files/components/ui/sheet.jsx +96 -11
  465. package/templates/next/files/components/ui/slider.jsx +174 -0
  466. package/templates/next/files/components/ui/stat.jsx +574 -0
  467. package/templates/next/files/components/ui/steps.jsx +338 -0
  468. package/templates/next/files/components/ui/swatch.jsx +33 -0
  469. package/templates/next/files/components/ui/table.jsx +130 -0
  470. package/templates/next/files/components/ui/toast.jsx +440 -0
  471. package/templates/next/files/components/ui/toggle.jsx +195 -0
  472. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  473. package/templates/next/template.json +264 -8
@@ -0,0 +1,135 @@
1
+ "use client";
2
+
3
+ // Annotate four ways — the gallery's and the smoke test's surface. Not
4
+ // installed into apps.
5
+ // Bug report a dashboard screenshot already marked up: a box, a
6
+ // highlight, two numbered notes with words; saves and
7
+ // sends through callbacks (a switch makes them fail),
8
+ // and beside it what an agent receives.
9
+ // Fresh screenshot the screenshot alone: the starter templates.
10
+ // No screenshot the drop zone (drop, browse or paste).
11
+ // Read-only the marked-up screenshot to look at.
12
+ import { useState } from "react";
13
+ import { Card, Switch, TabPanel, Tabs } from "../components/ui";
14
+ import { Annotate, annotationToText } from "../components/blocks/annotate";
15
+
16
+ // A small made-up analytics dashboard (480 × 300), drawn as flat blocks and
17
+ // encoded as a PNG — a stand-in for a real screenshot.
18
+ const DASHBOARD_PNG = "data:image/png;base64,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";
19
+ const SHOT = { src: DASHBOARD_PNG, width: 480, height: 300 };
20
+
21
+ // Marks written by hand, colours as TOKENS only (customData.tokens). A pin
22
+ // is an ellipse carrying customData.note, with its number as a bound label.
23
+ const tok = (strokeColor, backgroundColor) => ({ tokens: { strokeColor, ...(backgroundColor ? { backgroundColor } : {}) } });
24
+ const pin = (n, x, y) => [
25
+ {
26
+ id: `pin-${n}`,
27
+ type: "ellipse",
28
+ x,
29
+ y,
30
+ width: 28,
31
+ height: 28,
32
+ fillStyle: "solid",
33
+ strokeWidth: 2,
34
+ roughness: 0,
35
+ boundElements: [{ type: "text", id: `pin-${n}-label` }],
36
+ customData: { note: n, ...tok("destructive", "destructive:soft") },
37
+ },
38
+ {
39
+ id: `pin-${n}-label`,
40
+ type: "text",
41
+ x: x + 9,
42
+ y: y + 5,
43
+ width: 10,
44
+ height: 18,
45
+ text: String(n),
46
+ fontSize: 14,
47
+ containerId: `pin-${n}`,
48
+ textAlign: "center",
49
+ verticalAlign: "middle",
50
+ customData: { note: n, ...tok("destructive") },
51
+ },
52
+ ];
53
+
54
+ const MARKED = {
55
+ type: "annotation",
56
+ version: 1,
57
+ image: SHOT,
58
+ sketch: {
59
+ elements: [
60
+ { id: "box", type: "rectangle", x: 276, y: 156, width: 36, height: 120, strokeWidth: 3, roughness: 0, roundness: { type: 3 }, customData: tok("destructive", "none") },
61
+ ...pin(1, 300, 124),
62
+ { id: "band", type: "rectangle", x: 356, y: 219, width: 108, height: 16, fillStyle: "solid", strokeWidth: 1, roughness: 0, opacity: 35, customData: tok("warning", "warning") },
63
+ ...pin(2, 440, 186),
64
+ ],
65
+ },
66
+ notes: [
67
+ { n: 1, text: "September is amber and nothing says why. Label it, or keep it blue like the rest." },
68
+ { n: 2, text: "This refund row shows red with no reason — add a status column so it reads without the colour." },
69
+ ],
70
+ };
71
+
72
+ function BugReport() {
73
+ const [value, setValue] = useState(MARKED);
74
+ const [fail, setFail] = useState(false);
75
+ const [sent, setSent] = useState(null);
76
+ const wait = () => new Promise((r) => setTimeout(r, 500));
77
+ const save = async () => {
78
+ await wait();
79
+ return fail ? { ok: false, error: "The network dropped" } : { ok: true };
80
+ };
81
+ const submit = async ({ image, notes, text }) => {
82
+ await wait();
83
+ if (fail) return { ok: false, error: "The ticket couldn't be filed" };
84
+ setSent({ size: Math.max(1, Math.round(image.size / 1024)), count: notes.length, text });
85
+ return { ok: true };
86
+ };
87
+ return (
88
+ <div className="grid gap-4 xl:grid-cols-[minmax(0,1fr)_18rem]">
89
+ <Annotate title="Revenue dashboard — feedback" value={value} onChange={setValue} onSave={save} onSubmit={submit} submitLabel="File the bug" />
90
+ <div className="grid content-start gap-4">
91
+ <Card title="Callbacks">
92
+ <Switch id="annotate-fail" label="Make saves and sends fail" checked={fail} onChange={(e) => setFail(e.target.checked)} />
93
+ </Card>
94
+ <Card title="What an agent reads">
95
+ <pre className="whitespace-pre-wrap break-words font-mono text-xs">{annotationToText(value) || "Nothing yet."}</pre>
96
+ {sent ? (
97
+ <p className="mt-2 text-xs text-muted-foreground">
98
+ Sent: a PNG of {sent.size} KB and {sent.count} notes.
99
+ </p>
100
+ ) : null}
101
+ </Card>
102
+ </div>
103
+ </div>
104
+ );
105
+ }
106
+
107
+ export default function AnnotateDemo() {
108
+ const [tab, setTab] = useState("bug");
109
+ return (
110
+ <div className="grid gap-4">
111
+ <Tabs
112
+ aria-label="Annotate variants"
113
+ value={tab}
114
+ onChange={setTab}
115
+ tabs={[
116
+ { key: "bug", label: "Bug report" },
117
+ { key: "fresh", label: "Fresh screenshot" },
118
+ { key: "none", label: "No screenshot" },
119
+ { key: "read", label: "Read-only" },
120
+ ]}
121
+ />
122
+ <TabPanel tab={tab} value={tab}>
123
+ {tab === "bug" ? (
124
+ <BugReport />
125
+ ) : tab === "fresh" ? (
126
+ <Annotate title="Onboarding screen" defaultValue={{ image: SHOT }} onSubmit={async () => ({ ok: true })} />
127
+ ) : tab === "none" ? (
128
+ <Annotate title="Report a problem" onSubmit={async () => ({ ok: true })} submitLabel="Send to support" />
129
+ ) : (
130
+ <Annotate title="Revenue dashboard — feedback" defaultValue={MARKED} readOnly />
131
+ )}
132
+ </TabPanel>
133
+ </div>
134
+ );
135
+ }
@@ -0,0 +1,15 @@
1
+ // The Annotate block — `makersclaw add annotate`. Fixed: compose it
2
+ // through its props (README.md beside this file). Built on sketch-canvas
3
+ // (the canvas underneath); the helpers read an annotation anywhere, the
4
+ // server included.
5
+ export { Annotate, ANNOTATE_TOOLS } from "./annotate";
6
+ export {
7
+ ANNOTATE_TEMPLATES,
8
+ emptyAnnotation,
9
+ toAnnotation,
10
+ annotationNotes,
11
+ annotationToText,
12
+ noteMarkers,
13
+ nextNoteNumber,
14
+ markerSkeleton,
15
+ } from "./annotate-data";
@@ -0,0 +1,116 @@
1
+ # ApprovalRequest
2
+
3
+ One request waiting on a decision: what is asked for (label and value
4
+ facts, the amount in large type), who asked and when, why, and Approve /
5
+ Reject. Reject asks for a reason the requester will see. The decision
6
+ goes out through your callbacks; while one runs its button spins, when it
7
+ fails the card says why and the buttons stay, and once it lands the card
8
+ shows the outcome ("Approved by you · 23 September 2026") in their place.
9
+
10
+ ```jsx
11
+ import { ApprovalRequest } from "../components/blocks/approval-request"; // a Makersclaw app ("./blocks/approval-request" from components/)
12
+ import { ApprovalRequest } from "@/components/makersclaw/blocks/approval-request"; // a shadcn project
13
+ ```
14
+
15
+ A client component. Load the request in the server surface (README §4)
16
+ and pass its fields in.
17
+
18
+ ## The data
19
+
20
+ - `details` — the card's facts, in order:
21
+ `[{ label, value, icon?, emphasis? }]`. `value` is a string or a node;
22
+ `icon` is a kit `Icon` name; `emphasis` sets the value large (the
23
+ amount).
24
+ - `sections` — `variant="page"` only, the detail beside the card:
25
+ `[{ title, fields: [{ label, value, emphasis? }] }]`.
26
+ - `requester` — `{ name, role?, src? }` (`src` a picture URL).
27
+
28
+ ## Props
29
+
30
+ - `title` — what is asked for ("Linear Business", "Refund for order
31
+ 20931"). Without it (and not `loading`) the block shows `emptyLabel`.
32
+ - `onApprove()` — save the yes. Return `{ ok: true }` or
33
+ `{ ok: false, error }`; a throw counts as failed and its message shows.
34
+ - `onReject(reason)` — save the no, with the reason typed (a trimmed
35
+ string, "" when `reasonRequired` is off). Same return as `onApprove`.
36
+ Leave either out and its button is not drawn.
37
+ - `variant` — `"card"` (default: the card alone, with the requester, the
38
+ date and the reason why) or `"page"`: a heading, the `sections` and "The
39
+ request" (requester, date, why) on the left, the card on the right
40
+ (under them on a phone), sticky from 1024px.
41
+ - `status` — `"pending"` (default) · `"approved"` · `"rejected"`. The
42
+ block shows its own outcome as soon as a decision saves; a new
43
+ `status` from you replaces it.
44
+ - `decidedBy` · `decidedAt` · `decisionNote` — for a request decided
45
+ before: who, when, and the reason, shown under the outcome.
46
+ - `kind` — a small badge beside the title ("Per seat", "Refund").
47
+ - `requestedAt` — an ISO date or a `Date`.
48
+ - `justification` — the requester's reason, as a paragraph.
49
+ - `reasonRequired` — default `true`: Reject opens a reason field and
50
+ sends only when it is filled. `false`: Reject sends at once.
51
+ - `approveLabel` · `rejectLabel` — default "Approve" / "Reject"
52
+ ("Refund €149.00", "Decline").
53
+ - `heading` · `description` — `page`: the page's title (default `title`)
54
+ and the line under it.
55
+ - `formatDate(value)` — how a date reads; default the viewer's long date
56
+ ("21 September 2026").
57
+ - `loading` — a skeleton card while the request loads.
58
+ - `emptyLabel` — default "Nothing is waiting for a decision.".
59
+ - `className` — layout around it (width, margin). Never colour.
60
+
61
+ ## Example
62
+
63
+ ```jsx
64
+ // components/PurchaseApproval.jsx — client
65
+ "use client";
66
+ import { useRouter } from "next/navigation";
67
+ import { updateRow } from "../lib/actions";
68
+ import { ApprovalRequest } from "./blocks/approval-request";
69
+
70
+ const usd = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
71
+
72
+ export default function PurchaseApproval({ request }) {
73
+ const router = useRouter();
74
+ const decide = (status, reason) =>
75
+ updateRow({ source: "public.purchase_requests", id: request.id, patch: { status, reason: reason ?? null }, detail: request.product }).then(
76
+ (res) => (res.ok && router.refresh(), res),
77
+ );
78
+ return (
79
+ <ApprovalRequest
80
+ title={request.product}
81
+ kind={request.pricing}
82
+ details={[
83
+ { label: "Starts", value: request.starts_on, icon: "calendar" },
84
+ { label: "Seats", value: `${request.seats} people`, icon: "users" },
85
+ { label: "Yearly cost", value: usd.format(request.amount), icon: "dollar", emphasis: true },
86
+ ]}
87
+ requester={{ name: request.requested_by, role: request.team }}
88
+ requestedAt={request.created_at}
89
+ justification={request.why}
90
+ status={request.status}
91
+ decidedBy={request.decided_by}
92
+ decidedAt={request.decided_at}
93
+ decisionNote={request.reason}
94
+ onApprove={() => decide("approved")}
95
+ onReject={(reason) => decide("rejected", reason)}
96
+ />
97
+ );
98
+ }
99
+ ```
100
+
101
+ ## What it will not do
102
+
103
+ - List many requests: put them in a `data-table` and open one in this
104
+ block (a `Sheet`), or render one per row.
105
+ - Take a decision in several steps (two approvers, a delegate): `status`
106
+ is one of three.
107
+ - Edit the request: its facts are read-only here.
108
+
109
+ A request it cannot be is your own component in `components/`, built
110
+ from the kit — not an edit to this block. Its files are fixed: `npm run
111
+ check` refuses a change, and `makersclaw add approval-request` restores
112
+ them.
113
+
114
+ ## Credits
115
+
116
+ Ported from Creative Tim UI (https://github.com/creativetimofficial/ui, software-purchase-01 and software-purchase-card, MIT), rewritten on the Makersclaw kit.
@@ -0,0 +1,386 @@
1
+ "use client";
2
+
3
+ import { useEffect, useId, useState } from "react";
4
+ import { Avatar, Badge, Button, Empty, Field, Icon, Notice, Separator, Skeleton, Textarea, cx } from "../../ui";
5
+
6
+ // ApprovalRequest — one request waiting on a decision: what is asked for
7
+ // (label/value facts), who asked and when, why, and Approve / Reject. The
8
+ // decision goes out through `onApprove()` / `onReject(reason)`; the
9
+ // block shows it working, shows a failure, and once it lands shows the
10
+ // outcome in place of the buttons.
11
+
12
+ const STATUS = {
13
+ pending: { tone: "warning", label: "Pending approval" },
14
+ approved: { tone: "success", label: "Approved" },
15
+ rejected: { tone: "danger", label: "Rejected" },
16
+ };
17
+
18
+ function defaultFormat(value) {
19
+ if (!value) return "";
20
+ const d = value instanceof Date ? value : new Date(value);
21
+ if (Number.isNaN(d.getTime())) return String(value);
22
+ return new Intl.DateTimeFormat(undefined, { dateStyle: "long" }).format(d);
23
+ }
24
+
25
+ function When({ value, format }) {
26
+ if (!value) return null;
27
+ const iso = value instanceof Date ? value.toISOString() : String(value);
28
+ return (
29
+ <time dateTime={iso} suppressHydrationWarning>
30
+ {format(value)}
31
+ </time>
32
+ );
33
+ }
34
+
35
+ function StatusBadge({ status }) {
36
+ const s = STATUS[status] ?? STATUS.pending;
37
+ return (
38
+ <Badge tone={s.tone} variant="soft">
39
+ {s.label}
40
+ </Badge>
41
+ );
42
+ }
43
+
44
+ function Requester({ requester, requestedAt, format }) {
45
+ if (!requester && !requestedAt) return null;
46
+ return (
47
+ <div className="flex min-w-0 items-center gap-2 text-sm text-muted-foreground">
48
+ {requester ? <Avatar name={requester.name} src={requester.src} size="xs" /> : null}
49
+ <p className="min-w-0">
50
+ {requester ? (
51
+ <>
52
+ <span className="font-medium text-foreground">{requester.name}</span>
53
+ {requester.role ? `, ${requester.role}` : ""}
54
+ </>
55
+ ) : null}
56
+ {requester && requestedAt ? " · " : null}
57
+ <When value={requestedAt} format={format} />
58
+ </p>
59
+ </div>
60
+ );
61
+ }
62
+
63
+ /* ------------------------------------------------------------------------
64
+ The card: facts and the decision
65
+ ------------------------------------------------------------------------ */
66
+
67
+ function DecisionCard({
68
+ title,
69
+ kind,
70
+ details,
71
+ requester,
72
+ requestedAt,
73
+ justification,
74
+ status,
75
+ decidedBy,
76
+ decidedAt,
77
+ decisionNote,
78
+ onApprove,
79
+ onReject,
80
+ reasonRequired,
81
+ approveLabel,
82
+ rejectLabel,
83
+ format,
84
+ showContext,
85
+ className,
86
+ }) {
87
+ const [local, setLocal] = useState(null);
88
+ const [mode, setMode] = useState("idle"); // idle · rejecting
89
+ const [busy, setBusy] = useState(null); // approve · reject
90
+ const [reason, setReason] = useState("");
91
+ const [error, setError] = useState(null);
92
+ const reasonId = useId();
93
+
94
+ // A new status from the app wins over what the block showed meanwhile.
95
+ useEffect(() => setLocal(null), [status]);
96
+
97
+ const shown = local?.status ?? status ?? "pending";
98
+ const pending = shown === "pending";
99
+ const facts = (details ?? []).filter(Boolean);
100
+
101
+ async function decide(kindOf) {
102
+ const fn = kindOf === "approve" ? onApprove : onReject;
103
+ if (!fn) return;
104
+ setBusy(kindOf);
105
+ setError(null);
106
+ let res;
107
+ try {
108
+ res = await fn(kindOf === "reject" ? reason.trim() : undefined);
109
+ } catch (e) {
110
+ res = { ok: false, error: e?.message };
111
+ }
112
+ setBusy(null);
113
+ if (res?.ok) {
114
+ setLocal({ status: kindOf === "approve" ? "approved" : "rejected", note: kindOf === "reject" ? reason.trim() : undefined, at: new Date() });
115
+ setMode("idle");
116
+ } else {
117
+ setError(res?.error || (kindOf === "approve" ? "The approval was not saved. Try again." : "The rejection was not saved. Try again."));
118
+ }
119
+ }
120
+
121
+ const note = local?.note ?? decisionNote;
122
+ const at = local?.at ?? decidedAt;
123
+ const by = local ? "you" : decidedBy;
124
+
125
+ return (
126
+ <section aria-label={title} className={cx("grid gap-4 rounded-lg border border-border bg-card p-4 text-card-foreground sm:p-5", className)}>
127
+ <header className="grid gap-2">
128
+ <div className="flex flex-wrap items-start justify-between gap-2">
129
+ <h2 className="min-w-0 text-lg font-semibold leading-tight">{title}</h2>
130
+ <div className="flex flex-wrap gap-1.5">
131
+ {kind ? <Badge variant="soft">{kind}</Badge> : null}
132
+ <StatusBadge status={shown} />
133
+ </div>
134
+ </div>
135
+ {showContext ? <Requester requester={requester} requestedAt={requestedAt} format={format} /> : null}
136
+ </header>
137
+
138
+ {facts.length ? (
139
+ <dl className="grid gap-4">
140
+ {facts.map((f, i) => (
141
+ <div key={f.label ?? i} className="flex items-center gap-3">
142
+ {f.icon ? (
143
+ <span className="flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
144
+ <Icon name={f.icon} size={16} />
145
+ </span>
146
+ ) : null}
147
+ <div className="grid min-w-0 gap-0.5">
148
+ <dt className="text-xs text-muted-foreground">{f.label}</dt>
149
+ <dd data-nums className={cx("min-w-0 break-words", f.emphasis ? "text-xl font-semibold" : "text-sm font-medium")}>
150
+ {f.value}
151
+ </dd>
152
+ </div>
153
+ </div>
154
+ ))}
155
+ </dl>
156
+ ) : null}
157
+
158
+ {showContext && justification ? (
159
+ <div className="grid gap-1">
160
+ <p className="text-xs text-muted-foreground">Why</p>
161
+ <p className="text-sm leading-relaxed text-foreground">{justification}</p>
162
+ </div>
163
+ ) : null}
164
+
165
+ <Separator />
166
+
167
+ {pending ? (
168
+ mode === "rejecting" ? (
169
+ <form
170
+ className="grid gap-3"
171
+ onSubmit={(e) => {
172
+ e.preventDefault();
173
+ if (reasonRequired && !reason.trim()) return;
174
+ decide("reject");
175
+ }}
176
+ >
177
+ <Field id={reasonId} label="Why is it rejected?" hint="The requester sees this." required={reasonRequired}>
178
+ <Textarea
179
+ id={reasonId}
180
+ rows={3}
181
+ value={reason}
182
+ onChange={(e) => setReason(e.target.value)}
183
+ autoFocus
184
+ disabled={busy !== null}
185
+ placeholder="Over this quarter's budget; ask again in January."
186
+ />
187
+ </Field>
188
+ <div className="flex flex-wrap justify-end gap-2">
189
+ <Button
190
+ variant="quiet"
191
+ onClick={() => {
192
+ setMode("idle");
193
+ setError(null);
194
+ }}
195
+ disabled={busy !== null}
196
+ >
197
+ Back
198
+ </Button>
199
+ <Button type="submit" variant="danger" loading={busy === "reject"} disabled={reasonRequired && !reason.trim()}>
200
+ {rejectLabel}
201
+ </Button>
202
+ </div>
203
+ </form>
204
+ ) : (
205
+ <div className="flex gap-3">
206
+ {onReject ? (
207
+ <Button
208
+ className="flex-1"
209
+ onClick={() => {
210
+ setError(null);
211
+ if (reasonRequired) setMode("rejecting");
212
+ else decide("reject");
213
+ }}
214
+ loading={busy === "reject"}
215
+ disabled={busy !== null}
216
+ >
217
+ {rejectLabel}
218
+ </Button>
219
+ ) : null}
220
+ {onApprove ? (
221
+ <Button className="flex-1" variant="primary" icon="check" onClick={() => decide("approve")} loading={busy === "approve"} disabled={busy !== null}>
222
+ {approveLabel}
223
+ </Button>
224
+ ) : null}
225
+ </div>
226
+ )
227
+ ) : (
228
+ <div role="status" className="flex items-start gap-3 text-sm">
229
+ <Icon name={shown === "approved" ? "circle-check" : "circle-x"} size={20} className={cx("mt-0.5 shrink-0", shown === "approved" ? "text-success" : "text-destructive")} />
230
+ <div className="min-w-0">
231
+ <p className="font-medium">
232
+ {shown === "approved" ? "Approved" : "Rejected"}
233
+ {by ? ` by ${by}` : ""}
234
+ {at ? (
235
+ <span className="font-normal text-muted-foreground">
236
+ {" · "}
237
+ <When value={at} format={format} />
238
+ </span>
239
+ ) : null}
240
+ </p>
241
+ {note ? <p className="mt-0.5 text-muted-foreground">{note}</p> : null}
242
+ </div>
243
+ </div>
244
+ )}
245
+
246
+ {error ? (
247
+ <Notice tone="danger" onDismiss={() => setError(null)}>
248
+ {error}
249
+ </Notice>
250
+ ) : null}
251
+ </section>
252
+ );
253
+ }
254
+
255
+ /* ------------------------------------------------------------------------
256
+ ApprovalRequest
257
+ ------------------------------------------------------------------------ */
258
+
259
+ export function ApprovalRequest({
260
+ variant = "card",
261
+ title,
262
+ kind,
263
+ details,
264
+ sections,
265
+ requester,
266
+ requestedAt,
267
+ justification,
268
+ status = "pending",
269
+ decidedBy,
270
+ decidedAt,
271
+ decisionNote,
272
+ onApprove,
273
+ onReject,
274
+ reasonRequired = true,
275
+ approveLabel = "Approve",
276
+ rejectLabel = "Reject",
277
+ heading,
278
+ description,
279
+ formatDate = defaultFormat,
280
+ loading = false,
281
+ emptyLabel = "Nothing is waiting for a decision.",
282
+ className,
283
+ }) {
284
+ const card = {
285
+ title,
286
+ kind,
287
+ details,
288
+ requester,
289
+ requestedAt,
290
+ justification,
291
+ status,
292
+ decidedBy,
293
+ decidedAt,
294
+ decisionNote,
295
+ onApprove,
296
+ onReject,
297
+ reasonRequired,
298
+ approveLabel,
299
+ rejectLabel,
300
+ format: formatDate,
301
+ };
302
+
303
+ if (loading) {
304
+ return (
305
+ <div aria-busy="true" aria-label="Loading the request" className={cx("grid w-full max-w-md gap-4 rounded-lg border border-border bg-card p-5", className)}>
306
+ <Skeleton className="w-2/3" />
307
+ {[0, 1, 2].map((i) => (
308
+ <div key={i} className="flex items-center gap-3">
309
+ <Skeleton shape="rect" className="size-8" />
310
+ <Skeleton className="w-1/2" />
311
+ </div>
312
+ ))}
313
+ <div className="flex gap-3">
314
+ <Skeleton shape="rect" className="h-11 flex-1" />
315
+ <Skeleton shape="rect" className="h-11 flex-1" />
316
+ </div>
317
+ </div>
318
+ );
319
+ }
320
+ if (!title) return <Empty icon="inbox" title="No request" body={emptyLabel} className={className} />;
321
+
322
+ if (variant !== "page") {
323
+ return <DecisionCard {...card} showContext className={cx("w-full max-w-md", className)} />;
324
+ }
325
+
326
+ const groups = (sections ?? []).filter(Boolean);
327
+ return (
328
+ <div className={cx("grid gap-8 lg:grid-cols-[minmax(0,1fr)_24rem] lg:items-start", className)}>
329
+ <div className="grid min-w-0 gap-6">
330
+ <div className="grid gap-1">
331
+ <h1 className="text-2xl font-semibold leading-tight">{heading ?? title}</h1>
332
+ {description ? <p className="text-muted-foreground">{description}</p> : null}
333
+ </div>
334
+ {groups.map((g, gi) => (
335
+ <section key={g.title ?? gi} className="grid gap-4 border-t border-border pt-6">
336
+ {g.title ? <h2 className="text-lg font-semibold">{g.title}</h2> : null}
337
+ <dl className="grid gap-4 sm:grid-cols-2">
338
+ {(g.fields ?? []).filter(Boolean).map((f, fi) => (
339
+ <div key={f.label ?? fi} className="grid min-w-0 gap-1">
340
+ <dt className="text-sm font-medium">{f.label}</dt>
341
+ <dd className={cx("min-w-0 break-words text-muted-foreground", f.emphasis && "font-semibold text-foreground")}>{f.value}</dd>
342
+ </div>
343
+ ))}
344
+ </dl>
345
+ </section>
346
+ ))}
347
+ {requester || requestedAt || justification ? (
348
+ <section className="grid gap-4 border-t border-border pt-6">
349
+ <h2 className="text-lg font-semibold">The request</h2>
350
+ <dl className="grid gap-4 sm:grid-cols-2">
351
+ {requester ? (
352
+ <div className="grid min-w-0 gap-1">
353
+ <dt className="text-sm font-medium">Requested by</dt>
354
+ <dd className="flex min-w-0 items-center gap-2 text-muted-foreground">
355
+ <Avatar name={requester.name} src={requester.src} size="xs" />
356
+ <span className="min-w-0">
357
+ {requester.name}
358
+ {requester.role ? ` (${requester.role})` : ""}
359
+ </span>
360
+ </dd>
361
+ </div>
362
+ ) : null}
363
+ {requestedAt ? (
364
+ <div className="grid gap-1">
365
+ <dt className="text-sm font-medium">Requested on</dt>
366
+ <dd className="text-muted-foreground">
367
+ <When value={requestedAt} format={formatDate} />
368
+ </dd>
369
+ </div>
370
+ ) : null}
371
+ {justification ? (
372
+ <div className="grid gap-1 sm:col-span-2">
373
+ <dt className="text-sm font-medium">Why</dt>
374
+ <dd className="text-sm leading-relaxed text-muted-foreground">{justification}</dd>
375
+ </div>
376
+ ) : null}
377
+ </dl>
378
+ </section>
379
+ ) : null}
380
+ </div>
381
+ <div className="lg:sticky lg:top-6">
382
+ <DecisionCard {...card} showContext={false} />
383
+ </div>
384
+ </div>
385
+ );
386
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "approval-request",
3
+ "title": "ApprovalRequest",
4
+ "description": "One request waiting on a decision: what is asked for as label/value facts (an amount in large type), who asked and when, why, a status badge, and Approve / Reject (reject asks for a reason). The decision goes out through async onApprove / onReject; the block shows it working, a failure, then the outcome in place of the buttons. A card alone, or a page of detail sections beside the card.",
5
+ "useWhen": "Someone must say yes or no to one thing another person asked for: a purchase, a refund, time off, a discount, an access request, a published post. Not for a queue of many requests (a data-table with row actions) or a yes/no about the founder's own action (kit Confirm).",
6
+ "tags": ["approval", "approve", "reject", "request", "review", "decision", "purchase", "expense", "refund", "time off", "sign off", "pending"],
7
+ "exports": ["ApprovalRequest"],
8
+ "files": ["index.js", "approval-request.jsx"],
9
+ "requires": []
10
+ }