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,144 @@
1
+ "use client";
2
+
3
+ import { useId } from "react";
4
+ import { Badge, ButtonGroup, Field, IconButton, RadioGroup, Select, Swatch, ToggleGroup, cx } from "../../ui";
5
+ import { formatPrice, labelOf, valuesOf } from "./price";
6
+
7
+ // One option's control. How it is drawn follows the values unless the
8
+ // option says (`display`):
9
+ // swatches values carry a `color` → colour squares, the name in the heading
10
+ // buttons up to 6 short values → a segmented row (sizes)
11
+ // select more, or longer, values → the native select
12
+ // plans values carry a `price` or a `description` → a card per value
13
+ function displayOf(option, values) {
14
+ if (option.display) return option.display;
15
+ if (values.some((v) => v.color)) return "swatches";
16
+ if (values.some((v) => typeof v.price === "number" || v.description)) return "plans";
17
+ const long = values.reduce((n, v) => n + labelOf(v).length, 0) > 30;
18
+ return values.length <= 6 && !long ? "buttons" : "select";
19
+ }
20
+
21
+ export function OptionPicker({ option, value, onChange, currency, locale }) {
22
+ const id = useId();
23
+ const values = valuesOf(option);
24
+ if (values.length === 0) return null;
25
+ const display = displayOf(option, values);
26
+ const current = values.find((v) => v.value === value);
27
+ const heading = option.label ?? option.key;
28
+
29
+ if (display === "select") {
30
+ return (
31
+ <Field id={id} label={heading}>
32
+ <Select id={id} value={value ?? ""} onChange={(e) => onChange(e.target.value)}>
33
+ {values.map((v) => (
34
+ <option key={v.value} value={v.value} disabled={v.disabled}>
35
+ {labelOf(v)}
36
+ {v.disabled ? " — sold out" : ""}
37
+ </option>
38
+ ))}
39
+ </Select>
40
+ </Field>
41
+ );
42
+ }
43
+
44
+ if (display === "plans") {
45
+ return (
46
+ <div className="grid gap-2">
47
+ <p id={`${id}-l`} className="text-sm font-medium text-foreground">
48
+ {heading}
49
+ </p>
50
+ <RadioGroup
51
+ aria-labelledby={`${id}-l`}
52
+ variant="card"
53
+ value={value ?? undefined}
54
+ onChange={onChange}
55
+ options={values.map((v) => ({
56
+ value: v.value,
57
+ disabled: v.disabled,
58
+ description: v.description,
59
+ label: (
60
+ <span className="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1">
61
+ <span className="inline-flex flex-wrap items-center gap-2">
62
+ {labelOf(v)}
63
+ {v.badge ? (
64
+ <Badge tone="primary" variant="soft">
65
+ {v.badge}
66
+ </Badge>
67
+ ) : null}
68
+ </span>
69
+ {typeof v.price === "number" ? (
70
+ <span data-nums className="font-semibold">
71
+ {formatPrice(v.price, currency, locale)}
72
+ {v.per ? <span className="text-xs font-normal text-muted-foreground"> {v.per}</span> : null}
73
+ </span>
74
+ ) : null}
75
+ </span>
76
+ ),
77
+ }))}
78
+ />
79
+ </div>
80
+ );
81
+ }
82
+
83
+ const swatches = display === "swatches";
84
+ return (
85
+ <div className="grid gap-2">
86
+ <p id={`${id}-l`} className="text-sm font-medium text-foreground">
87
+ {heading}
88
+ {swatches && current ? <span className="font-normal text-muted-foreground">: {labelOf(current)}</span> : null}
89
+ </p>
90
+ <ToggleGroup
91
+ aria-label={heading}
92
+ value={value ?? undefined}
93
+ onChange={onChange}
94
+ className={swatches ? "flex-wrap" : undefined}
95
+ items={values.map((v) => ({
96
+ value: v.value,
97
+ disabled: v.disabled,
98
+ label: swatches ? (
99
+ <Swatch color={v.color} label={`${labelOf(v)}${v.disabled ? ", sold out" : ""}`} />
100
+ ) : (
101
+ <span className={cx(v.disabled && "line-through")}>{labelOf(v)}</span>
102
+ ),
103
+ }))}
104
+ />
105
+ </div>
106
+ );
107
+ }
108
+
109
+ /** − n + as one attached control. The count is announced as it changes. */
110
+ export function QuantityControl({ value, onChange, min = 1, max = 10, disabled, label = "Quantity" }) {
111
+ const id = useId();
112
+ return (
113
+ <div className="grid gap-2">
114
+ <p id={id} className="text-sm font-medium text-foreground">
115
+ {label}
116
+ </p>
117
+ <ButtonGroup aria-labelledby={id} className="w-fit">
118
+ <IconButton
119
+ icon="minus"
120
+ label="Decrease quantity"
121
+ variant="secondary"
122
+ disabled={disabled || value <= min}
123
+ onClick={() => onChange(Math.max(min, value - 1))}
124
+ />
125
+ <output
126
+ aria-live="polite"
127
+ aria-label={`${label} ${value}`}
128
+ data-nums
129
+ className="grid min-w-12 place-items-center border border-border bg-background px-2 text-sm font-medium text-foreground"
130
+ >
131
+ {value}
132
+ </output>
133
+ <IconButton
134
+ icon="plus"
135
+ label="Increase quantity"
136
+ variant="secondary"
137
+ disabled={disabled || value >= max}
138
+ onClick={() => onChange(Math.min(max, value + 1))}
139
+ />
140
+ </ButtonGroup>
141
+ {value >= max && max > min ? <p className="text-xs text-muted-foreground">{max} is the most you can add at once.</p> : null}
142
+ </div>
143
+ );
144
+ }
@@ -0,0 +1,162 @@
1
+ # Product grid
2
+
3
+ Products as cards in a grid — picture, badge, heart, brand, name, stars,
4
+ price — with a quick **Add to cart** on each. Over the grid: facet filters,
5
+ a sort and a live count. A lead tile (a picture or a muted looping video)
6
+ can take a double cell, and `card="promo"` turns the cards into collection
7
+ tiles ("New", "Sale"). The add goes out through `onAddToCart(line)`; while
8
+ it runs the card's button spins, when it fails the card says why.
9
+
10
+ ```jsx
11
+ import { ProductGrid } from "../components/blocks/product-grid"; // a Makersclaw app ("./blocks/product-grid" from components/)
12
+ import { ProductGrid } from "@/components/makersclaw/blocks/product-grid"; // a shadcn project
13
+ ```
14
+
15
+ It is a client component: render it from a `"use client"` component, and
16
+ load the rows in the server surface (README §4). It requires
17
+ `product-detail` (added with it): the cards share its price and cart line.
18
+
19
+ ## The data
20
+
21
+ `products` are the same objects `ProductDetail` takes (see its README):
22
+ `{ id, name, price }` required; `compareAt`, `currency`, `image` (or
23
+ `images`), `brand`, `badge`, `rating`, `reviews`, `href`, `available:
24
+ false` (sold out), `options` all draw on the card when present. A product
25
+ with an option that has more than one value cannot be added blind: its
26
+ button says **Choose options** and opens it (`onOpen`, else its `href`).
27
+
28
+ Filters look for a value in three places on each product: its own field
29
+ (`product.category`, a string or a list), `product.facets[key]`, and the
30
+ values of its option with that key (so a **size** filter keeps what is
31
+ sold in that size, skipping sold-out sizes).
32
+
33
+ With `card="promo"` each item is a tile: `{ id, title, kicker?, body?,
34
+ image, href?, actionLabel?, action?: { label, href?, onClick? } }`.
35
+
36
+ ### The cart line
37
+
38
+ `onAddToCart` gets one line, the shape the `cart` block takes as an item:
39
+ `{ id, key, name, price, compareAt?, currency, image, href?, quantity: 1,
40
+ selected: {}, variant: "" }`. `key` is the product id (plus its choices on
41
+ a product page), so adding the same thing twice is one row — merge
42
+ quantities by `key`.
43
+
44
+ ## Props
45
+
46
+ - `products` — the rows. Pass `useFixture(rows, SAMPLE).rows` to show
47
+ example cards before there is data.
48
+ - `onAddToCart(line)` — return `{ ok: true }` or `{ ok: false, error }` (a
49
+ throw counts as failed). Without it the cards have no button.
50
+ - `onOpen(product)` — the card becomes a button that opens the product (a
51
+ `Sheet`, a route). A product's own `href` makes it a link instead.
52
+ - `onFavorite(product, next)` — a heart on each picture; flips at once,
53
+ flips back with the error when the save fails. `favorites` — the ids
54
+ saved now.
55
+ - `filters` — `[{ key, label, options, all?, value? }]`: one select per
56
+ facet, first choice "All …" (`all` renames it, `value` starts it set).
57
+ `options` are strings or `{ value, label }`.
58
+ - `sort` — `true` for Featured, price up, price down, top rated; or a
59
+ list of those keys (`"featured"`, `"price-asc"`, `"price-desc"`,
60
+ `"rating"`, `"newest"` by `createdAt`) and your own `{ value, label,
61
+ compare(a, b) }`. `defaultSort` — the key it starts on.
62
+ - `manual` — the loader filters and sorts (a big catalogue): the block
63
+ shows `products` as they come, reports each change through
64
+ `onQueryChange({ filters, sort })`, and counts `total`.
65
+ - `feature` — the lead tile, `{ kicker, title, body?, image | video +
66
+ poster, href | onOpen, actionLabel }`, or any node. Two cells wide (and
67
+ two tall from lg up). A video is muted and looping, has a pause, and
68
+ never plays for a reader who asks for reduced motion.
69
+ - `card` — `"product"` (default) or `"promo"`.
70
+ - `columns` — how many from lg up: `2` · `3` · `4` (default 4 for
71
+ products, 3 for tiles). A phone shows two product cards a row, one tile.
72
+ - `currency` (`"USD"`) · `locale` — for prices and counts.
73
+ - `countLabel(n)` — `"12 products"` by default. `addLabel` — the button's
74
+ words.
75
+ - `loading` — skeleton cards. `error` (a string) with `onRetry` — "Try
76
+ again". `emptyTitle` · `emptyBody` — when there are no products; when
77
+ filters hide them all it offers **Clear filters**.
78
+ - `label` — what the grid is called to a screen reader.
79
+ - `className` — layout around it (width, margin). Never colour.
80
+
81
+ `ProductCard({ product, onAddToCart, onOpen, onFavorite, favorite })` and
82
+ `PromoTile({ item, large })` are exported for a row of your own.
83
+
84
+ ## Example
85
+
86
+ ```jsx
87
+ // surfaces/shop.jsx — server: load, hand over
88
+ import { loadRows } from "../lib/data";
89
+ import Shop from "../components/Shop";
90
+
91
+ export default async function ShopSurface() {
92
+ const { rows, error } = await loadRows({ source: "public.products", orderBy: "created_at desc" });
93
+ return <Shop products={rows} error={error} />;
94
+ }
95
+ ```
96
+
97
+ ```jsx
98
+ // components/Shop.jsx — client: the grid and the cart write
99
+ "use client";
100
+ import { useRouter } from "next/navigation";
101
+ import { insertRow } from "../lib/actions";
102
+ import { ProductGrid } from "./blocks/product-grid";
103
+
104
+ export default function Shop({ products, error }) {
105
+ const router = useRouter();
106
+ return (
107
+ <ProductGrid
108
+ products={products}
109
+ error={error}
110
+ onRetry={() => router.refresh()}
111
+ filters={[
112
+ { key: "category", label: "Category", options: ["Shirts", "Sweaters", "Jackets"] },
113
+ { key: "size", label: "Size", options: ["S", "M", "L", "XL"] },
114
+ ]}
115
+ sort
116
+ onAddToCart={(line) =>
117
+ insertRow({ source: "public.cart_items", values: { product_id: line.id, line_key: line.key, quantity: 1 }, detail: line.name })
118
+ }
119
+ label="Shop"
120
+ />
121
+ );
122
+ }
123
+ ```
124
+
125
+ Collection tiles, and a lead picture beside four products:
126
+
127
+ ```jsx
128
+ <ProductGrid
129
+ card="promo"
130
+ products={[
131
+ { id: "new", kicker: "New", title: "The autumn edit", image: "/tiles/autumn.jpg", href: "/shop/new" },
132
+ { id: "sale", kicker: "Sale", title: "Summer linen", image: "/tiles/linen.jpg", href: "/shop/sale" },
133
+ ]}
134
+ label="Collections"
135
+ />
136
+
137
+ <ProductGrid
138
+ products={skincare}
139
+ feature={{ kicker: "Skincare", title: "The morning routine", image: "/hero.jpg", href: "/routine", actionLabel: "Shop the routine" }}
140
+ onAddToCart={addToCart}
141
+ />
142
+ ```
143
+
144
+ ## What it will not do
145
+
146
+ - Choose options on a card: that is the product page's job
147
+ (`product-detail`); the card sends the customer there.
148
+ - Page through a catalogue: pass a page of rows with `manual` and put the
149
+ kit's `Pagination` under it.
150
+ - Load a third-party player: a lead video is a plain `<video>` file, never
151
+ a YouTube embed or script.
152
+ - Colour itself: the tiles' words sit on the theme's background, so any
153
+ picture reads in any theme.
154
+
155
+ A catalogue it cannot be is your own component in `components/`, built
156
+ from the kit (and `ProductCard`) — not an edit to this block. Its files
157
+ are fixed: `npm run check` refuses a change, and `makersclaw add
158
+ product-grid` restores them.
159
+
160
+ ## Credits
161
+
162
+ Ported from Creative Tim UI (https://github.com/creativetimofficial/ui), MIT — a rewrite on the Makersclaw kit, none of its code, copy or pictures.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "product-grid",
3
+ "title": "Product grid",
4
+ "description": "Products as cards in a grid: picture, badge, favourite heart, brand, name, star rating, price with the old one struck through, and a quick add to cart through an async callback that may fail (\"Choose options\" when the product has sizes or colours). Facet filters as selects that also match a product's option values, a sort, a live count, a lead tile that takes a double cell (a picture or a muted looping video), and a promo card for collection tiles. Loading, error, empty and no-matches states; two columns on a phone.",
5
+ "useWhen": "A shop's catalogue, a collection page, related products under a product page, a row of promotions ('New', 'Sale'). Not for records to scan and act on in columns (data-table), one product's page (product-detail), or the cart (cart).",
6
+ "tags": ["products", "shop", "store", "ecommerce", "commerce", "catalogue", "catalog", "grid", "cards", "filter", "facets", "sort", "add to cart", "favourite", "collection", "promo", "listing", "plp"],
7
+ "exports": ["ProductGrid", "ProductCard", "PromoTile", "productMatches"],
8
+ "files": ["index.js", "product-grid.jsx", "product-card.jsx"],
9
+ "requires": ["product-detail"]
10
+ }
@@ -0,0 +1,255 @@
1
+ "use client";
2
+
3
+ // The product grid with its data in memory — the gallery's and the smoke
4
+ // test's surface. Not installed into apps: `makersclaw add product-grid`
5
+ // lays the block's files only. Each layout it was ported from is one
6
+ // choice in the switcher.
7
+ import { useState } from "react";
8
+ import { Field, Select, ToggleGroup } from "../components/ui";
9
+ import { ProductGrid } from "../components/blocks/product-grid";
10
+
11
+ const pic = (seed, w = 800, h = 800) => `https://picsum.photos/seed/${seed}/${w}/${h}`;
12
+
13
+ const PRODUCTS = [
14
+ {
15
+ id: "cardigan",
16
+ brand: "Northfold",
17
+ name: "Cable-knit merino cardigan",
18
+ category: "sweaters",
19
+ material: "wool",
20
+ price: 240,
21
+ rating: 4.6,
22
+ reviews: 58,
23
+ badge: "Exclusive",
24
+ image: pic("mc-grid-cardigan"),
25
+ options: [{ key: "size", values: ["S", "M", "L"] }],
26
+ createdAt: "2026-08-02",
27
+ },
28
+ {
29
+ id: "oxford",
30
+ brand: "Harbor & Pine",
31
+ name: "Brushed cotton oxford shirt",
32
+ category: "shirts",
33
+ material: "cotton",
34
+ price: 72,
35
+ rating: 4.2,
36
+ reviews: 131,
37
+ image: pic("mc-grid-oxford"),
38
+ createdAt: "2026-06-11",
39
+ },
40
+ {
41
+ id: "trousers",
42
+ brand: "Northfold",
43
+ name: "Wool straight trousers",
44
+ category: "trousers",
45
+ material: "wool",
46
+ price: 165,
47
+ compareAt: 210,
48
+ rating: 4.8,
49
+ reviews: 44,
50
+ badge: "Sale",
51
+ image: pic("mc-grid-trousers"),
52
+ createdAt: "2026-05-20",
53
+ },
54
+ {
55
+ id: "crewneck",
56
+ brand: "Atelier Rue",
57
+ name: "Cashmere crewneck",
58
+ category: "sweaters",
59
+ material: "cashmere",
60
+ price: 310,
61
+ rating: 5,
62
+ reviews: 12,
63
+ badge: "New",
64
+ image: pic("mc-grid-crewneck"),
65
+ options: [{ key: "size", values: ["XS", "S", { value: "M", disabled: true }] }],
66
+ createdAt: "2026-09-10",
67
+ },
68
+ {
69
+ id: "overshirt",
70
+ brand: "Harbor & Pine",
71
+ name: "Linen overshirt",
72
+ category: "shirts",
73
+ material: "linen",
74
+ price: 98,
75
+ rating: 3.9,
76
+ reviews: 27,
77
+ image: pic("mc-grid-overshirt"),
78
+ createdAt: "2026-07-01",
79
+ },
80
+ {
81
+ id: "chore",
82
+ brand: "Kiln Street",
83
+ name: "Canvas chore jacket",
84
+ category: "jackets",
85
+ material: "cotton",
86
+ price: 185,
87
+ rating: 4.4,
88
+ reviews: 90,
89
+ available: false,
90
+ image: pic("mc-grid-chore"),
91
+ createdAt: "2026-04-18",
92
+ },
93
+ {
94
+ id: "silk-scarf",
95
+ brand: "Atelier Rue",
96
+ name: "Printed silk scarf",
97
+ category: "accessories",
98
+ material: "silk",
99
+ price: 60,
100
+ rating: 4.7,
101
+ reviews: 203,
102
+ image: pic("mc-grid-scarf"),
103
+ createdAt: "2026-08-28",
104
+ },
105
+ {
106
+ id: "field-jacket",
107
+ brand: "Northfold",
108
+ name: "Waxed field jacket",
109
+ category: "jackets",
110
+ material: "cotton",
111
+ price: 280,
112
+ rating: 4.5,
113
+ reviews: 66,
114
+ image: pic("mc-grid-field"),
115
+ options: [{ key: "size", values: ["M", "L", "XL"] }],
116
+ createdAt: "2026-03-30",
117
+ },
118
+ ];
119
+
120
+ const FILTERS = [
121
+ { key: "category", label: "Category", all: "All categories", options: [{ value: "shirts", label: "Shirts" }, { value: "sweaters", label: "Sweaters" }, { value: "trousers", label: "Trousers" }, { value: "jackets", label: "Jackets" }, { value: "accessories", label: "Accessories" }] },
122
+ { key: "size", label: "Size", all: "All sizes", options: ["XS", "S", "M", "L", "XL"] },
123
+ { key: "material", label: "Material", all: "All materials", options: [{ value: "cotton", label: "Cotton" }, { value: "wool", label: "Wool" }, { value: "cashmere", label: "Cashmere" }, { value: "linen", label: "Linen" }, { value: "silk", label: "Silk" }] },
124
+ ];
125
+
126
+ const COLLECTIONS = [
127
+ { id: "new", kicker: "New", title: "The autumn edit", image: pic("mc-tile-autumn", 800, 1000), href: "#new", actionLabel: "See what's new" },
128
+ { id: "sale", kicker: "Sale", title: "Last of the summer linen", image: pic("mc-tile-linen", 800, 1000), href: "#sale", actionLabel: "Shop the sale" },
129
+ { id: "half", kicker: "Half price", title: "Knitwear, one week only", image: pic("mc-tile-knit", 800, 1000), href: "#knit", actionLabel: "Shop knitwear" },
130
+ ];
131
+
132
+ const SKINCARE = [
133
+ { id: "toner", name: "Balancing toner", price: 32, rating: 4.4, reviews: 212, image: pic("mc-skin-toner") },
134
+ { id: "serum", name: "Hydrating serum", price: 45, rating: 4.8, reviews: 540, badge: "Best seller", image: pic("mc-skin-serum") },
135
+ { id: "cream", name: "Daily moisturiser", price: 38, rating: 4.5, reviews: 318, image: pic("mc-skin-cream") },
136
+ { id: "balm", name: "Overnight lip balm", price: 16, compareAt: 20, rating: 4.1, reviews: 97, image: pic("mc-skin-balm") },
137
+ ];
138
+
139
+ const HEADPHONES = [
140
+ { id: "hp-1", brand: "Loop Audio", name: "Over-ear headphones, noise cancelling", price: 299, rating: 4, reviews: 128, badge: "New", image: pic("mc-audio-1") },
141
+ { id: "hp-2", brand: "Loop Audio", name: "Wireless earbuds", price: 149, rating: 4.3, reviews: 402, image: pic("mc-audio-2") },
142
+ { id: "hp-3", brand: "Loop Audio", name: "Bookshelf speaker pair", price: 420, compareAt: 499, rating: 4.7, reviews: 61, image: pic("mc-audio-3") },
143
+ ];
144
+
145
+ const VARIANTS = [
146
+ { value: "filters", label: "Filters, sort and count" },
147
+ { value: "tiles", label: "Collection tiles" },
148
+ { value: "promo", label: "Promotion beside products" },
149
+ { value: "spotlight", label: "Video spotlight" },
150
+ { value: "cards", label: "Product cards" },
151
+ ];
152
+
153
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
154
+
155
+ export default function ProductGridDemo() {
156
+ const [variant, setVariant] = useState("filters");
157
+ const [state, setState] = useState("ready");
158
+ const [favorites, setFavorites] = useState(["oxford"]);
159
+ const [cart, setCart] = useState([]);
160
+ const failing = state === "fails";
161
+
162
+ async function addToCart(line) {
163
+ await wait(600);
164
+ if (failing) return { ok: false, error: "The cart did not answer." };
165
+ setCart((all) => {
166
+ const hit = all.find((l) => l.key === line.key);
167
+ return hit ? all.map((l) => (l.key === line.key ? { ...l, quantity: l.quantity + 1 } : l)) : [...all, line];
168
+ });
169
+ return { ok: true };
170
+ }
171
+ async function favorite(product, next) {
172
+ await wait(300);
173
+ if (failing) return { ok: false, error: "Favourites are not saving." };
174
+ setFavorites((all) => (next ? [...all, product.id] : all.filter((id) => id !== product.id)));
175
+ return { ok: true };
176
+ }
177
+ const open = () => {};
178
+
179
+ const common = {
180
+ loading: state === "loading",
181
+ error: state === "error" ? "The catalogue did not answer." : undefined,
182
+ onRetry: () => setState("ready"),
183
+ onAddToCart: addToCart,
184
+ onFavorite: favorite,
185
+ favorites,
186
+ onOpen: open,
187
+ };
188
+ const pick = (list) => (state === "empty" ? [] : list);
189
+ const count = cart.reduce((n, l) => n + l.quantity, 0);
190
+
191
+ let grid;
192
+ if (variant === "tiles") {
193
+ grid = <ProductGrid key="tiles" card="promo" products={pick(COLLECTIONS)} {...common} label="Collections" emptyTitle="No collections yet" />;
194
+ } else if (variant === "promo") {
195
+ grid = (
196
+ <ProductGrid
197
+ key="promo"
198
+ products={pick(SKINCARE)}
199
+ columns={4}
200
+ feature={{ kicker: "Skincare", title: "Glow, from plants up", body: "Four steps, morning and night.", image: pic("mc-skin-hero", 1200, 1200), href: "#skincare", actionLabel: "Shop the routine" }}
201
+ {...common}
202
+ label="Skincare"
203
+ />
204
+ );
205
+ } else if (variant === "spotlight") {
206
+ grid = (
207
+ <ProductGrid
208
+ key="spotlight"
209
+ products={pick(HEADPHONES)}
210
+ columns={3}
211
+ feature={{
212
+ kicker: "In the studio",
213
+ title: "Sound you can work in",
214
+ video: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
215
+ poster: pic("mc-audio-hero", 1200, 900),
216
+ href: "#audio",
217
+ actionLabel: "See all audio",
218
+ }}
219
+ {...common}
220
+ label="Audio"
221
+ />
222
+ );
223
+ } else if (variant === "cards") {
224
+ grid = <ProductGrid key="cards" products={pick(HEADPHONES)} columns={3} {...common} label="Headphones" />;
225
+ } else {
226
+ grid = <ProductGrid key="filters" products={pick(PRODUCTS)} filters={FILTERS} sort={["featured", "price-asc", "price-desc", "rating", "newest"]} {...common} label="Menswear" />;
227
+ }
228
+
229
+ return (
230
+ <div className="grid gap-6">
231
+ <div className="flex flex-wrap items-end gap-3">
232
+ <Field id="pg-variant" label="Layout" className="w-full sm:w-64">
233
+ <Select id="pg-variant" value={variant} onChange={(e) => setVariant(e.target.value)} options={VARIANTS} />
234
+ </Field>
235
+ <ToggleGroup
236
+ size="sm"
237
+ aria-label="Demo state"
238
+ value={state}
239
+ onChange={setState}
240
+ items={[
241
+ { value: "ready", label: "Ready" },
242
+ { value: "fails", label: "Fails" },
243
+ { value: "loading", label: "Loading" },
244
+ { value: "error", label: "Error" },
245
+ { value: "empty", label: "Empty" },
246
+ ]}
247
+ />
248
+ <p data-nums className="text-sm text-muted-foreground sm:ml-auto">
249
+ Cart: {count} {count === 1 ? "item" : "items"}
250
+ </p>
251
+ </div>
252
+ {grid}
253
+ </div>
254
+ );
255
+ }
@@ -0,0 +1,5 @@
1
+ // The Product grid block — `makersclaw add product-grid`. Fixed: compose
2
+ // it through its props (README.md beside this file); a catalogue it cannot
3
+ // be is your own component in components/.
4
+ export { ProductGrid, productMatches } from "./product-grid";
5
+ export { ProductCard, PromoTile } from "./product-card";