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,149 @@
1
+ "use client";
2
+
3
+ import { useId, useRef } from "react";
4
+ import Link from "next/link";
5
+ import { cx } from "./cx";
6
+ import { Icon } from "./icon";
7
+ import { usePopoverPosition } from "./popover";
8
+
9
+ // Breadcrumb — where this page sits: Deals › Acme Corp › Renewal. Items
10
+ // are data; each with an `href` is a next/link (base path applied), the
11
+ // last is the page you are on (aria-current) and is never a link.
12
+ // A client part (a server surface renders it as it is; items are plain
13
+ // data): the "…" that stands in for the middle is a native popover
14
+ // (popovertarget), kept under its button by usePopoverPosition — CSS
15
+ // anchoring where the browser has it, measured where it does not.
16
+ //
17
+ // items [{ label, href? }] — first is the root, last is this page
18
+ // max how many slots on a wide window before the middle folds
19
+ // into "…" (default 4, the "…" counts as one); a narrow
20
+ // window shows first › … › last once there are four or more
21
+ // separator chevron (default) · slash
22
+ //
23
+ // Long labels truncate, the full text on hover. Earlier crumbs are capped
24
+ // (max-w-40, 56 on sm+); the current page takes the rest of the row. One item or none: nothing
25
+ // to place the page within, so nothing is drawn.
26
+
27
+ const SEP = {
28
+ chevron: <Icon name="chevron-right" size={14} />,
29
+ slash: <span className="px-0.5">/</span>,
30
+ };
31
+
32
+ // Shown at one width and not the other: the "…", each crumb, each entry
33
+ // in the popover. Whole class names, so Tailwind sees them.
34
+ const SHOW = {
35
+ flex: { both: "flex", narrow: "flex sm:hidden", wide: "hidden sm:flex", none: "hidden" },
36
+ block: { both: "block", narrow: "block sm:hidden", wide: "hidden sm:block", none: "hidden" },
37
+ };
38
+
39
+ // Every crumb truncates; only the earlier ones carry a cap. The current
40
+ // page is the one worth reading, so it takes whatever the row has left
41
+ // and cuts off only when the row really runs out. It is clamped to one
42
+ // line rather than kept on one (nowrap), so its narrowest size is a
43
+ // letter, not the whole title: a card or grid cell sized by its content
44
+ // still shrinks to the window instead of being pushed wide by the title.
45
+ const CRUMB = "min-w-0 rounded-sm outline-none focus-visible:ring-2 focus-visible:ring-ring";
46
+ const CAP = "block max-w-40 truncate sm:max-w-56";
47
+ const REST = "line-clamp-1 [overflow-wrap:anywhere]";
48
+
49
+ export function Breadcrumb({ items, max = 4, separator = "chevron", label = "Breadcrumb", className }) {
50
+ const auto = useId();
51
+ const more = useRef(null);
52
+ const panel = useRef(null);
53
+ usePopoverPosition(more, panel, { side: "bottom", align: "start", offset: 4 });
54
+ const list = (items ?? []).filter(Boolean);
55
+ if (list.length < 2) return null;
56
+
57
+ const id = `crumbs-${auto.replace(/[^a-zA-Z0-9]/g, "")}`;
58
+ const n = list.length;
59
+ const keep = Math.max(1, max - 2); // trailing items kept beside the first and the "…"
60
+ // Middle item i folds on a wide window when there are more than `max`;
61
+ // on a narrow one every middle item folds once there are four or more
62
+ // (three fit, truncated).
63
+ const foldsWide = (i) => n > max && i > 0 && i < n - keep;
64
+ const foldsNarrow = n > 3;
65
+ const middle = list.slice(1, -1).map((item, k) => ({ item, i: k + 1 }));
66
+ const wideFold = middle.some(({ i }) => foldsWide(i));
67
+ const at = (narrow, wide, display = "flex") => SHOW[display][narrow ? (wide ? "both" : "narrow") : wide ? "wide" : "none"];
68
+ const sep = (
69
+ <span aria-hidden="true" className="shrink-0 text-muted-foreground/70">
70
+ {SEP[separator] ?? SEP.chevron}
71
+ </span>
72
+ );
73
+
74
+ const crumb = (item, current) =>
75
+ current || !item.href ? (
76
+ <span aria-current={current ? "page" : undefined} title={item.label} className={cx(CRUMB, current ? cx(REST, "font-medium text-foreground") : CAP)}>
77
+ {item.label}
78
+ </span>
79
+ ) : (
80
+ <Link href={item.href} title={item.label} className={cx(CRUMB, CAP, "transition-colors hover:text-foreground")}>
81
+ {item.label}
82
+ </Link>
83
+ );
84
+
85
+ return (
86
+ <nav aria-label={label} className={cx("min-w-0", className)}>
87
+ <ol className="flex min-w-0 items-center gap-1.5 text-sm text-muted-foreground">
88
+ <li className="flex min-w-0 items-center">{crumb(list[0], false)}</li>
89
+
90
+ {middle.length > 0 ? (
91
+ <li className={cx("shrink-0 items-center gap-1.5", at(foldsNarrow, wideFold))}>
92
+ {sep}
93
+ <button
94
+ type="button"
95
+ ref={more}
96
+ popoverTarget={id}
97
+ aria-label="Show the full path"
98
+ title="Show the full path"
99
+ className="-mx-1 inline-flex h-8 w-8 items-center justify-center rounded-md outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
100
+ >
101
+ <Icon name="more" size={18} />
102
+ </button>
103
+ {/* Keyed by the page, so a client navigation lands with it closed. */}
104
+ <div
105
+ key={list[n - 1].href ?? list[n - 1].label}
106
+ ref={panel}
107
+ id={id}
108
+ popover="auto"
109
+ className="min-w-44 max-w-[calc(100vw-2rem)] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg"
110
+ >
111
+ <ul>
112
+ {middle.map(({ item, i }) => (
113
+ <li key={i} className={at(foldsNarrow, foldsWide(i), "block")}>
114
+ {item.href ? (
115
+ <Link
116
+ href={item.href}
117
+ className="flex min-h-10 items-center rounded-sm px-2 text-sm outline-none hover:bg-accent focus-visible:bg-accent"
118
+ >
119
+ <span className="truncate">{item.label}</span>
120
+ </Link>
121
+ ) : (
122
+ <span className="flex min-h-10 items-center px-2 text-sm text-muted-foreground">
123
+ <span className="truncate">{item.label}</span>
124
+ </span>
125
+ )}
126
+ </li>
127
+ ))}
128
+ </ul>
129
+ </div>
130
+ </li>
131
+ ) : null}
132
+
133
+ {middle.map(({ item, i }) => (
134
+ <li key={i} className={cx("min-w-0 items-center gap-1.5", at(!foldsNarrow, !foldsWide(i)))}>
135
+ {sep}
136
+ {crumb(item, false)}
137
+ </li>
138
+ ))}
139
+
140
+ {/* The rest of the row, and never less than 10rem (or half a narrow
141
+ row): long earlier crumbs give way before this page's title. */}
142
+ <li className="flex min-w-[min(10rem,50%)] flex-1 items-center gap-1.5">
143
+ {sep}
144
+ {crumb(list[n - 1], true)}
145
+ </li>
146
+ </ol>
147
+ </nav>
148
+ );
149
+ }
@@ -0,0 +1,70 @@
1
+ import { cx } from "./cx";
2
+
3
+ // ButtonGroup — buttons that belong together drawn as one attached
4
+ // piece: a split "Save | ▾", a pager "‹ 2 of 9 ›", a zoom "− 100% +".
5
+ // It only reshapes its children (square inner corners, one shared border
6
+ // between neighbours); each child stays the Button, IconButton or Menu
7
+ // it is, with its own behaviour and focus. Server-safe (no hooks).
8
+ //
9
+ // orientation horizontal (the default) · vertical
10
+ // size md · sm — match the buttons inside
11
+ // variant secondary (the default) · primary · quiet — how a Menu's
12
+ // trigger inside is drawn, to match its neighbours (the
13
+ // Buttons keep their own variant)
14
+ // aria-label what the group is for ("Pagination", "Text alignment")
15
+ //
16
+ // Secondary buttons share their borders, so they need no separator.
17
+ // Primary and quiet buttons have no visible border: put a
18
+ // <ButtonGroupSeparator /> between them. A group is for a few related
19
+ // actions — a toolbar with sections is several groups with a gap.
20
+
21
+ const ORIENT = {
22
+ horizontal: cx(
23
+ "inline-flex flex-row items-stretch",
24
+ "[&>:where(:not([popover]))]:rounded-none [&>:first-child]:rounded-l-md [&>:last-child]:rounded-r-md [&>:has(+[popover]:last-child)]:rounded-r-md",
25
+ "[&>:not(:first-child):not([popover])]:border-l-0 [&>[role=separator]]:w-px",
26
+ ),
27
+ vertical: cx(
28
+ "inline-flex flex-col items-stretch",
29
+ "[&>:where(:not([popover]))]:rounded-none [&>:first-child]:rounded-t-md [&>:last-child]:rounded-b-md [&>:has(+[popover]:last-child)]:rounded-b-md",
30
+ "[&>:not(:first-child):not([popover])]:border-t-0 [&>[role=separator]]:h-px",
31
+ ),
32
+ };
33
+
34
+ // A Menu renders a bare trigger; inside a group it wears its neighbours' look.
35
+ const MENU = {
36
+ secondary: "[&>[aria-haspopup]]:border [&>[aria-haspopup]]:border-border [&>[aria-haspopup]]:bg-secondary [&>[aria-haspopup]]:text-secondary-foreground [&>[aria-haspopup]]:hover:bg-accent",
37
+ primary: "[&>[aria-haspopup]]:border [&>[aria-haspopup]]:border-transparent [&>[aria-haspopup]]:bg-primary [&>[aria-haspopup]]:text-primary-foreground [&>[aria-haspopup]]:hover:bg-primary [&>[aria-haspopup]]:hover:opacity-90",
38
+ quiet: "[&>[aria-haspopup]]:border [&>[aria-haspopup]]:border-transparent",
39
+ };
40
+ const MENU_SIZE = {
41
+ md: "[&>[aria-haspopup]]:min-h-11 [&>[aria-haspopup]]:min-w-11",
42
+ sm: "[&>[aria-haspopup]]:min-h-9 [&>[aria-haspopup]]:min-w-9",
43
+ };
44
+
45
+ export function ButtonGroup({ orientation = "horizontal", size = "md", variant = "secondary", className, children, ...rest }) {
46
+ return (
47
+ <div
48
+ role="group"
49
+ aria-orientation={orientation === "vertical" ? "vertical" : undefined}
50
+ className={cx(
51
+ ORIENT[orientation] ?? ORIENT.horizontal,
52
+ MENU[variant] ?? MENU.secondary,
53
+ MENU_SIZE[size] ?? MENU_SIZE.md,
54
+ // The focused child's ring draws over its neighbours.
55
+ "[&>:not([popover])]:relative [&>:focus-visible]:z-10",
56
+ className,
57
+ )}
58
+ {...rest}
59
+ >
60
+ {children}
61
+ </div>
62
+ );
63
+ }
64
+
65
+ /** The line between two buttons whose borders do not show (primary,
66
+ * quiet). The group sizes it; in a vertical group pass
67
+ * orientation="horizontal" so a screen reader hears it right. */
68
+ export function ButtonGroupSeparator({ orientation = "vertical", className }) {
69
+ return <div role="separator" aria-orientation={orientation} className={cx("shrink-0 self-stretch bg-border", className)} />;
70
+ }
@@ -1,23 +1,72 @@
1
1
  import Link from "next/link";
