makersclaw 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -1
  3. package/THIRD-PARTY-NOTICES.md +180 -0
  4. package/package.json +15 -8
  5. package/r/annotate.json +62 -0
  6. package/r/approval-request.json +52 -0
  7. package/r/audio-player.json +74 -0
  8. package/r/auth-form.json +55 -0
  9. package/r/board.json +55 -0
  10. package/r/calendar-view.json +105 -0
  11. package/r/cart.json +62 -0
  12. package/r/chart.json +83 -0
  13. package/r/chat.json +95 -0
  14. package/r/code-editor.json +94 -0
  15. package/r/comment-box.json +64 -0
  16. package/r/contact-section.json +53 -0
  17. package/r/core.json +341 -0
  18. package/r/csv-import.json +63 -0
  19. package/r/data-table.json +69 -0
  20. package/r/diagram.json +74 -0
  21. package/r/doc-editor.json +82 -0
  22. package/r/doc-page.json +61 -0
  23. package/r/email-render.json +73 -0
  24. package/r/faq.json +50 -0
  25. package/r/file-upload.json +54 -0
  26. package/r/flow-canvas.json +93 -0
  27. package/r/footer.json +52 -0
  28. package/r/gantt.json +70 -0
  29. package/r/job-panel.json +56 -0
  30. package/r/json-editor.json +66 -0
  31. package/r/map.json +89 -0
  32. package/r/menubar.json +52 -0
  33. package/r/mind-map.json +67 -0
  34. package/r/navigation-menu.json +52 -0
  35. package/r/order-detail.json +54 -0
  36. package/r/org-chart.json +66 -0
  37. package/r/page-builder.json +105 -0
  38. package/r/payment-methods.json +51 -0
  39. package/r/pdf-document.json +79 -0
  40. package/r/pdf-viewer.json +88 -0
  41. package/r/product-detail.json +76 -0
  42. package/r/product-grid.json +65 -0
  43. package/r/record-form.json +67 -0
  44. package/r/record-notes.json +55 -0
  45. package/r/registry.json +3612 -0
  46. package/r/search-dialog.json +51 -0
  47. package/r/settings-list.json +66 -0
  48. package/r/setup-checklist.json +51 -0
  49. package/r/share-dialog.json +52 -0
  50. package/r/sidebar.json +69 -0
  51. package/r/signature-pad.json +72 -0
  52. package/r/sketch-canvas.json +99 -0
  53. package/r/spreadsheet.json +90 -0
  54. package/r/stat-cards.json +66 -0
  55. package/r/task-list.json +63 -0
  56. package/r/task-model.json +98 -0
  57. package/r/testimonials.json +52 -0
  58. package/r/transaction-list.json +53 -0
  59. package/r/whiteboard.json +66 -0
  60. package/registry/blocks/annotate/README.md +179 -0
  61. package/registry/blocks/annotate/annotate-data.js +250 -0
  62. package/registry/blocks/annotate/annotate.jsx +646 -0
  63. package/registry/blocks/annotate/block.json +10 -0
  64. package/registry/blocks/annotate/demo.jsx +135 -0
  65. package/registry/blocks/annotate/index.js +15 -0
  66. package/registry/blocks/approval-request/README.md +116 -0
  67. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  68. package/registry/blocks/approval-request/block.json +10 -0
  69. package/registry/blocks/approval-request/demo.jsx +127 -0
  70. package/registry/blocks/approval-request/index.js +4 -0
  71. package/registry/blocks/audio-player/README.md +167 -0
  72. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  73. package/registry/blocks/audio-player/block.json +14 -0
  74. package/registry/blocks/audio-player/colors.js +109 -0
  75. package/registry/blocks/audio-player/demo.jsx +209 -0
  76. package/registry/blocks/audio-player/index.js +6 -0
  77. package/registry/blocks/audio-player/time.js +67 -0
  78. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  79. package/registry/blocks/auth-form/README.md +126 -0
  80. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  81. package/registry/blocks/auth-form/block.json +10 -0
  82. package/registry/blocks/auth-form/demo.jsx +131 -0
  83. package/registry/blocks/auth-form/index.js +3 -0
  84. package/registry/blocks/board/README.md +64 -13
  85. package/registry/blocks/board/block.json +2 -2
  86. package/registry/blocks/board/board.jsx +237 -94
  87. package/registry/blocks/board/demo.jsx +103 -24
  88. package/registry/blocks/calendar-view/README.md +180 -0
  89. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  90. package/registry/blocks/calendar-view/block.json +76 -0
  91. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  92. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  93. package/registry/blocks/calendar-view/demo.jsx +195 -0
  94. package/registry/blocks/calendar-view/draft.jsx +49 -0
  95. package/registry/blocks/calendar-view/index.js +39 -0
  96. package/registry/blocks/calendar-view/month.jsx +346 -0
  97. package/registry/blocks/calendar-view/paint.js +69 -0
  98. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  99. package/registry/blocks/calendar-view/tray.jsx +87 -0
  100. package/registry/blocks/cart/README.md +146 -0
  101. package/registry/blocks/cart/block.json +10 -0
  102. package/registry/blocks/cart/cart.jsx +597 -0
  103. package/registry/blocks/cart/demo.jsx +98 -0
  104. package/registry/blocks/cart/index.js +4 -0
  105. package/registry/blocks/cart/money.js +28 -0
  106. package/registry/blocks/chart/README.md +316 -0
  107. package/registry/blocks/chart/block.json +10 -0
  108. package/registry/blocks/chart/cartesian.jsx +642 -0
  109. package/registry/blocks/chart/core.jsx +262 -0
  110. package/registry/blocks/chart/demo.jsx +357 -0
  111. package/registry/blocks/chart/heatmap.jsx +336 -0
  112. package/registry/blocks/chart/index.js +8 -0
  113. package/registry/blocks/chart/pie.jsx +245 -0
  114. package/registry/blocks/chart/sparkline.jsx +88 -0
  115. package/registry/blocks/chat/README.md +273 -0
  116. package/registry/blocks/chat/attachment.jsx +95 -0
  117. package/registry/blocks/chat/block.json +10 -0
  118. package/registry/blocks/chat/chat.jsx +132 -0
  119. package/registry/blocks/chat/composer.jsx +364 -0
  120. package/registry/blocks/chat/demo.jsx +578 -0
  121. package/registry/blocks/chat/header.jsx +34 -0
  122. package/registry/blocks/chat/index.js +9 -0
  123. package/registry/blocks/chat/message.jsx +450 -0
  124. package/registry/blocks/chat/scroller.jsx +247 -0
  125. package/registry/blocks/chat/text.jsx +104 -0
  126. package/registry/blocks/code-editor/README.md +210 -0
  127. package/registry/blocks/code-editor/block.json +22 -0
  128. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  129. package/registry/blocks/code-editor/codemirror.js +38 -0
  130. package/registry/blocks/code-editor/demo.jsx +205 -0
  131. package/registry/blocks/code-editor/index.js +8 -0
  132. package/registry/blocks/code-editor/json.js +317 -0
  133. package/registry/blocks/code-editor/sql.js +136 -0
  134. package/registry/blocks/code-editor/text.js +101 -0
  135. package/registry/blocks/code-editor/theme.js +186 -0
  136. package/registry/blocks/comment-box/README.md +123 -0
  137. package/registry/blocks/comment-box/block.json +10 -0
  138. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  139. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  140. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  141. package/registry/blocks/comment-box/demo.jsx +141 -0
  142. package/registry/blocks/comment-box/index.js +8 -0
  143. package/registry/blocks/contact-section/README.md +152 -0
  144. package/registry/blocks/contact-section/block.json +11 -0
  145. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  146. package/registry/blocks/contact-section/demo.jsx +93 -0
  147. package/registry/blocks/contact-section/index.js +4 -0
  148. package/registry/blocks/csv-import/README.md +133 -0
  149. package/registry/blocks/csv-import/block.json +13 -0
  150. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  151. package/registry/blocks/csv-import/demo.jsx +106 -0
  152. package/registry/blocks/csv-import/import.js +200 -0
  153. package/registry/blocks/csv-import/index.js +7 -0
  154. package/registry/blocks/data-table/README.md +386 -0
  155. package/registry/blocks/data-table/block.json +10 -0
  156. package/registry/blocks/data-table/data-table.jsx +1164 -0
  157. package/registry/blocks/data-table/demo.jsx +588 -0
  158. package/registry/blocks/data-table/index.js +5 -0
  159. package/registry/blocks/data-table/model.js +169 -0
  160. package/registry/blocks/diagram/README.md +108 -0
  161. package/registry/blocks/diagram/block.json +13 -0
  162. package/registry/blocks/diagram/demo.jsx +113 -0
  163. package/registry/blocks/diagram/diagram.jsx +481 -0
  164. package/registry/blocks/diagram/index.js +7 -0
  165. package/registry/blocks/diagram/mermaid.js +52 -0
  166. package/registry/blocks/diagram/palette.js +313 -0
  167. package/registry/blocks/diagram/source.js +98 -0
  168. package/registry/blocks/doc-editor/README.md +215 -0
  169. package/registry/blocks/doc-editor/block.json +15 -0
  170. package/registry/blocks/doc-editor/demo.jsx +225 -0
  171. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  172. package/registry/blocks/doc-editor/doc.js +309 -0
  173. package/registry/blocks/doc-editor/index.js +7 -0
  174. package/registry/blocks/doc-editor/schema.jsx +56 -0
  175. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  176. package/registry/blocks/doc-editor/theme.js +82 -0
  177. package/registry/blocks/doc-page/README.md +119 -0
  178. package/registry/blocks/doc-page/autosave.js +104 -0
  179. package/registry/blocks/doc-page/block.json +10 -0
  180. package/registry/blocks/doc-page/demo.jsx +137 -0
  181. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  182. package/registry/blocks/doc-page/index.js +4 -0
  183. package/registry/blocks/email-render/README.md +151 -0
  184. package/registry/blocks/email-render/block.json +14 -0
  185. package/registry/blocks/email-render/demo.jsx +153 -0
  186. package/registry/blocks/email-render/doc-email.jsx +210 -0
  187. package/registry/blocks/email-render/email.jsx +221 -0
  188. package/registry/blocks/email-render/index.js +10 -0
  189. package/registry/blocks/email-render/render.js +50 -0
  190. package/registry/blocks/email-render/theme.js +215 -0
  191. package/registry/blocks/faq/README.md +101 -0
  192. package/registry/blocks/faq/block.json +11 -0
  193. package/registry/blocks/faq/demo.jsx +89 -0
  194. package/registry/blocks/faq/faq.jsx +220 -0
  195. package/registry/blocks/faq/index.js +4 -0
  196. package/registry/blocks/file-upload/README.md +138 -0
  197. package/registry/blocks/file-upload/block.json +10 -0
  198. package/registry/blocks/file-upload/demo.jsx +204 -0
  199. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  200. package/registry/blocks/file-upload/index.js +4 -0
  201. package/registry/blocks/flow-canvas/README.md +420 -0
  202. package/registry/blocks/flow-canvas/block.json +13 -0
  203. package/registry/blocks/flow-canvas/board.js +819 -0
  204. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  205. package/registry/blocks/flow-canvas/context.jsx +35 -0
  206. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  207. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  208. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  209. package/registry/blocks/flow-canvas/index.js +41 -0
  210. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  211. package/registry/blocks/flow-canvas/theme.js +174 -0
  212. package/registry/blocks/footer/README.md +133 -0
  213. package/registry/blocks/footer/block.json +11 -0
  214. package/registry/blocks/footer/demo.jsx +119 -0
  215. package/registry/blocks/footer/footer.jsx +406 -0
  216. package/registry/blocks/footer/index.js +4 -0
  217. package/registry/blocks/gantt/README.md +220 -0
  218. package/registry/blocks/gantt/block.json +10 -0
  219. package/registry/blocks/gantt/demo.jsx +148 -0
  220. package/registry/blocks/gantt/gantt.jsx +923 -0
  221. package/registry/blocks/gantt/index.js +7 -0
  222. package/registry/blocks/gantt/rows.jsx +468 -0
  223. package/registry/blocks/gantt/schedule.js +278 -0
  224. package/registry/blocks/job-panel/README.md +86 -2
  225. package/registry/blocks/job-panel/block.json +3 -3
  226. package/registry/blocks/job-panel/demo.jsx +230 -3
  227. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  228. package/registry/blocks/json-editor/README.md +133 -0
  229. package/registry/blocks/json-editor/block.json +10 -0
  230. package/registry/blocks/json-editor/demo.jsx +92 -0
  231. package/registry/blocks/json-editor/index.js +7 -0
  232. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  233. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  234. package/registry/blocks/json-editor/tree.js +225 -0
  235. package/registry/blocks/map/README.md +221 -0
  236. package/registry/blocks/map/block.json +14 -0
  237. package/registry/blocks/map/demo.jsx +201 -0
  238. package/registry/blocks/map/geo.js +198 -0
  239. package/registry/blocks/map/index.js +8 -0
  240. package/registry/blocks/map/list.jsx +128 -0
  241. package/registry/blocks/map/map-view.jsx +715 -0
  242. package/registry/blocks/map/maplibre.js +30 -0
  243. package/registry/blocks/map/marks.jsx +146 -0
  244. package/registry/blocks/map/theme.js +142 -0
  245. package/registry/blocks/menubar/README.md +109 -0
  246. package/registry/blocks/menubar/block.json +10 -0
  247. package/registry/blocks/menubar/demo.jsx +128 -0
  248. package/registry/blocks/menubar/index.js +4 -0
  249. package/registry/blocks/menubar/menubar.jsx +199 -0
  250. package/registry/blocks/mind-map/README.md +206 -0
  251. package/registry/blocks/mind-map/block.json +10 -0
  252. package/registry/blocks/mind-map/demo.jsx +103 -0
  253. package/registry/blocks/mind-map/index.js +31 -0
  254. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  255. package/registry/blocks/mind-map/topic.jsx +143 -0
  256. package/registry/blocks/mind-map/tree.js +645 -0
  257. package/registry/blocks/navigation-menu/README.md +124 -0
  258. package/registry/blocks/navigation-menu/block.json +10 -0
  259. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  260. package/registry/blocks/navigation-menu/index.js +4 -0
  261. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  262. package/registry/blocks/order-detail/README.md +109 -0
  263. package/registry/blocks/order-detail/block.json +10 -0
  264. package/registry/blocks/order-detail/demo.jsx +88 -0
  265. package/registry/blocks/order-detail/index.js +4 -0
  266. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  267. package/registry/blocks/org-chart/README.md +145 -0
  268. package/registry/blocks/org-chart/block.json +10 -0
  269. package/registry/blocks/org-chart/demo.jsx +94 -0
  270. package/registry/blocks/org-chart/index.js +7 -0
  271. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  272. package/registry/blocks/org-chart/org.js +245 -0
  273. package/registry/blocks/org-chart/person.jsx +96 -0
  274. package/registry/blocks/page-builder/README.md +257 -0
  275. package/registry/blocks/page-builder/block.json +14 -0
  276. package/registry/blocks/page-builder/demo.jsx +145 -0
  277. package/registry/blocks/page-builder/grapes.js +18 -0
  278. package/registry/blocks/page-builder/index.js +11 -0
  279. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  280. package/registry/blocks/page-builder/page-view.jsx +33 -0
  281. package/registry/blocks/page-builder/page.js +118 -0
  282. package/registry/blocks/page-builder/panels.jsx +588 -0
  283. package/registry/blocks/page-builder/sections.js +209 -0
  284. package/registry/blocks/page-builder/theme.js +87 -0
  285. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  286. package/registry/blocks/page-builder/tokens.js +329 -0
  287. package/registry/blocks/payment-methods/README.md +104 -0
  288. package/registry/blocks/payment-methods/block.json +10 -0
  289. package/registry/blocks/payment-methods/demo.jsx +71 -0
  290. package/registry/blocks/payment-methods/index.js +4 -0
  291. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  292. package/registry/blocks/pdf-document/README.md +213 -0
  293. package/registry/blocks/pdf-document/block.json +13 -0
  294. package/registry/blocks/pdf-document/demo.jsx +136 -0
  295. package/registry/blocks/pdf-document/index.js +33 -0
  296. package/registry/blocks/pdf-document/money.js +83 -0
  297. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  298. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  299. package/registry/blocks/pdf-document/quote.jsx +179 -0
  300. package/registry/blocks/pdf-document/theme.js +193 -0
  301. package/registry/blocks/pdf-viewer/README.md +191 -0
  302. package/registry/blocks/pdf-viewer/block.json +14 -0
  303. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  304. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  305. package/registry/blocks/pdf-viewer/index.js +8 -0
  306. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  307. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  308. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  309. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  310. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  311. package/registry/blocks/product-detail/README.md +217 -0
  312. package/registry/blocks/product-detail/block.json +10 -0
  313. package/registry/blocks/product-detail/demo.jsx +233 -0
  314. package/registry/blocks/product-detail/index.js +7 -0
  315. package/registry/blocks/product-detail/price.jsx +115 -0
  316. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  317. package/registry/blocks/product-detail/product-media.jsx +102 -0
  318. package/registry/blocks/product-detail/product-options.jsx +144 -0
  319. package/registry/blocks/product-grid/README.md +162 -0
  320. package/registry/blocks/product-grid/block.json +10 -0
  321. package/registry/blocks/product-grid/demo.jsx +255 -0
  322. package/registry/blocks/product-grid/index.js +5 -0
  323. package/registry/blocks/product-grid/product-card.jsx +232 -0
  324. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  325. package/registry/blocks/record-form/README.md +196 -0
  326. package/registry/blocks/record-form/block.json +10 -0
  327. package/registry/blocks/record-form/demo.jsx +525 -0
  328. package/registry/blocks/record-form/index.js +4 -0
  329. package/registry/blocks/record-form/record-fields.jsx +457 -0
  330. package/registry/blocks/record-form/record-form.jsx +415 -0
  331. package/registry/blocks/record-form/rules.js +81 -0
  332. package/registry/blocks/record-notes/README.md +139 -0
  333. package/registry/blocks/record-notes/block.json +10 -0
  334. package/registry/blocks/record-notes/demo.jsx +179 -0
  335. package/registry/blocks/record-notes/index.js +4 -0
  336. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  337. package/registry/blocks/search-dialog/README.md +108 -0
  338. package/registry/blocks/search-dialog/block.json +10 -0
  339. package/registry/blocks/search-dialog/demo.jsx +116 -0
  340. package/registry/blocks/search-dialog/index.js +3 -0
  341. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  342. package/registry/blocks/settings-list/README.md +171 -0
  343. package/registry/blocks/settings-list/block.json +10 -0
  344. package/registry/blocks/settings-list/demo.jsx +333 -0
  345. package/registry/blocks/settings-list/index.js +4 -0
  346. package/registry/blocks/settings-list/row-state.jsx +93 -0
  347. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  348. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  349. package/registry/blocks/setup-checklist/README.md +142 -0
  350. package/registry/blocks/setup-checklist/block.json +10 -0
  351. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  352. package/registry/blocks/setup-checklist/index.js +4 -0
  353. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  354. package/registry/blocks/share-dialog/README.md +113 -0
  355. package/registry/blocks/share-dialog/block.json +10 -0
  356. package/registry/blocks/share-dialog/demo.jsx +140 -0
  357. package/registry/blocks/share-dialog/index.js +3 -0
  358. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  359. package/registry/blocks/sidebar/README.md +190 -0
  360. package/registry/blocks/sidebar/block.json +43 -0
  361. package/registry/blocks/sidebar/demo.jsx +577 -0
  362. package/registry/blocks/sidebar/index.js +4 -0
  363. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  364. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  365. package/registry/blocks/signature-pad/README.md +137 -0
  366. package/registry/blocks/signature-pad/block.json +13 -0
  367. package/registry/blocks/signature-pad/colors.js +115 -0
  368. package/registry/blocks/signature-pad/demo.jsx +94 -0
  369. package/registry/blocks/signature-pad/index.js +6 -0
  370. package/registry/blocks/signature-pad/pad.js +7 -0
  371. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  372. package/registry/blocks/signature-pad/signature.js +68 -0
  373. package/registry/blocks/sketch-canvas/README.md +280 -0
  374. package/registry/blocks/sketch-canvas/block.json +13 -0
  375. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  376. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  377. package/registry/blocks/sketch-canvas/index.js +9 -0
  378. package/registry/blocks/sketch-canvas/palette.js +226 -0
  379. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  380. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  381. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  382. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  383. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  384. package/registry/blocks/sketch-canvas/theme.js +131 -0
  385. package/registry/blocks/spreadsheet/README.md +307 -0
  386. package/registry/blocks/spreadsheet/block.json +13 -0
  387. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  388. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  389. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  390. package/registry/blocks/spreadsheet/grid.js +387 -0
  391. package/registry/blocks/spreadsheet/index.js +34 -0
  392. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  393. package/registry/blocks/spreadsheet/types.js +473 -0
  394. package/registry/blocks/stat-cards/README.md +173 -0
  395. package/registry/blocks/stat-cards/block.json +10 -0
  396. package/registry/blocks/stat-cards/demo.jsx +257 -0
  397. package/registry/blocks/stat-cards/index.js +4 -0
  398. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  399. package/registry/blocks/stat-cards/usage.jsx +243 -0
  400. package/registry/blocks/task-list/README.md +176 -0
  401. package/registry/blocks/task-list/block.json +10 -0
  402. package/registry/blocks/task-list/demo.jsx +134 -0
  403. package/registry/blocks/task-list/index.js +5 -0
  404. package/registry/blocks/task-list/task-list.jsx +907 -0
  405. package/registry/blocks/task-model/README.md +455 -0
  406. package/registry/blocks/task-model/block.json +167 -0
  407. package/registry/blocks/task-model/changes.js +89 -0
  408. package/registry/blocks/task-model/dates.js +371 -0
  409. package/registry/blocks/task-model/demo.jsx +215 -0
  410. package/registry/blocks/task-model/dnd.jsx +240 -0
  411. package/registry/blocks/task-model/index.js +97 -0
  412. package/registry/blocks/task-model/model.js +919 -0
  413. package/registry/blocks/task-model/parts.jsx +449 -0
  414. package/registry/blocks/task-model/toolbar.jsx +271 -0
  415. package/registry/blocks/testimonials/README.md +139 -0
  416. package/registry/blocks/testimonials/block.json +11 -0
  417. package/registry/blocks/testimonials/demo.jsx +137 -0
  418. package/registry/blocks/testimonials/index.js +4 -0
  419. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  420. package/registry/blocks/transaction-list/README.md +126 -0
  421. package/registry/blocks/transaction-list/block.json +10 -0
  422. package/registry/blocks/transaction-list/demo.jsx +79 -0
  423. package/registry/blocks/transaction-list/index.js +4 -0
  424. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  425. package/registry/blocks/whiteboard/README.md +179 -0
  426. package/registry/blocks/whiteboard/block.json +10 -0
  427. package/registry/blocks/whiteboard/demo.jsx +169 -0
  428. package/registry/blocks/whiteboard/index.js +6 -0
  429. package/registry/blocks/whiteboard/templates.js +150 -0
  430. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  431. package/src/install.mjs +18 -0
  432. package/src/shadcn.mjs +171 -0
  433. package/templates/next/files/README.md +145 -11
  434. package/templates/next/files/app/globals.css +55 -4
  435. package/templates/next/files/check/run.mjs +3 -3
  436. package/templates/next/files/components/parts/fixture.jsx +1 -1
  437. package/templates/next/files/components/parts/sample.js +15 -0
  438. package/templates/next/files/components/ui/avatar.jsx +141 -0
  439. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  440. package/templates/next/files/components/ui/button-group.jsx +70 -0
  441. package/templates/next/files/components/ui/button.jsx +132 -12
  442. package/templates/next/files/components/ui/calendar.jsx +609 -0
  443. package/templates/next/files/components/ui/carousel.jsx +281 -0
  444. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  445. package/templates/next/files/components/ui/combobox.jsx +608 -0
  446. package/templates/next/files/components/ui/command.jsx +577 -0
  447. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  448. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  449. package/templates/next/files/components/ui/distribution.jsx +117 -0
  450. package/templates/next/files/components/ui/feedback.jsx +143 -0
  451. package/templates/next/files/components/ui/field.jsx +115 -3
  452. package/templates/next/files/components/ui/file-input.jsx +234 -0
  453. package/templates/next/files/components/ui/icon.jsx +130 -8
  454. package/templates/next/files/components/ui/image.jsx +143 -0
  455. package/templates/next/files/components/ui/index.js +47 -2
  456. package/templates/next/files/components/ui/input-group.jsx +213 -0
  457. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  458. package/templates/next/files/components/ui/item.jsx +206 -0
  459. package/templates/next/files/components/ui/menu.jsx +454 -82
  460. package/templates/next/files/components/ui/notice.jsx +126 -14
  461. package/templates/next/files/components/ui/pagination.jsx +156 -0
  462. package/templates/next/files/components/ui/popover.jsx +284 -0
  463. package/templates/next/files/components/ui/radio.jsx +193 -0
  464. package/templates/next/files/components/ui/rating.jsx +131 -0
  465. package/templates/next/files/components/ui/resizable.jsx +338 -0
  466. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  467. package/templates/next/files/components/ui/separator.jsx +119 -0
  468. package/templates/next/files/components/ui/sheet.jsx +96 -11
  469. package/templates/next/files/components/ui/slider.jsx +174 -0
  470. package/templates/next/files/components/ui/stat.jsx +574 -0
  471. package/templates/next/files/components/ui/steps.jsx +338 -0
  472. package/templates/next/files/components/ui/swatch.jsx +33 -0
  473. package/templates/next/files/components/ui/table.jsx +130 -0
  474. package/templates/next/files/components/ui/toast.jsx +440 -0
  475. package/templates/next/files/components/ui/toggle.jsx +195 -0
  476. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  477. package/templates/next/files/lib/sample.js +4 -12
  478. package/templates/next/template.json +264 -8
