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,271 @@
1
+ "use client";
2
+
3
+ import { useId } from "react";
4
+ import { Button, Checkbox, Icon, IconButton, InputGroup, Menu, Popover, Switch, cx } from "../../ui";
5
+ import { DEFAULT_VIEW, NONE, activeFilterCount, createTaskContext, groupOptions, optionsOf, sortOptions, valuesOf } from "./model";
6
+
7
+ // ViewToolbar — the one row above every task view: search, filter,
8
+ // group by, sort, show fields, and your own button at the end. It edits a
9
+ // view object ({ search, filters, groupBy, sort, fields, hideDone }) and
10
+ // hands the next one to `onViewChange`; the view applies it with
11
+ // applyView(). Active filters show as chips under the row, each with its
12
+ // own ×, and "Clear" takes them all off.
13
+ //
14
+ // On a phone the search takes the first line and the controls become
15
+ // icons on the second; nothing scrolls sideways.
16
+
17
+ const ctxOf = (ctx) => (ctx && ctx.statusById ? ctx : createTaskContext(ctx ?? {}));
18
+
19
+ const FILTER_KINDS = new Set(["status", "people", "priority", "project", "tags", "date", "select", "checkbox"]);
20
+ const SHOWABLE = ["status", "assignees", "due", "start", "priority", "project", "tags", "estimate", "progress"];
21
+
22
+ export function ViewToolbar({
23
+ view: viewProp,
24
+ onViewChange,
25
+ ctx,
26
+ tasks = [],
27
+ controls = ["search", "filter", "group", "sort", "fields"],
28
+ filterFields,
29
+ groupFields,
30
+ showableFields,
31
+ searchPlaceholder = "Search tasks",
32
+ count,
33
+ extra,
34
+ className,
35
+ }) {
36
+ const c = ctxOf(ctx);
37
+ const uid = useId();
38
+ const view = { ...DEFAULT_VIEW, ...viewProp };
39
+ const set = (patch) => onViewChange?.({ ...view, ...patch });
40
+ const has = (k) => controls.includes(k);
41
+
42
+ const filterable = c.fields.filter(
43
+ (f) =>
44
+ FILTER_KINDS.has(f.kind) &&
45
+ (filterFields ? filterFields.includes(f.key) : f.key !== "start") &&
46
+ optionsOf(f.key, c, tasks).some((o) => !o.none),
47
+ );
48
+ const groups = groupOptions(c).filter((g) => !groupFields || g.key === "none" || groupFields.includes(g.key));
49
+ const sorts = sortOptions(c);
50
+ const showable = c.fields.filter((f) => (showableFields ?? [...SHOWABLE, ...c.fields.filter((x) => x.custom).map((x) => x.key)]).includes(f.key));
51
+ const active = activeFilterCount(view);
52
+ const groupLabel = groups.find((g) => g.key === (view.groupBy ?? "none"))?.label ?? "None";
53
+ const sort = view.sort?.[0];
54
+ const sortLabel = sort ? sorts.find((s) => s.key === sort.key)?.label ?? sort.key : "Manual";
55
+
56
+ const toggleFilter = (key, value, on) => {
57
+ const now = new Set(view.filters?.[key] ?? []);
58
+ if (on) now.add(value);
59
+ else now.delete(value);
60
+ const filters = { ...view.filters, [key]: [...now] };
61
+ if (!filters[key].length) delete filters[key];
62
+ set({ filters });
63
+ };
64
+
65
+ // How many tasks each filter choice holds, among all tasks.
66
+ const counts = (key) => {
67
+ const m = new Map();
68
+ for (const t of tasks) for (const v of valuesOf(t, key, c)) m.set(v, (m.get(v) ?? 0) + 1);
69
+ return m;
70
+ };
71
+
72
+ const chips = [];
73
+ for (const [key, values] of Object.entries(view.filters ?? {})) {
74
+ if (!values?.length) continue;
75
+ const field = c.fields.find((f) => f.key === key);
76
+ const opts = optionsOf(key, c, tasks);
77
+ const words = values.map((v) => opts.find((o) => o.id === v)?.label ?? (v === NONE ? "None" : v));
78
+ chips.push({ key, label: `${field?.label ?? key}: ${words.join(", ")}` });
79
+ }
80
+ if (view.hideDone) chips.push({ key: "__done", label: "Done hidden" });
81
+
82
+ return (
83
+ <div className={cx("grid min-w-0 grid-cols-1 gap-2", className)}>
84
+ <div className="flex flex-wrap items-center gap-2">
85
+ {has("search") ? (
86
+ <div className="min-w-0 basis-full sm:max-w-72 sm:flex-1 sm:basis-auto">
87
+ <label htmlFor={`${uid}-q`} className="sr-only">
88
+ {searchPlaceholder}
89
+ </label>
90
+ <InputGroup
91
+ id={`${uid}-q`}
92
+ icon="search"
93
+ type="search"
94
+ value={view.search ?? ""}
95
+ placeholder={searchPlaceholder}
96
+ onChange={(e) => set({ search: e.target.value })}
97
+ onKeyDown={(e) => {
98
+ if (e.key === "Escape" && view.search) {
99
+ e.preventDefault();
100
+ set({ search: "" });
101
+ }
102
+ }}
103
+ action={view.search ? { label: "Clear search", icon: "x", onClick: () => set({ search: "" }) } : undefined}
104
+ />
105
+ </div>
106
+ ) : null}
107
+ <div className="flex min-w-0 flex-1 items-center gap-1">
108
+ {has("filter") ? (
109
+ <Popover
110
+ label="Filter tasks"
111
+ width="md"
112
+ align="start"
113
+ variant={active ? "secondary" : "quiet"}
114
+ size="sm"
115
+ className="max-h-[min(70vh,32rem)] overflow-y-auto p-0"
116
+ trigger={
117
+ <span className="inline-flex items-center gap-1.5">
118
+ <Icon name="filter" size={16} />
119
+ <span className="sr-only sm:not-sr-only">Filter</span>
120
+ {active ? (
121
+ <span data-nums className="rounded-full bg-primary px-1.5 text-2xs font-semibold text-primary-foreground">
122
+ <span className="sr-only">, </span>
123
+ {active}
124
+ <span className="sr-only"> on</span>
125
+ </span>
126
+ ) : null}
127
+ </span>
128
+ }
129
+ >
130
+ <div className="grid divide-y divide-border">
131
+ {filterable.map((f) => {
132
+ const opts = optionsOf(f.key, c, tasks).filter((o) => o.id !== "past");
133
+ const n = counts(f.key);
134
+ const chosen = new Set(view.filters?.[f.key] ?? []);
135
+ return (
136
+ <fieldset key={f.key} className="grid gap-0.5 px-3 py-2">
137
+ <legend className="float-left mb-1 w-full pt-1 text-xs font-medium text-muted-foreground">{f.label}</legend>
138
+ {opts.map((o) => (
139
+ <div key={o.id} className="flex items-center justify-between gap-3">
140
+ <Checkbox
141
+ id={`${uid}-${f.key}-${o.id}`}
142
+ label={o.label}
143
+ checked={chosen.has(o.id)}
144
+ onChange={(e) => toggleFilter(f.key, o.id, e.target.checked)}
145
+ className="min-w-0 flex-1"
146
+ />
147
+ <span data-nums className="text-xs text-muted-foreground">
148
+ {n.get(o.id) ?? 0}
149
+ </span>
150
+ </div>
151
+ ))}
152
+ </fieldset>
153
+ );
154
+ })}
155
+ <div className="px-3 py-1">
156
+ <Switch id={`${uid}-done`} label="Hide done tasks" checked={Boolean(view.hideDone)} onChange={(e) => set({ hideDone: e.target.checked })} />
157
+ </div>
158
+ </div>
159
+ </Popover>
160
+ ) : null}
161
+ {has("group") ? (
162
+ <Menu
163
+ label={`Group by ${groupLabel}`}
164
+ align="start"
165
+ trigger={
166
+ <span className="inline-flex items-center gap-1.5">
167
+ <Icon name="layers" size={16} />
168
+ <span className="hidden sm:inline">
169
+ Group<span className="text-muted-foreground">: {groupLabel}</span>
170
+ </span>
171
+ </span>
172
+ }
173
+ items={[
174
+ { type: "label", label: "Group by" },
175
+ { type: "radio", value: view.groupBy ?? "none", onValueChange: (v) => set({ groupBy: v }), options: groups.map((g) => ({ value: g.key, label: g.label })) },
176
+ ]}
177
+ />
178
+ ) : null}
179
+ {has("sort") ? (
180
+ <Menu
181
+ label={`Sort by ${sortLabel}`}
182
+ align="start"
183
+ trigger={
184
+ <span className="inline-flex items-center gap-1.5">
185
+ <Icon name="chevrons-up-down" size={16} />
186
+ <span className="hidden sm:inline">
187
+ Sort<span className="text-muted-foreground">: {sortLabel}</span>
188
+ </span>
189
+ </span>
190
+ }
191
+ items={[
192
+ { type: "label", label: "Sort by" },
193
+ {
194
+ type: "radio",
195
+ value: sort?.key ?? "manual",
196
+ onValueChange: (v) => set({ sort: v === "manual" ? [] : [{ key: v, dir: sort?.dir ?? "asc" }] }),
197
+ options: sorts.map((s) => ({ value: s.key, label: s.label })),
198
+ },
199
+ sort && { type: "separator" },
200
+ sort && {
201
+ type: "radio",
202
+ value: sort.dir,
203
+ onValueChange: (dir) => set({ sort: [{ key: sort.key, dir }] }),
204
+ options: [
205
+ { value: "asc", label: "Ascending" },
206
+ { value: "desc", label: "Descending" },
207
+ ],
208
+ },
209
+ ]}
210
+ />
211
+ ) : null}
212
+ {has("fields") ? (
213
+ <Menu
214
+ label="Show fields"
215
+ align="start"
216
+ trigger={
217
+ <span className="inline-flex items-center gap-1.5">
218
+ <Icon name="eye" size={16} />
219
+ <span className="hidden sm:inline">Fields</span>
220
+ </span>
221
+ }
222
+ items={[
223
+ { type: "label", label: "Show on each task" },
224
+ ...showable.map((f) => ({
225
+ type: "checkbox",
226
+ label: f.label,
227
+ checked: (view.fields ?? []).includes(f.key),
228
+ onCheckedChange: (on) => set({ fields: on ? [...(view.fields ?? []), f.key] : (view.fields ?? []).filter((k) => k !== f.key) }),
229
+ })),
230
+ ]}
231
+ />
232
+ ) : null}
233
+ {typeof count === "number" ? (
234
+ <span data-nums className="ms-1 hidden text-xs text-muted-foreground md:inline">
235
+ {count} {count === 1 ? "task" : "tasks"}
236
+ </span>
237
+ ) : null}
238
+ {extra ? <div className="ms-auto flex shrink-0 items-center gap-2">{extra}</div> : null}
239
+ </div>
240
+ </div>
241
+ {chips.length ? (
242
+ <ul className="flex flex-wrap items-center gap-1.5" aria-label="Filters on">
243
+ {chips.map((chip) => (
244
+ <li key={chip.key} className="inline-flex max-w-full items-center rounded-full border border-border bg-card ps-3 text-xs text-foreground">
245
+ <span className="truncate">{chip.label}</span>
246
+ <IconButton
247
+ icon="x"
248
+ size="sm"
249
+ label={`Remove filter ${chip.label}`}
250
+ className="-my-1 rounded-full"
251
+ onClick={() => {
252
+ if (chip.key === "__done") set({ hideDone: false });
253
+ else {
254
+ const filters = { ...view.filters };
255
+ delete filters[chip.key];
256
+ set({ filters });
257
+ }
258
+ }}
259
+ />
260
+ </li>
261
+ ))}
262
+ <li>
263
+ <Button variant="link" size="sm" tone="muted" onClick={() => set({ filters: {}, hideDone: false })}>
264
+ Clear filters
265
+ </Button>
266
+ </li>
267
+ </ul>
268
+ ) : null}
269
+ </div>
270
+ );
271
+ }
@@ -0,0 +1,139 @@
1
+ # Testimonials
2
+
3
+ A marketing section of customer quotes. Each quote carries who said it
4
+ (name, role, company, a face or a logo), an optional star rating drawn
5
+ with the kit's `Rating`, an optional verified mark and "View on X"
6
+ source, and an optional link to the full story. Headline numbers
7
+ (`stats`) sit above the cards, or beside a single quote. Five layouts
8
+ over the same rows: a **grid** of cards, a **single** large quote, a
9
+ **switcher** (press a face to swap the quote), and a **carousel** (swipe,
10
+ arrow keys, buttons, dots), optionally in a panel or over a picture. It
11
+ is a full-width section: it pads itself and centres its content.
12
+
13
+ ```jsx
14
+ import { Testimonials } from "../components/blocks/testimonials"; // a Makersclaw app ("./blocks/testimonials" from components/)
15
+ import { Testimonials } from "@/components/makersclaw/blocks/testimonials"; // a shadcn project
16
+ ```
17
+
18
+ It is a client component: render it from a `"use client"` component.
19
+
20
+ ## The data
21
+
22
+ `items` is the quotes, in order:
23
+
24
+ ```js
25
+ {
26
+ quote: "We closed the books four days faster…", // required; a row without one is skipped
27
+ name: "Maya Okafor", // required
28
+ id?: "maya", // a stable key
29
+ role?: "Head of Operations", company?: "Greenhaus", // shown as "role, company"
30
+ avatar?: "/faces/maya.jpg", // initials while it loads, and when it fails
31
+ logo?: <GreenhausLogo />, // a node: the company's mark, above the quote
32
+ rating?: 4.5, // 0–5, halves drawn; no rating, no stars
33
+ date?: "12 Aug 2026", // already formatted
34
+ verified?: true, // a check after the name
35
+ source?: { network: "x", href: "https://x.com/…", label? }, // "View on X" + the brand glyph
36
+ href?: "/customers/greenhaus", hrefLabel?: "Read the story", // a link under the quote
37
+ title?: "From a week of month-end to an afternoon", // single: the heading
38
+ image?: "/stories/greenhaus.jpg", imageAlt?: "", // single and switcher: a photo beside the quote
39
+ highlight?: true, // grid: a primary ring round this card
40
+ wide?: true, // grid: this card spans the row
41
+ }
42
+ ```
43
+
44
+ `source.network` is one of `x`, `linkedin`, `instagram`, `youtube`,
45
+ `facebook`, `github`, `google`; anything else shows `label` and a link
46
+ glyph.
47
+
48
+ ## Props
49
+
50
+ - `items` — the quotes, as above. Required.
51
+ - `layout` — `grid` (default) · `single` (the first quote, or the one at
52
+ `defaultIndex`) · `switcher` · `carousel`.
53
+ - `kicker`, `title`, `description` — the header. In `single` and
54
+ `switcher` the title sits beside the quote (an item's own `title` wins
55
+ in `single`).
56
+ - `align` — the header: `center` (default for grid and carousel) ·
57
+ `start` (default for single and switcher).
58
+ - `stats` — `[{ label, value, unit?, caption? }]`, values already
59
+ formatted ("4,200+", "4.8" with unit "/ 5"). A strip of kit `Stat`s
60
+ under the header; in `single` they take the picture's place, beside the
61
+ quote.
62
+ - `columns` — the grid from `lg` up: `1` · `2` · `3` (default) · `4`. One
63
+ column on a phone, two from `sm`.
64
+ - `look` — each card: `card` (default: border and card fill) · `raised`
65
+ (plus a shadow) · `plain` (no box; quiet text). In `single` and
66
+ `carousel`, `plain` drops the panel round it.
67
+ - `cardAlign` — `start` (default) · `center`.
68
+ - `byline` — `bottom` (default: stars, quote, then the person) · `top`
69
+ (the person first, stars last).
70
+ - `quoteMark` — `true` draws a quote glyph above each quote. Default
71
+ `false`.
72
+ - `focusOnHover` — `true`: the card under the pointer stays lit and the
73
+ rest dim. Decoration only; nothing is selected. Default `false`.
74
+ - `action` — `{ label, onClick?, href?, icon? }`: "Write a review". A
75
+ dashed tile after the cards in `grid`, a button in `single` and
76
+ `carousel`, and the way forward in the empty state.
77
+ - `background`, `backgroundAlt` — `carousel` only: a picture behind the
78
+ slides, under a veil of the background colour so the text reads in
79
+ every theme.
80
+ - `defaultIndex` — the quote `single` and `switcher` open on. Default `0`.
81
+ - `onIndexChange(index)` — the switcher's pick, or the carousel's
82
+ settled slide.
83
+ - `loading` — `true` draws three skeleton cards (the region is
84
+ `aria-busy`).
85
+ - `empty` — `{ title?, body? }` for the empty state (no `items`). Default
86
+ "No reviews yet".
87
+ - `label` — what a screen reader calls the section. Default the title.
88
+ - `className` — the section's spacing and width. Never colour.
89
+
90
+ ## Example
91
+
92
+ ```jsx
93
+ // components/Proof.jsx
94
+ "use client";
95
+ import { Testimonials } from "./blocks/testimonials";
96
+
97
+ const QUOTES = [
98
+ { id: "maya", name: "Maya Okafor", role: "Head of Operations", company: "Greenhaus", rating: 5,
99
+ quote: "We closed the books four days faster in the first month." },
100
+ { id: "tomas", name: "Tomás Berg", role: "Founder", company: "Northwind Freight", rating: 4.5,
101
+ quote: "Every quote we send now carries its own margin." },
102
+ { id: "priya", name: "Priya Raman", role: "Customer Lead", company: "Loop Studio", rating: 5,
103
+ quote: "Support replies went from a day to under an hour." },
104
+ ];
105
+
106
+ export default function Proof() {
107
+ return (
108
+ <Testimonials
109
+ kicker="Customers"
110
+ title="Loved by small teams"
111
+ description="Operators, founders and support leads on what changed."
112
+ items={QUOTES}
113
+ stats={[
114
+ { label: "Teams onboarded", value: "4,200+" },
115
+ { label: "Average rating", value: "4.8", unit: "/ 5" },
116
+ { label: "Hours saved a month", value: "31" },
117
+ ]}
118
+ />
119
+ );
120
+ }
121
+ ```
122
+
123
+ ## What it will not do
124
+
125
+ - Fetch reviews or take one in: `action` hands off, and the form is
126
+ yours (a `Sheet` with a `Rating` input, saved through your own action).
127
+ - Colour a card by brand: a `highlight` is the theme's primary ring.
128
+ - Autoplay: the carousel moves when the reader moves it.
129
+ - Draw a company's logo from a URL: pass the logo as a node.
130
+
131
+ A section it cannot be is your own component in `components/`, built
132
+ from the kit — not an edit to this block. Its files are fixed: `npm run
133
+ check` refuses a change, and `makersclaw add testimonials` restores them.
134
+
135
+ ## Credits
136
+
137
+ Layouts ported from Creative Tim UI's testimonials blocks
138
+ (https://github.com/creativetimofficial/ui, MIT), rewritten on the
139
+ Makersclaw kit.
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "testimonials",
3
+ "title": "Testimonials",
4
+ "description": "A marketing section of customer quotes: name, role, company, face or logo, the quote, an optional star rating, a verified mark and a \"view on X\" source, and optional headline numbers (stats). Layouts: a grid of cards (plain, card or raised; hover can light one and dim the rest; a \"write a review\" tile), one large quote, a switcher of faces, and a carousel, optionally over a picture.",
5
+ "useWhen": "Social proof on a public page: a landing page, a pricing page, a product page, a case-study teaser. Not for reviews a signed-in user writes and manages (a record list or form), or an app's own activity feed.",
6
+ "tags": ["testimonials", "reviews", "quotes", "social proof", "customers", "rating", "stars", "stats", "carousel", "marketing", "landing page", "case study"],
7
+ "exports": ["Testimonials"],
8
+ "files": ["index.js", "testimonials.jsx"],
9
+ "requires": [],
10
+ "frame": "bleed"
11
+ }
@@ -0,0 +1,137 @@
1
+ "use client";
2
+
3
+ // Testimonials in every variant — the gallery's and the smoke test's
4
+ // surface. Not installed into apps: `makersclaw add testimonials` lays
5
+ // index.js and testimonials.jsx only. Pick a variant and a state; the
6
+ // "write a review" tile only counts its presses here.
7
+ import { useState } from "react";
8
+ import { Field, Icon, Select, ToggleGroup } from "../components/ui";
9
+ import { Testimonials } from "../components/blocks/testimonials";
10
+
11
+ function Wordmark({ icon, name }) {
12
+ return (
13
+ <span className="inline-flex items-center gap-2 text-lg font-semibold tracking-tight text-muted-foreground">
14
+ <Icon name={icon} size={22} />
15
+ {name}
16
+ </span>
17
+ );
18
+ }
19
+
20
+ const PEOPLE = [
21
+ {
22
+ id: "maya",
23
+ name: "Maya Okafor",
24
+ role: "Head of Operations",
25
+ company: "Greenhaus",
26
+ logo: <Wordmark icon="leaf" name="Greenhaus" />,
27
+ quote: "We closed the books four days faster in the first month. The team stopped chasing receipts and started reading the numbers.",
28
+ rating: 5,
29
+ date: "12 Aug 2026",
30
+ title: "From a week of month-end to an afternoon",
31
+ },
32
+ {
33
+ id: "tomas",
34
+ name: "Tomás Berg",
35
+ role: "Founder",
36
+ company: "Northwind Freight",
37
+ logo: <Wordmark icon="truck" name="Northwind" />,
38
+ quote: "Every quote we send now carries its own margin. I can see which lanes pay before we say yes, not three weeks after.",
39
+ rating: 4.5,
40
+ date: "3 Aug 2026",
41
+ },
42
+ {
43
+ id: "priya",
44
+ name: "Priya Raman",
45
+ role: "Customer Lead",
46
+ company: "Loop Studio",
47
+ logo: <Wordmark icon="layers" name="Loop Studio" />,
48
+ quote: "Support replies went from a day to under an hour. Customers noticed before we announced anything.",
49
+ rating: 5,
50
+ date: "28 Jul 2026",
51
+ },
52
+ {
53
+ id: "daniel",
54
+ name: "Daniel Cho",
55
+ role: "CTO",
56
+ company: "Brightpath",
57
+ logo: <Wordmark icon="zap" name="Brightpath" />,
58
+ quote: "Setup took an afternoon and nothing has broken since. That is the whole review.",
59
+ rating: 4,
60
+ date: "19 Jul 2026",
61
+ },
62
+ ];
63
+
64
+ const HANDLES = { maya: "@mayaops", tomas: "@tomasberg", priya: "@priyaraman", daniel: "@dcho" };
65
+
66
+ const withSource = PEOPLE.slice(0, 3).map((p) => ({
67
+ ...p,
68
+ role: HANDLES[p.id],
69
+ company: undefined,
70
+ verified: true,
71
+ source: { network: "x", href: "https://x.com" },
72
+ }));
73
+ const noRating = PEOPLE.map(({ rating, ...p }) => p);
74
+ const noLogo = PEOPLE.map(({ logo, ...p }) => p);
75
+ const STATS = [
76
+ { label: "Teams onboarded", value: "4,200+" },
77
+ { label: "Average rating", value: "4.8", unit: "/ 5" },
78
+ { label: "Hours saved a month", value: "31" },
79
+ ];
80
+
81
+ const COMMON = { kicker: "Customers", title: "Loved by small teams", description: "Operators, founders and support leads on what changed after the switch." };
82
+
83
+ const VARIANTS = [
84
+ { id: "01", label: "01 · Grid, avatars", props: { ...COMMON, items: noLogo.map(({ rating, ...p }) => p).slice(0, 3) } },
85
+ { id: "02", label: "02 · Grid, verified and on X", props: { ...COMMON, align: "start", items: withSource.map(({ logo, rating, ...p }) => p) } },
86
+ { id: "03", label: "03 · Grid, numbers and stars", props: { ...COMMON, items: noLogo.slice(0, 3), stats: STATS, quoteMark: true } },
87
+ { id: "04", label: "04 · Three columns, stars", props: { ...COMMON, kicker: undefined, items: noLogo.slice(0, 3) } },
88
+ { id: "05", label: "05 · Stars, byline first", props: { ...COMMON, items: noLogo.slice(0, 3), byline: "top" } },
89
+ { id: "06", label: "06 · One quote, logo", props: { kicker: "Customer story", items: [{ ...PEOPLE[1], title: "Every lane priced before we say yes", rating: undefined }], look: "plain" } },
90
+ { id: "07", label: "07 · Switcher", props: { layout: "switcher", title: "What operators say", items: noLogo } },
91
+ { id: "08", label: "08 · Plain, stars", props: { ...COMMON, items: noLogo.slice(0, 3), look: "plain" } },
92
+ { id: "09", label: "09 · Customer story", props: { layout: "single", kicker: "Customer story", items: [PEOPLE[0]] } },
93
+ { id: "10", label: "10 · Logos, centred", props: { ...COMMON, items: noRating.slice(0, 3).map((p) => ({ ...p, href: "/customers" })), look: "plain", cardAlign: "center" } },
94
+ { id: "11", label: "11 · Hover lights one", props: { ...COMMON, items: noLogo.slice(0, 3).map((p, i) => ({ ...p, highlight: i === 1 })), byline: "top", focusOnHover: true } },
95
+ { id: "12", label: "12 · Logos, two columns", props: { ...COMMON, columns: 2, items: noRating.slice(0, 3).map((p, i) => ({ ...p, wide: i === 2 })) } },
96
+ { id: "13", label: "13 · One card", props: { items: [{ ...noLogo[2] }] } },
97
+ { id: "14", label: "14 · Raised cards", props: { ...COMMON, items: noLogo.slice(0, 3).map(({ rating, ...p }) => p), look: "raised" } },
98
+ { id: "15", label: "15 · Write a review", props: { ...COMMON, columns: 4, items: noLogo.slice(0, 3), cardAlign: "center", byline: "top", action: { label: "Write a review" } } },
99
+ { id: "16", label: "16 · Carousel", props: { ...COMMON, layout: "carousel", look: "plain", items: noRating } },
100
+ // 17 sits over a photo in an app (`background`); the gallery has no photos, so it shows the panel.
101
+ { id: "17", label: "17 · Carousel in a panel", props: { layout: "carousel", items: noLogo } },
102
+ ];
103
+
104
+ const STATES = [
105
+ { value: "filled", label: "Filled" },
106
+ { value: "loading", label: "Loading" },
107
+ { value: "empty", label: "Empty" },
108
+ ];
109
+
110
+ export default function TestimonialsDemo() {
111
+ const [variant, setVariant] = useState("03");
112
+ const [state, setState] = useState("filled");
113
+ const [asks, setAsks] = useState(0);
114
+ const v = VARIANTS.find((x) => x.id === variant) ?? VARIANTS[0];
115
+ const props = { ...v.props };
116
+ // 06 and 13 are one quote: the "single" layout.
117
+ if (v.id === "06" || v.id === "13") props.layout = "single";
118
+ if (v.id === "13") props.look = "card";
119
+ if (state === "empty") props.items = [];
120
+ // An action on every variant's empty state, so there is a way forward.
121
+ const onReview = () => setAsks((n) => n + 1);
122
+ if (props.action) props.action = { ...props.action, onClick: onReview };
123
+ else if (state === "empty") props.action = { label: "Ask a customer", icon: "send", onClick: onReview };
124
+
125
+ return (
126
+ <div className="grid gap-2">
127
+ <div className="flex flex-wrap items-end gap-3 px-4 pt-4 sm:px-6">
128
+ <Field id="t-variant" label="Variant" className="w-full sm:w-72">
129
+ <Select id="t-variant" value={variant} onChange={(e) => setVariant(e.target.value)} options={VARIANTS.map((x) => ({ value: x.id, label: x.label }))} />
130
+ </Field>
131
+ <ToggleGroup aria-label="State" items={STATES} value={state} onChange={setState} />
132
+ {asks ? <p className="pb-3 text-sm text-muted-foreground">Review asked for {asks}×</p> : null}
133
+ </div>
134
+ <Testimonials key={`${variant}-${state}`} {...props} loading={state === "loading"} />
135
+ </div>
136
+ );
137
+ }
@@ -0,0 +1,4 @@
1
+ // The Testimonials block — `makersclaw add testimonials`. Fixed: compose
2
+ // it through its props (README.md beside this file); a section it cannot
3
+ // be is your own component in components/.
4
+ export { Testimonials } from "./testimonials";