2
2
  import { cx } from "./cx";
3
3
  import { Icon } from "./icon";
4
+ import { Spinner } from "./feedback";
4
5
 
5
- // Button — every action in the app. Four looks, one shape, 44px targets
6
+ // Button — every action in the app. One shape, 44px targets
6
7
  // (mobile first: a thumb hits it). `href` makes it a next/link (base
7
8
  // path applied); `icon` names one from ./icon. Never style a <button>
8
9
  // by hand in a surface: the look is the workspace's, the behaviour is
9
10
  // the browser's, and this is the only place both meet.
10
11
  //
11
12
  // variant primary (the one main action per surface) · secondary ·
12
- // quiet (no fill) · danger (destructive, red text) · link
13
- // size md (44px) · sm (36px, for dense rows and rails)
13
+ // quiet (no fill) · danger (destructive, red text) ·
14
+ // link (text only: inline, no box, padding or min-height — it
15
+ // wraps and truncates with the sentence it sits in) · nav (a navigation row: quiet, full
16
+ // width, start-aligned, normal weight; aria-current="page"
17
+ // fills it and sets it medium)
18
+ // size md (44px) · sm (36px, for dense rows and rails); a link has
19
+ // no height, so for it md and sm are text-sm and `inherit`
20
+ // takes the surrounding text's size and weight
21
+ // align center (the default) · start (label at the leading edge, for
22
+ // a full-width row of your own; nav is always start)
23
+ // loading true while its action runs: a spinner over the label (the
24
+ // width does not jump), aria-busy, and disabled so a second
25
+ // click cannot fire it again
26
+ // tone a link's colour: primary (the default, text-primary) · muted
27
+ // (text-muted-foreground, foreground on hover — a secondary
28
+ // link beside a heading, "What's new", "View all"); only a
29
+ // link reads it
30
+ // iconOnly a square at the size (IconButton sets it; a Button whose
31
+ // only child is an <Icon> should too)
32
+ //
33
+ // cx does not merge classes: a className can add, never override, what a
34
+ // variant or size already sets. Anything a surface needs to vary is a
35
+ // prop here, not a className fight.
14
36
 