@@ -0,0 +1,578 @@
1
+ "use client";
2
+
3
+ // The Chat block — the gallery's and the smoke test's surface. Not
4
+ // installed into apps. Four variants behind the switcher:
5
+ // Support a pretend support thread: replies "stream" from a timer, the
6
+ // last message failed to send and can be retried, older
7
+ // messages load from the top.
8
+ // Assistant a header, reasoning folded over replies, thumbs up/down,
9
+ // edit (Up arrow in the empty composer), suggestion chips.
10
+ // Ask the "ask anything" pill with a + menu, a mic and chips.
11
+ // Prompt a box composer with a model menu, a settings menu and
12
+ // starter cards.
13
+ import { useEffect, useRef, useState } from "react";
14
+ import { Button, Icon, Menu, Switch, Toggle, ToggleGroup } from "../components/ui";
15
+ import { ChatThread, Composer } from "../components/blocks/chat";
16
+
17
+ const MIN = 60 * 1000;
18
+ const DAY = 24 * 60 * MIN;
19
+ const ME = { name: "Maya Chen" };
20
+ const ADA = { name: "Ada · Support" };
21
+
22
+ // A picture of a bank statement, for the attachment's thumbnail: a real
23
+ // 80×80 PNG, not SVG markup, which an app's check refuses in its code.
24
+ const STATEMENT_PNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAIAAAABc2X6AAAAh0lEQVR42u3YMQ0AIAwEQDSzsDJiATeYYmHCBKEhXFMDt3ybT/OzScDAwMDAwMDAwMBXwKX1kAUGBgYGdpaAgYGBgYGBgSPB48EBBgaW0sDAwMA+LXcYGNinJaWBgYH/Bq+awxcYGFhoAQMDA+u0NB7AwDotKQ0MDAwMDAwMDAwMDAwMDHxgNrTiMi0505F8AAAAAElFTkSuQmCC";
25
+
26
+ function conversation(now) {
27
+ const at = (ms) => new Date(now - ms).toISOString();
28
+ return [
29
+ { id: "s1", role: "system", content: "Conversation started · Billing", createdAt: at(DAY + 12 * MIN) },
30
+ { id: "m1", role: "user", author: ME, content: "Hi! We were charged twice for the September invoice. Can you check?", createdAt: at(DAY + 11 * MIN) },
31
+ { id: "m2", role: "user", author: ME, content: "Workspace is Fernhill Bakery, if that helps.", createdAt: at(DAY + 10 * MIN) },
32
+ {
33
+ id: "m3",
34
+ role: "assistant",
35
+ author: ADA,
36
+ content:
37
+ "Sorry about that. I can see two charges of `$49.00` on 1 Sep — one of them is a pending hold from the card update, not a second payment. It should drop off within 3–5 business days.\n\nIf it is still there on Friday, send me the statement line and I will refund it straight away.",
38
+ createdAt: at(DAY + 8 * MIN),
39
+ },
40
+ {
41
+ id: "m4",
42
+ role: "user",
43
+ author: ME,
44
+ content: "It's Friday and it is still showing as posted. Here's the statement.",
45
+ createdAt: at(26 * MIN),
46
+ attachments: [
47
+ { id: "a1", name: "statement-september.pdf", size: 188_416, type: "application/pdf" },
48
+ { id: "a2", name: "posted-charges.png", size: 402_112, type: "image/png", url: STATEMENT_PNG },
49
+ ],
50
+ },
51
+ {
52
+ id: "m5",
53
+ role: "assistant",
54
+ author: ADA,
55
+ content:
56
+ "Thanks, Maya — that confirms it. I've refunded **$49.00** to the card ending 4417, reference `RF-20931`. It lands in 5–10 days.\n\nYour developer can check it from the API too:\n```bash\ncurl https://api.ledgerly.dev/v1/refunds/RF-20931 \\\n -H \"Authorization: Bearer $LEDGERLY_KEY\"\n```",
57
+ createdAt: at(24 * MIN),
58
+ },
59
+ {
60
+ id: "m6",
61
+ role: "user",
62
+ author: ME,
63
+ content: "Could you also email the receipt to accounts@fernhill.co?",
64
+ createdAt: at(3 * MIN),
65
+ status: "failed",
66
+ error: "you are offline",
67
+ },
68
+ ];
69
+ }
70
+
71
+ function older(now) {
72
+ const at = (ms) => new Date(now - ms).toISOString();
73
+ return [
74
+ { id: "o1", role: "user", author: ME, content: "Is there a way to add a second admin to our workspace?", createdAt: at(3 * DAY + 40 * MIN) },
75
+ {
76
+ id: "o2",
77
+ role: "assistant",
78
+ author: ADA,
79
+ content: "Yes. Open **Settings → Members**, choose Invite, and pick the `Admin` role. The invite link is good for 7 days.",
80
+ createdAt: at(3 * DAY + 38 * MIN),
81
+ },
82
+ { id: "o3", role: "user", author: ME, content: "Perfect, thanks!", createdAt: at(3 * DAY + 37 * MIN) },
83
+ ];
84
+ }
85
+
86
+ const REPLIES = [
87
+ "Done — the receipt for RF-20931 is on its way to accounts@fernhill.co. It comes from billing@ledgerly.dev, so check the spam folder if it has not arrived in a few minutes.",
88
+ "Happy to help. I've added a note to your account so the next card update does not place a second hold.\n\nAnything else I can look at while I'm here?",
89
+ "Good question. Receipts live under **Billing → History**; each row has a `Download PDF` link, and the whole year exports as CSV from the same page.",
90
+ ];
91
+
92
+ function SupportDemo() {
93
+ const [anchor] = useState(() => Math.floor(Date.now() / MIN) * MIN);
94
+ const [messages, setMessages] = useState(() => conversation(anchor));
95
+ const [hasMore, setHasMore] = useState(true);
96
+ const [loadingMore, setLoadingMore] = useState(false);
97
+ const [files, setFiles] = useState([]);
98
+ const [readOnly, setReadOnly] = useState(false);
99
+ const [empty, setEmpty] = useState(false);
100
+ const timers = useRef(new Set());
101
+ const replyIndex = useRef(0);
102
+ const streamId = useRef(null);
103
+
104
+ useEffect(() => {
105
+ const all = timers.current;
106
+ return () => all.forEach((t) => clearTimeout(t));
107
+ }, []);
108
+ const later = (ms, fn) => {
109
+ const t = setTimeout(() => {
110
+ timers.current.delete(t);
111
+ fn();
112
+ }, ms);
113
+ timers.current.add(t);
114
+ };
115
+ const patch = (id, change) => setMessages((all) => all.map((m) => (m.id === id ? { ...m, ...change } : m)));
116
+
117
+ // Stream `text` into message `id`, a few words at a time.
118
+ function stream(id, text) {
119
+ streamId.current = id;
120
+ const words = text.split(/(\s+)/);
121
+ let i = 0;
122
+ const tick = () => {
123
+ if (streamId.current !== id) return;
124
+ i = Math.min(words.length, i + 3);
125
+ const done = i >= words.length;
126
+ patch(id, { content: words.slice(0, i).join(""), status: done ? undefined : "streaming" });
127
+ if (done) streamId.current = null;
128
+ else later(60, tick);
129
+ };
130
+ later(700, tick);
131
+ }
132
+
133
+ function reply() {
134
+ const id = `r${Date.now()}`;
135
+ const text = REPLIES[replyIndex.current++ % REPLIES.length];
136
+ setMessages((all) => [...all, { id, role: "assistant", author: ADA, content: "", status: "streaming", createdAt: new Date().toISOString() }]);
137
+ stream(id, text);
138
+ }
139
+
140
+ function deliver(id) {
141
+ later(500, () => {
142
+ patch(id, { status: undefined, error: undefined });
143
+ reply();
144
+ });
145
+ }
146
+
147
+ async function send(text, attached) {
148
+ const id = `u${Date.now()}`;
149
+ setMessages((all) => [
150
+ ...all,
151
+ { id, role: "user", author: ME, content: text, createdAt: new Date().toISOString(), status: "sending", attachments: attached.map(({ progress, ...f }) => f) },
152
+ ]);
153
+ setFiles([]);
154
+ deliver(id);
155
+ return { ok: true };
156
+ }
157
+
158
+ function retry(m) {
159
+ patch(m.id, { status: "sending", error: undefined });
160
+ deliver(m.id);
161
+ }
162
+
163
+ function regenerate(m) {
164
+ patch(m.id, { content: "", status: "streaming" });
165
+ stream(m.id, REPLIES[replyIndex.current++ % REPLIES.length]);
166
+ }
167
+
168
+ function stop() {
169
+ const id = streamId.current;
170
+ streamId.current = null;
171
+ if (id) setMessages((all) => all.map((m) => (m.id === id ? { ...m, status: undefined, content: m.content || "(stopped)" } : m)));
172
+ }
173
+
174
+ function attach(picked) {
175
+ const added = picked.map((file, i) => ({
176
+ id: `f${Date.now()}-${i}`,
177
+ name: file.name,
178
+ size: file.size,
179
+ type: file.type,
180
+ url: file.type.startsWith("image/") ? URL.createObjectURL(file) : undefined,
181
+ progress: 0,
182
+ }));
183
+ setFiles((all) => [...all, ...added]);
184
+ for (const f of added) {
185
+ const step = (p) =>
186
+ later(220, () => {
187
+ setFiles((all) => all.map((x) => (x.id === f.id ? { ...x, progress: Math.min(100, p) } : x)));
188
+ if (p < 100) step(p + 20);
189
+ });
190
+ step(20);
191
+ }
192
+ }
193
+
194
+ function loadMore() {
195
+ setLoadingMore(true);
196
+ later(900, () => {
197
+ setMessages((all) => [...older(anchor), ...all]);
198
+ setHasMore(false);
199
+ setLoadingMore(false);
200
+ });
201
+ }
202
+
203
+ const streaming = messages.some((m) => m.status === "streaming");
204
+
205
+ return (
206
+ <div className="mx-auto grid max-w-3xl gap-3">
207
+ <div className="flex flex-wrap items-center justify-between gap-2">
208
+ <Switch id="chat-demo-readonly" label="Read-only thread" checked={readOnly} onChange={(e) => setReadOnly(e.target.checked)} />
209
+ <Button variant="quiet" size="sm" onClick={() => setEmpty((v) => !v)}>
210
+ {empty ? "Restore the conversation" : "Show an empty thread"}
211
+ </Button>
212
+ </div>
213
+ <ChatThread
214
+ messages={empty ? [] : messages}
215
+ onSend={send}
216
+ streaming={streaming}
217
+ onStop={stop}
218
+ onRetry={retry}
219
+ onRegenerate={regenerate}
220
+ actionsOf={(m) => [
221
+ { label: "Copy link", icon: "link", onSelect: () => navigator.clipboard?.writeText(`#message-${m.id}`).catch(() => {}) },
222
+ { label: "Delete message", icon: "trash", tone: "danger", onSelect: () => setMessages((all) => all.filter((x) => x.id !== m.id)) },
223
+ ]}
224
+ hasMore={!empty && hasMore}
225
+ loadingMore={loadingMore}
226
+ onLoadMore={loadMore}
227
+ attachments={files}
228
+ onAttach={attach}
229
+ onRemoveAttachment={(f) => setFiles((all) => all.filter((x) => x.id !== f.id))}
230
+ disabled={readOnly}
231
+ disabledPlaceholder="This conversation is closed"
232
+ assistantName="Ada · Support"
233
+ emptyTitle="No messages yet"
234
+ emptyBody="Ask about billing, your workspace or an invoice — Ada answers in a few seconds."
235
+ label="Support chat"
236
+ height="min(44rem, 85dvh)"
237
+ />
238
+ </div>
239
+ );
240
+ }
241
+
242
+ // ——— shared: a timer set that is cleared on unmount ———
243
+ function useLater() {
244
+ const timers = useRef(new Set());
245
+ useEffect(() => {
246
+ const all = timers.current;
247
+ return () => all.forEach((t) => clearTimeout(t));
248
+ }, []);
249
+ return (ms, fn) => {
250
+ const t = setTimeout(() => {
251
+ timers.current.delete(t);
252
+ fn();
253
+ }, ms);
254
+ timers.current.add(t);
255
+ };
256
+ }
257
+
258
+ // ——— Assistant: header, reasoning, feedback, edit, suggestions ———
259
+
260
+ const PIP = { name: "Pip · Planner" };
261
+
262
+ function assistantThread(now) {
263
+ const at = (ms) => new Date(now - ms).toISOString();
264
+ return [
265
+ { id: "a1", role: "user", content: "Which of this week's orders are at risk of shipping late?", createdAt: at(9 * MIN) },
266
+ {
267
+ id: "a2",
268
+ role: "assistant",
269
+ author: PIP,
270
+ reasoning:
271
+ "Orders due by Friday: 14. Checked each against stock and the courier cut-off.\nTwo are waiting on the oak shelf restock (arrives Thursday). One is going to a Highlands postcode, which adds a day.",
272
+ reasoningDuration: 6,
273
+ content:
274
+ "Three orders are at risk:\n\n**Order 4471** and **order 4478** — both need the oak wall shelf, which is back in stock Thursday.\n**Order 4482** — Highlands address; the courier needs one extra day.\n\nThe other 11 are packed or ready to pack.",
275
+ createdAt: at(8 * MIN),
276
+ feedback: "up",
277
+ },
278
+ { id: "a3", role: "user", content: "Draft a short note to the two shelf customers.", createdAt: at(4 * MIN) },
279
+ {
280
+ id: "a4",
281
+ role: "assistant",
282
+ author: PIP,
283
+ reasoning: "Keep it short, apologise once, give the new date, offer a swap to the walnut shelf which is in stock.",
284
+ reasoningDuration: 3,
285
+ content:
286
+ "Here is a draft:\n\nHi — your oak wall shelf is running two days behind; it now leaves us on **Thursday** and reaches you Friday. If you would rather have it sooner, the walnut version is in stock and ships today at the same price. Just reply and we'll swap it.",
287
+ createdAt: at(3 * MIN),
288
+ },
289
+ ];
290
+ }
291
+
292
+ const PLAN_REPLIES = [
293
+ {
294
+ reasoning: "Looked at last month's returns by reason. Sizing on the linen apron is the top cause, then transit damage on ceramics.",
295
+ content: "Returns are mostly two things: the **linen apron** runs small (9 of 23 returns), and **ceramic mugs** break in transit (6). A size note on the apron page and double-boxing mugs would cover most of it.",
296
+ },
297
+ {
298
+ reasoning: "Stock under two weeks of cover at the current sell-through rate.",
299
+ content: "Four products drop below two weeks of stock by the 5th: oak wall shelf, stoneware bowl (large), linen apron (M) and the beeswax wraps. Want me to draft the purchase orders?",
300
+ },
301
+ ];
302
+
303
+ const PLAN_SUGGESTIONS = [
304
+ { label: "What are customers returning?", icon: "refresh" },
305
+ { label: "What runs out soon?", icon: "package" },
306
+ { label: "Summarise this week", icon: "sparkles" },
307
+ ];
308
+
309
+ function AssistantDemo() {
310
+ const [anchor] = useState(() => Math.floor(Date.now() / MIN) * MIN);
311
+ const [messages, setMessages] = useState(() => assistantThread(anchor));
312
+ const [failSaves, setFailSaves] = useState(false);
313
+ const [deep, setDeep] = useState(true);
314
+ const streamId = useRef(null);
315
+ const turn = useRef(0);
316
+ const later = useLater();
317
+ const patch = (id, change) => setMessages((all) => all.map((m) => (m.id === id ? { ...m, ...change } : m)));
318
+
319
+ function answer() {
320
+ const id = `p${Date.now()}`;
321
+ const r = PLAN_REPLIES[turn.current++ % PLAN_REPLIES.length];
322
+ const started = Date.now();
323
+ streamId.current = id;
324
+ setMessages((all) => [...all, { id, role: "assistant", author: PIP, content: "", reasoning: "", status: "streaming", createdAt: new Date().toISOString() }]);
325
+ later(900, () => patch(id, { reasoning: r.reasoning }));
326
+ const words = r.content.split(/(\s+)/);
327
+ let i = 0;
328
+ const tick = () => {
329
+ if (streamId.current !== id) return;
330
+ i = Math.min(words.length, i + 3);
331
+ const done = i >= words.length;
332
+ patch(id, { content: words.slice(0, i).join(""), status: done ? undefined : "streaming", reasoningDuration: Math.max(1, Math.round((Date.now() - started) / 1000)) });
333
+ if (done) streamId.current = null;
334
+ else later(60, tick);
335
+ };
336
+ later(1800, tick);
337
+ }
338
+
339
+ async function send(text) {
340
+ setMessages((all) => [...all, { id: `u${Date.now()}`, role: "user", content: text, createdAt: new Date().toISOString() }]);
341
+ answer();
342
+ return { ok: true };
343
+ }
344
+
345
+ function stop() {
346
+ const id = streamId.current;
347
+ streamId.current = null;
348
+ if (id) setMessages((all) => all.map((m) => (m.id === id ? { ...m, status: undefined, content: m.content || "(stopped)" } : m)));
349
+ }
350
+
351
+ function pause() {
352
+ return new Promise((r) => later(500, r));
353
+ }
354
+
355
+ async function feedback(m, value) {
356
+ await pause();
357
+ if (failSaves) return { ok: false, error: "Feedback not saved: the server did not answer." };
358
+ patch(m.id, { feedback: value ?? undefined });
359
+ return { ok: true };
360
+ }
361
+
362
+ async function edit(m, text) {
363
+ await pause();
364
+ if (failSaves) return { ok: false, error: "Not saved: the server did not answer." };
365
+ // An edit asks again: the replies after it go, a new one streams.
366
+ setMessages((all) => {
367
+ const at = all.findIndex((x) => x.id === m.id);
368
+ return [...all.slice(0, at), { ...m, content: text }];
369
+ });
370
+ answer();
371
+ return { ok: true };
372
+ }
373
+
374
+ const streaming = messages.some((m) => m.status === "streaming");
375
+
376
+ return (
377
+ <div className="mx-auto grid max-w-2xl gap-3">
378
+ <div className="flex flex-wrap items-center justify-between gap-2">
379
+ <Switch id="chat-demo-fail" label="Saves fail" checked={failSaves} onChange={(e) => setFailSaves(e.target.checked)} />
380
+ <Button variant="quiet" size="sm" onClick={() => setMessages([])}>
381
+ Show an empty thread
382
+ </Button>
383
+ </div>
384
+ <ChatThread
385
+ messages={messages}
386
+ onSend={send}
387
+ streaming={streaming}
388
+ onStop={stop}
389
+ onFeedback={feedback}
390
+ onEdit={edit}
391
+ onRegenerate={(m) => {
392
+ setMessages((all) => all.filter((x) => x.id !== m.id));
393
+ answer();
394
+ }}
395
+ header={{
396
+ title: "Pip",
397
+ status: { tone: "success", label: "Online · knows your orders and stock" },
398
+ avatar: { name: "Pip" },
399
+ actions: (
400
+ <Button variant="quiet" size="sm" icon="plus" onClick={() => setMessages([])}>
401
+ New chat
402
+ </Button>
403
+ ),
404
+ menu: [
405
+ { type: "checkbox", label: "Think before answering", checked: deep, onCheckedChange: setDeep },
406
+ { type: "separator" },
407
+ { label: "Clear this chat", icon: "trash", tone: "danger", onSelect: () => setMessages([]) },
408
+ ],
409
+ }}
410
+ suggestions={PLAN_SUGGESTIONS}
411
+ placeholder="Ask Pip about orders, stock or returns…"
412
+ emptyTitle="What should we look at?"
413
+ emptyBody="Pip reads your orders, stock and returns. Pick a question or ask your own."
414
+ label="Planning assistant"
415
+ height="min(40rem, 85dvh)"
416
+ />
417
+ </div>
418
+ );
419
+ }
420
+
421
+ // ——— Ask: the "ask anything" pill ———
422
+
423
+ const ASK_CHIPS = [
424
+ { label: "Plan a spring sale", icon: "tag", prompt: "Plan a two-week spring sale for our ceramics: which products, what discount, and the emails to send." },
425
+ { label: "Write product copy", icon: "pencil", prompt: "Write a 60-word product description for the large stoneware bowl, warm and plain." },
426
+ { label: "Find slow sellers", icon: "trending-down", prompt: "Which products sold fewer than five units in the last 90 days?" },
427
+ ];
428
+
429
+ function AskDemo() {
430
+ const [sent, setSent] = useState([]);
431
+ const [files, setFiles] = useState([]);
432
+ const [listening, setListening] = useState(false);
433
+ const [mode, setMode] = useState(null);
434
+ const later = useLater();
435
+
436
+ async function send(text, attached) {
437
+ await new Promise((r) => later(400, r));
438
+ if (/fail/i.test(text)) return { ok: false, error: "Could not reach the assistant. Your text is back in the box." };
439
+ setSent((all) => [{ id: Date.now(), text, files: attached.length, mode }, ...all].slice(0, 3));
440
+ setFiles([]);
441
+ return { ok: true };
442
+ }
443
+
444
+ return (
445
+ <div className="mx-auto grid w-full max-w-2xl gap-6 py-6 sm:py-10">
446
+ <h2 className="text-balance text-center text-2xl font-semibold tracking-tight sm:text-3xl">What should we work on today?</h2>
447
+ <Composer
448
+ shape="pill"
449
+ onSend={send}
450
+ placeholder={listening ? "Listening…" : "Ask anything"}
451
+ attachments={files}
452
+ onAttach={(picked) => setFiles((all) => [...all, ...picked.map((f, i) => ({ id: `${Date.now()}-${i}`, name: f.name, size: f.size, type: f.type }))])}
453
+ onRemoveAttachment={(f) => setFiles((all) => all.filter((x) => x.id !== f.id))}
454
+ menu={[
455
+ { label: "Research the web", icon: "globe", onSelect: () => setMode("research") },
456
+ { label: "Plan it step by step", icon: "list", onSelect: () => setMode("plan") },
457
+ { label: "Just answer", icon: "zap", onSelect: () => setMode(null) },
458
+ ]}
459
+ tools={<Toggle variant="quiet" icon="mic" label={listening ? "Stop listening" : "Speak"} pressed={listening} onPressedChange={setListening} className="rounded-full" />}
460
+ suggestions={ASK_CHIPS}
461
+ suggestionsLabel="Start from an idea"
462
+ />
463
+ <p className="text-center text-xs text-muted-foreground">
464
+ {mode ? `Mode: ${mode === "research" ? "research the web" : "plan step by step"} · ` : ""}Type a word with “fail” in it to see a send fail.
465
+ </p>
466
+ {sent.length ? (
467
+ <ul aria-label="Sent" className="grid gap-2 text-sm">
468
+ {sent.map((m) => (
469
+ <li key={m.id} className="rounded-md border border-border bg-card px-3 py-2">
470
+ <span className="text-muted-foreground">Sent{m.files ? ` with ${m.files} file${m.files === 1 ? "" : "s"}` : ""}: </span>
471
+ {m.text}
472
+ </li>
473
+ ))}
474
+ </ul>
475
+ ) : null}
476
+ </div>
477
+ );
478
+ }
479
+
480
+ // ——— Prompt: a box with tools and starter cards ———
481
+
482
+ const MODELS = [
483
+ { value: "quick", label: "Quick", description: "Fast answers, short replies" },
484
+ { value: "balanced", label: "Balanced", description: "The everyday choice" },
485
+ { value: "deep", label: "Deep", description: "Slower, reads more, thinks longer" },
486
+ ];
487
+
488
+ const STARTERS = [
489
+ { label: "Import a price list", description: "From a spreadsheet or a PDF", icon: "upload", prompt: "Import the attached price list and update our product prices." },
490
+ { label: "Build a customer list", description: "Everyone who ordered twice", icon: "users", prompt: "Build a list of customers who ordered at least twice this year." },
491
+ { label: "Draft the newsletter", description: "This month's news and offers", icon: "mail", prompt: "Draft this month's newsletter: new arrivals, the spring sale and a workshop date." },
492
+ { label: "Tidy the catalogue", description: "Missing photos and prices", icon: "package", prompt: "Find products that are missing a photo, a price or a description." },
493
+ ];
494
+
495
+ function PromptDemo() {
496
+ const [model, setModel] = useState("balanced");
497
+ const [stream, setStream] = useState(true);
498
+ const [web, setWeb] = useState(false);
499
+ const [last, setLast] = useState(null);
500
+ const current = MODELS.find((m) => m.value === model) ?? MODELS[1];
501
+
502
+ return (
503
+ <div className="mx-auto grid w-full max-w-2xl gap-6 py-6">
504
+ <div className="grid gap-1 text-center">
505
+ <h2 className="text-balance text-2xl font-semibold tracking-tight">Describe it. We'll build it.</h2>
506
+ <p className="text-sm text-muted-foreground">Tell the assistant what you need, or start from one of these.</p>
507
+ </div>
508
+ <Composer
509
+ onSend={async (text) => {
510
+ setLast({ text, model: current.label, stream, web });
511
+ return { ok: true };
512
+ }}
513
+ placeholder="Ask anything"
514
+ hint={false}
515
+ onAttach={() => {}}
516
+ tools={
517
+ <>
518
+ <Menu
519
+ label={`Model: ${current.label}`}
520
+ align="start"
521
+ trigger={
522
+ <>
523
+ <span>{current.label}</span>
524
+ <Icon name="chevron-down" size={14} className="text-muted-foreground" />
525
+ </>
526
+ }
527
+ items={[{ type: "radio", value: model, onValueChange: setModel, options: MODELS }]}
528
+ />
529
+ <Menu
530
+ label="Settings"
531
+ align="start"
532
+ trigger={<Icon name="settings" />}
533
+ items={[
534
+ { type: "checkbox", label: "Stream the reply", checked: stream, onCheckedChange: setStream },
535
+ { type: "checkbox", label: "Search the web", checked: web, onCheckedChange: setWeb },
536
+ ]}
537
+ />
538
+ </>
539
+ }
540
+ suggestions={STARTERS}
541
+ suggestionsLook="cards"
542
+ suggestionsLabel="Starters"
543
+ />
544
+ {last ? (
545
+ <p className="rounded-md border border-border bg-card px-3 py-2 text-sm">
546
+ <span className="text-muted-foreground">
547
+ Sent to {last.model}
548
+ {last.web ? " · with web search" : ""}
549
+ {last.stream ? "" : " · no streaming"}:{" "}
550
+ </span>
551
+ {last.text}
552
+ </p>
553
+ ) : null}
554
+ </div>
555
+ );
556
+ }
557
+
558
+ // ——— the switcher ———
559
+
560
+ const VARIANTS = [
561
+ { value: "support", label: "Support" },
562
+ { value: "assistant", label: "Assistant" },
563
+ { value: "ask", label: "Ask" },
564
+ { value: "prompt", label: "Prompt" },
565
+ ];
566
+
567
+ export default function ChatDemo() {
568
+ const [variant, setVariant] = useState("support");
569
+ return (
570
+ <div className="grid gap-4">
571
+ <ToggleGroup size="sm" aria-label="Variant" value={variant} onChange={setVariant} items={VARIANTS} className="max-w-full justify-self-start overflow-x-auto" />
572
+ {variant === "support" ? <SupportDemo /> : null}
573
+ {variant === "assistant" ? <AssistantDemo /> : null}
574
+ {variant === "ask" ? <AskDemo /> : null}
575
+ {variant === "prompt" ? <PromptDemo /> : null}
576
+ </div>
577
+ );
578
+ }
@@ -0,0 +1,34 @@
1
+ "use client";
2
+
3
+ import { Avatar, Menu, StatusDot, cx } from "../../ui";
4
+
5
+ // ChatHeader — the strip over a conversation: who you are talking to
6
+ // (an avatar, a name, a line under it or a live status), then the
7
+ // surface's own actions ("New chat") and a menu of the rest. ChatThread
8
+ // draws it when given `header={{ title, … }}`; it is exported for a
9
+ // thread you compose yourself.
10
+ //
11
+ // <ChatHeader title="Ada" status={{ tone: "success", label: "Online" }}
12
+ // actions={<Button size="sm" variant="quiet" icon="plus" onClick={reset}>New chat</Button>} />
13
+
14
+ export function ChatHeader({ title, subtitle, status, avatar, actions, menu, menuLabel = "Conversation options", className }) {
15
+ return (
16
+ <header className={cx("flex min-h-14 items-center gap-3 border-b border-border px-3 py-2 sm:px-4", className)}>
17
+ {avatar ? <Avatar name={avatar.name ?? title} src={avatar.src} size="sm" shape="square" status={avatar.status} /> : null}
18
+ <div className="min-w-0 flex-1">
19
+ {title ? <h2 className="truncate text-sm font-semibold leading-tight">{title}</h2> : null}
20
+ {status ? (
21
+ <StatusDot tone={status.tone} size="sm" pulse={status.pulse} label={status.label} className="max-w-full text-xs" />
22
+ ) : subtitle ? (
23
+ <p className="truncate text-xs text-muted-foreground">{subtitle}</p>
24
+ ) : null}
25
+ </div>
26
+ {actions || (menu && menu.length) ? (
27
+ <div className="flex shrink-0 items-center gap-1">
28
+ {actions}
29
+ <Menu items={menu} label={menuLabel} />
30
+ </div>
31
+ ) : null}
32
+ </header>
33
+ );
34
+ }
@@ -0,0 +1,9 @@
1
+ // The Chat block — `makersclaw add chat`. Fixed: compose it through its
2
+ // props (README.md beside this file); a chat it cannot be is your own
3
+ // component in components/, built from these parts.
4
+ export { ChatThread } from "./chat";
5
+ export { ChatHeader } from "./header";
6
+ export { Message, Bubble } from "./message";
7
+ export { Attachment } from "./attachment";
8
+ export { MessageScroller } from "./scroller";
9
+ export { Composer } from "./composer";