15
37
  const VARIANTS = {
16
38
  primary: "bg-primary text-primary-foreground hover:opacity-90 border-transparent",
17
39
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-accent",
18
40
  quiet: "bg-transparent text-foreground border-transparent hover:bg-accent",
19
41
  danger: "bg-transparent text-destructive border-border hover:bg-accent",
20
- link: "bg-transparent text-primary underline-offset-4 hover:underline border-transparent px-0 min-h-0",
42
+ link: "underline-offset-4 hover:underline",
43
+ nav:
44
+ "w-full min-w-0 bg-transparent text-foreground border-transparent hover:bg-accent " +
45
+ "[&[aria-current]:not([aria-current=false])]:bg-accent [&[aria-current]:not([aria-current=false])]:text-accent-foreground",
46
+ };
47
+
48
+ // A link's colour, apart from its variant so a secondary link is a prop
49
+ // and not a text-muted-foreground laid over text-primary.
50
+ const LINK_TONES = {
51
+ primary: "text-primary",
52
+ muted: "text-muted-foreground hover:text-foreground",
53
+ };
54
+
55
+ // The shape each variant is drawn in. A nav row spaces its icon wider.
56
+ // A link is text in a line: inline, not a flex box — no border, padding
57
+ // or height, it wraps where the sentence wraps and truncates with it. Its
58
+ // icons sit on the text's line: `icon` leads, an <Icon> child trails.
59
+ const SHAPE = {
60
+ box: "inline-flex items-center gap-2 rounded-md border whitespace-nowrap",
61
+ nav: "inline-flex items-center gap-3 rounded-md border whitespace-nowrap",
62
+ link: "inline rounded-sm [&>svg]:ml-1 [&>svg]:inline-block [&>svg]:align-[-0.125em]",
63
+ };
64
+
65
+ // Weight lives apart from the shape so a nav row can be normal weight
66
+ // (its current row medium) without laying one font weight over another.
67
+ const WEIGHT = {
68
+ box: "font-medium",
69
+ nav: "font-normal [&[aria-current]:not([aria-current=false])]:font-medium",
21
70
  };
22
71
 
23
72
  const SIZES = {
@@ -25,6 +74,27 @@ const SIZES = {
25
74
  sm: "min-h-9 px-3 text-sm",
26
75
  };
27
76
 
77
+ // A link's sizes are only its text: md and sm as every other button,
78
+ // inherit for a link inside a sentence.
79
+ const LINK_SIZES = {
80
+ md: "text-sm font-medium",
81
+ sm: "text-sm font-medium",
82
+ inherit: "",
83
+ };
84
+
85
+ // IconButton's squares. Their own entries, never a px-0 laid over a
86
+ // size's padding: cx does not merge classes, so which of two paddings
87
+ // wins is CSS order, not the order they were written in.
88
+ const ICON_SIZES = {
89
+ md: "size-11 px-0 text-sm",
90
+ sm: "size-9 px-0 text-sm",
91
+ };
92
+
93
+ const ALIGN = {
94
+ center: "justify-center",
95
+ start: "justify-start text-left",
96
+ };
97
+
28
98
  export function Button({
29
99
  variant = "secondary",
30
100
  size = "md",
@@ -33,31 +103,80 @@ export function Button({
33
103
  className,
34
104
  children,
35
105
  type = "button",
106
+ loading = false,
107
+ disabled,
108
+ iconOnly = false,
109
+ align = "center",
110
+ tone = "primary",
36
111
  ...rest
37
112
  }) {
113
+ const look = VARIANTS[variant] ? variant : "secondary";
114
+ const link = look === "link";
115
+ const nav = look === "nav";
116
+ const sizeClass = link
117
+ ? LINK_SIZES[size] ?? LINK_SIZES.md
118
+ : iconOnly
119
+ ? ICON_SIZES[size] ?? ICON_SIZES.md
120
+ : SIZES[size] ?? SIZES.md;
38
121
  const classes = cx(
39
- "inline-flex items-center justify-center gap-2 rounded-md border font-medium whitespace-nowrap",
122
+ SHAPE[link ? "link" : nav ? "nav" : "box"],
123
+ !link && (nav ? WEIGHT.nav : WEIGHT.box),
124
+ !link && !iconOnly && (ALIGN[nav ? "start" : align] ?? ALIGN.center),
125
+ iconOnly && ALIGN.center,
40
126
  "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
41
127
  "disabled:cursor-not-allowed disabled:opacity-50",
42
- VARIANTS[variant] ?? VARIANTS.secondary,
43
- SIZES[size] ?? SIZES.md,
128
+ VARIANTS[look],
129
+ link && (LINK_TONES[tone] ?? LINK_TONES.primary),
130
+ sizeClass,
131
+ // Busy is not unavailable: the button keeps its full colour.
132
+ loading && "relative disabled:aria-busy:opacity-100 disabled:aria-busy:cursor-progress",
133
+ loading && href && "pointer-events-none opacity-50",
44
134
  className,
45
135
  );
46
- const body = (
136
+ const lead = icon ? (
137
+ link ? (
138
+ <span className="mr-1 inline-block align-[-0.125em]">
139
+ <Icon name={icon} />
140
+ </span>
141
+ ) : (
142
+ <Icon name={icon} />
143
+ )
144
+ ) : null;
145
+ const content = (
47
146
  <>
48
- {icon ? <Icon name={icon} /> : null}
147
+ {lead}
49
148
  {children}
50
149
  </>
51
150
  );
151
+ // Loading: the label stays in place (transparent, still the accessible
152
+ // name) so the button keeps its width; the spinner sits on top of it.
153
+ const body = loading ? (
154
+ <>
155
+ <span className="inline-flex items-center gap-2 opacity-0">{content}</span>
156
+ <span className="absolute inset-0 grid place-items-center">
157
+ <Spinner size="sm" label={null} />
158
+ </span>
159
+ </>
160
+ ) : (
161
+ content
162
+ );
52
163
  if (href) {
53
164
  return (
54
- <Link href={href} className={classes} {...rest}>
165
+ <Link
166
+ href={href}
167
+ className={classes}
168
+ aria-busy={loading || undefined}
169
+ aria-disabled={loading || undefined}
170
+ tabIndex={loading ? -1 : undefined}
171
+ disabled={disabled}
172
+ {...rest}
173
+ >
55
174
  {body}
56
175
  </Link>
57
176
  );
58
177
  }
59
178
  return (
60
- <button type={type} className={classes} {...rest}>
179
+ <button type={type} className={classes} disabled={loading || disabled} aria-busy={loading || undefined} {...rest}>
61
180
  {body}
62
181
  </button>
63
182
  );
@@ -72,7 +191,8 @@ export function IconButton({ icon, label, size = "md", variant = "quiet", classN
72
191
  size={size}
73
192
  aria-label={label}
74
193
  title={label}
75
- className={cx(size === "sm" ? "w-9 px-0" : "w-11 px-0", className)}
194
+ iconOnly
195
+ className={cx("shrink-0", className)}
76
196
  {...rest}
77
197
  >
78
198
  <Icon name={icon} size={size === "sm" ? 16 : 18} />