makersclaw 0.2.0 → 0.3.1

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 (475) hide show
  1. package/THIRD-PARTY-NOTICES.md +180 -0
  2. package/package.json +3 -2
  3. package/r/annotate.json +62 -0
  4. package/r/approval-request.json +52 -0
  5. package/r/audio-player.json +74 -0
  6. package/r/auth-form.json +55 -0
  7. package/r/board.json +10 -6
  8. package/r/calendar-view.json +105 -0
  9. package/r/cart.json +62 -0
  10. package/r/chart.json +83 -0
  11. package/r/chat.json +95 -0
  12. package/r/code-editor.json +94 -0
  13. package/r/comment-box.json +64 -0
  14. package/r/contact-section.json +53 -0
  15. package/r/core.json +205 -8
  16. package/r/csv-import.json +63 -0
  17. package/r/data-table.json +69 -0
  18. package/r/diagram.json +74 -0
  19. package/r/doc-editor.json +82 -0
  20. package/r/doc-page.json +61 -0
  21. package/r/email-render.json +73 -0
  22. package/r/faq.json +50 -0
  23. package/r/file-upload.json +54 -0
  24. package/r/flow-canvas.json +93 -0
  25. package/r/footer.json +52 -0
  26. package/r/gantt.json +70 -0
  27. package/r/job-panel.json +12 -7
  28. package/r/json-editor.json +66 -0
  29. package/r/map.json +89 -0
  30. package/r/menubar.json +52 -0
  31. package/r/mind-map.json +67 -0
  32. package/r/navigation-menu.json +52 -0
  33. package/r/order-detail.json +54 -0
  34. package/r/org-chart.json +66 -0
  35. package/r/page-builder.json +105 -0
  36. package/r/payment-methods.json +51 -0
  37. package/r/pdf-document.json +79 -0
  38. package/r/pdf-viewer.json +88 -0
  39. package/r/product-detail.json +76 -0
  40. package/r/product-grid.json +65 -0
  41. package/r/record-form.json +67 -0
  42. package/r/record-notes.json +55 -0
  43. package/r/registry.json +3411 -29
  44. package/r/search-dialog.json +51 -0
  45. package/r/settings-list.json +66 -0
  46. package/r/setup-checklist.json +51 -0
  47. package/r/share-dialog.json +52 -0
  48. package/r/sidebar.json +69 -0
  49. package/r/signature-pad.json +72 -0
  50. package/r/sketch-canvas.json +99 -0
  51. package/r/spreadsheet.json +90 -0
  52. package/r/stat-cards.json +66 -0
  53. package/r/task-list.json +63 -0
  54. package/r/task-model.json +98 -0
  55. package/r/testimonials.json +52 -0
  56. package/r/transaction-list.json +53 -0
  57. package/r/whiteboard.json +66 -0
  58. package/registry/blocks/annotate/README.md +179 -0
  59. package/registry/blocks/annotate/annotate-data.js +250 -0
  60. package/registry/blocks/annotate/annotate.jsx +646 -0
  61. package/registry/blocks/annotate/block.json +10 -0
  62. package/registry/blocks/annotate/demo.jsx +135 -0
  63. package/registry/blocks/annotate/index.js +15 -0
  64. package/registry/blocks/approval-request/README.md +116 -0
  65. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  66. package/registry/blocks/approval-request/block.json +10 -0
  67. package/registry/blocks/approval-request/demo.jsx +127 -0
  68. package/registry/blocks/approval-request/index.js +4 -0
  69. package/registry/blocks/audio-player/README.md +167 -0
  70. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  71. package/registry/blocks/audio-player/block.json +14 -0
  72. package/registry/blocks/audio-player/colors.js +109 -0
  73. package/registry/blocks/audio-player/demo.jsx +209 -0
  74. package/registry/blocks/audio-player/index.js +6 -0
  75. package/registry/blocks/audio-player/time.js +67 -0
  76. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  77. package/registry/blocks/auth-form/README.md +126 -0
  78. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  79. package/registry/blocks/auth-form/block.json +10 -0
  80. package/registry/blocks/auth-form/demo.jsx +131 -0
  81. package/registry/blocks/auth-form/index.js +3 -0
  82. package/registry/blocks/board/README.md +55 -5
  83. package/registry/blocks/board/block.json +2 -2
  84. package/registry/blocks/board/board.jsx +230 -86
  85. package/registry/blocks/board/demo.jsx +103 -24
  86. package/registry/blocks/calendar-view/README.md +180 -0
  87. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  88. package/registry/blocks/calendar-view/block.json +76 -0
  89. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  90. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  91. package/registry/blocks/calendar-view/demo.jsx +195 -0
  92. package/registry/blocks/calendar-view/draft.jsx +49 -0
  93. package/registry/blocks/calendar-view/index.js +39 -0
  94. package/registry/blocks/calendar-view/month.jsx +346 -0
  95. package/registry/blocks/calendar-view/paint.js +69 -0
  96. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  97. package/registry/blocks/calendar-view/tray.jsx +87 -0
  98. package/registry/blocks/cart/README.md +146 -0
  99. package/registry/blocks/cart/block.json +10 -0
  100. package/registry/blocks/cart/cart.jsx +597 -0
  101. package/registry/blocks/cart/demo.jsx +98 -0
  102. package/registry/blocks/cart/index.js +4 -0
  103. package/registry/blocks/cart/money.js +28 -0
  104. package/registry/blocks/chart/README.md +316 -0
  105. package/registry/blocks/chart/block.json +10 -0
  106. package/registry/blocks/chart/cartesian.jsx +642 -0
  107. package/registry/blocks/chart/core.jsx +262 -0
  108. package/registry/blocks/chart/demo.jsx +357 -0
  109. package/registry/blocks/chart/heatmap.jsx +336 -0
  110. package/registry/blocks/chart/index.js +8 -0
  111. package/registry/blocks/chart/pie.jsx +245 -0
  112. package/registry/blocks/chart/sparkline.jsx +88 -0
  113. package/registry/blocks/chat/README.md +273 -0
  114. package/registry/blocks/chat/attachment.jsx +95 -0
  115. package/registry/blocks/chat/block.json +10 -0
  116. package/registry/blocks/chat/chat.jsx +132 -0
  117. package/registry/blocks/chat/composer.jsx +364 -0
  118. package/registry/blocks/chat/demo.jsx +578 -0
  119. package/registry/blocks/chat/header.jsx +34 -0
  120. package/registry/blocks/chat/index.js +9 -0
  121. package/registry/blocks/chat/message.jsx +450 -0
  122. package/registry/blocks/chat/scroller.jsx +247 -0
  123. package/registry/blocks/chat/text.jsx +104 -0
  124. package/registry/blocks/code-editor/README.md +210 -0
  125. package/registry/blocks/code-editor/block.json +22 -0
  126. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  127. package/registry/blocks/code-editor/codemirror.js +38 -0
  128. package/registry/blocks/code-editor/demo.jsx +205 -0
  129. package/registry/blocks/code-editor/index.js +8 -0
  130. package/registry/blocks/code-editor/json.js +317 -0
  131. package/registry/blocks/code-editor/sql.js +136 -0
  132. package/registry/blocks/code-editor/text.js +101 -0
  133. package/registry/blocks/code-editor/theme.js +186 -0
  134. package/registry/blocks/comment-box/README.md +123 -0
  135. package/registry/blocks/comment-box/block.json +10 -0
  136. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  137. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  138. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  139. package/registry/blocks/comment-box/demo.jsx +141 -0
  140. package/registry/blocks/comment-box/index.js +8 -0
  141. package/registry/blocks/contact-section/README.md +152 -0
  142. package/registry/blocks/contact-section/block.json +11 -0
  143. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  144. package/registry/blocks/contact-section/demo.jsx +93 -0
  145. package/registry/blocks/contact-section/index.js +4 -0
  146. package/registry/blocks/csv-import/README.md +133 -0
  147. package/registry/blocks/csv-import/block.json +13 -0
  148. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  149. package/registry/blocks/csv-import/demo.jsx +106 -0
  150. package/registry/blocks/csv-import/import.js +200 -0
  151. package/registry/blocks/csv-import/index.js +7 -0
  152. package/registry/blocks/data-table/README.md +386 -0
  153. package/registry/blocks/data-table/block.json +10 -0
  154. package/registry/blocks/data-table/data-table.jsx +1164 -0
  155. package/registry/blocks/data-table/demo.jsx +588 -0
  156. package/registry/blocks/data-table/index.js +5 -0
  157. package/registry/blocks/data-table/model.js +169 -0
  158. package/registry/blocks/diagram/README.md +108 -0
  159. package/registry/blocks/diagram/block.json +13 -0
  160. package/registry/blocks/diagram/demo.jsx +113 -0
  161. package/registry/blocks/diagram/diagram.jsx +481 -0
  162. package/registry/blocks/diagram/index.js +7 -0
  163. package/registry/blocks/diagram/mermaid.js +52 -0
  164. package/registry/blocks/diagram/palette.js +313 -0
  165. package/registry/blocks/diagram/source.js +98 -0
  166. package/registry/blocks/doc-editor/README.md +215 -0
  167. package/registry/blocks/doc-editor/block.json +15 -0
  168. package/registry/blocks/doc-editor/demo.jsx +225 -0
  169. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  170. package/registry/blocks/doc-editor/doc.js +309 -0
  171. package/registry/blocks/doc-editor/index.js +7 -0
  172. package/registry/blocks/doc-editor/schema.jsx +56 -0
  173. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  174. package/registry/blocks/doc-editor/theme.js +82 -0
  175. package/registry/blocks/doc-page/README.md +119 -0
  176. package/registry/blocks/doc-page/autosave.js +104 -0
  177. package/registry/blocks/doc-page/block.json +10 -0
  178. package/registry/blocks/doc-page/demo.jsx +137 -0
  179. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  180. package/registry/blocks/doc-page/index.js +4 -0
  181. package/registry/blocks/email-render/README.md +151 -0
  182. package/registry/blocks/email-render/block.json +14 -0
  183. package/registry/blocks/email-render/demo.jsx +153 -0
  184. package/registry/blocks/email-render/doc-email.jsx +210 -0
  185. package/registry/blocks/email-render/email.jsx +221 -0
  186. package/registry/blocks/email-render/index.js +10 -0
  187. package/registry/blocks/email-render/render.js +50 -0
  188. package/registry/blocks/email-render/theme.js +215 -0
  189. package/registry/blocks/faq/README.md +101 -0
  190. package/registry/blocks/faq/block.json +11 -0
  191. package/registry/blocks/faq/demo.jsx +89 -0
  192. package/registry/blocks/faq/faq.jsx +220 -0
  193. package/registry/blocks/faq/index.js +4 -0
  194. package/registry/blocks/file-upload/README.md +138 -0
  195. package/registry/blocks/file-upload/block.json +10 -0
  196. package/registry/blocks/file-upload/demo.jsx +204 -0
  197. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  198. package/registry/blocks/file-upload/index.js +4 -0
  199. package/registry/blocks/flow-canvas/README.md +420 -0
  200. package/registry/blocks/flow-canvas/block.json +13 -0
  201. package/registry/blocks/flow-canvas/board.js +819 -0
  202. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  203. package/registry/blocks/flow-canvas/context.jsx +35 -0
  204. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  205. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  206. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  207. package/registry/blocks/flow-canvas/index.js +41 -0
  208. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  209. package/registry/blocks/flow-canvas/theme.js +174 -0
  210. package/registry/blocks/footer/README.md +133 -0
  211. package/registry/blocks/footer/block.json +11 -0
  212. package/registry/blocks/footer/demo.jsx +119 -0
  213. package/registry/blocks/footer/footer.jsx +406 -0
  214. package/registry/blocks/footer/index.js +4 -0
  215. package/registry/blocks/gantt/README.md +220 -0
  216. package/registry/blocks/gantt/block.json +10 -0
  217. package/registry/blocks/gantt/demo.jsx +148 -0
  218. package/registry/blocks/gantt/gantt.jsx +923 -0
  219. package/registry/blocks/gantt/index.js +7 -0
  220. package/registry/blocks/gantt/rows.jsx +468 -0
  221. package/registry/blocks/gantt/schedule.js +278 -0
  222. package/registry/blocks/job-panel/README.md +80 -0
  223. package/registry/blocks/job-panel/block.json +3 -3
  224. package/registry/blocks/job-panel/demo.jsx +230 -3
  225. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  226. package/registry/blocks/json-editor/README.md +133 -0
  227. package/registry/blocks/json-editor/block.json +10 -0
  228. package/registry/blocks/json-editor/demo.jsx +92 -0
  229. package/registry/blocks/json-editor/index.js +7 -0
  230. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  231. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  232. package/registry/blocks/json-editor/tree.js +225 -0
  233. package/registry/blocks/map/README.md +221 -0
  234. package/registry/blocks/map/block.json +14 -0
  235. package/registry/blocks/map/demo.jsx +201 -0
  236. package/registry/blocks/map/geo.js +198 -0
  237. package/registry/blocks/map/index.js +8 -0
  238. package/registry/blocks/map/list.jsx +128 -0
  239. package/registry/blocks/map/map-view.jsx +715 -0
  240. package/registry/blocks/map/maplibre.js +30 -0
  241. package/registry/blocks/map/marks.jsx +146 -0
  242. package/registry/blocks/map/theme.js +142 -0
  243. package/registry/blocks/menubar/README.md +109 -0
  244. package/registry/blocks/menubar/block.json +10 -0
  245. package/registry/blocks/menubar/demo.jsx +128 -0
  246. package/registry/blocks/menubar/index.js +4 -0
  247. package/registry/blocks/menubar/menubar.jsx +199 -0
  248. package/registry/blocks/mind-map/README.md +206 -0
  249. package/registry/blocks/mind-map/block.json +10 -0
  250. package/registry/blocks/mind-map/demo.jsx +103 -0
  251. package/registry/blocks/mind-map/index.js +31 -0
  252. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  253. package/registry/blocks/mind-map/topic.jsx +143 -0
  254. package/registry/blocks/mind-map/tree.js +645 -0
  255. package/registry/blocks/navigation-menu/README.md +124 -0
  256. package/registry/blocks/navigation-menu/block.json +10 -0
  257. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  258. package/registry/blocks/navigation-menu/index.js +4 -0
  259. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  260. package/registry/blocks/order-detail/README.md +109 -0
  261. package/registry/blocks/order-detail/block.json +10 -0
  262. package/registry/blocks/order-detail/demo.jsx +88 -0
  263. package/registry/blocks/order-detail/index.js +4 -0
  264. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  265. package/registry/blocks/org-chart/README.md +145 -0
  266. package/registry/blocks/org-chart/block.json +10 -0
  267. package/registry/blocks/org-chart/demo.jsx +94 -0
  268. package/registry/blocks/org-chart/index.js +7 -0
  269. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  270. package/registry/blocks/org-chart/org.js +245 -0
  271. package/registry/blocks/org-chart/person.jsx +96 -0
  272. package/registry/blocks/page-builder/README.md +257 -0
  273. package/registry/blocks/page-builder/block.json +14 -0
  274. package/registry/blocks/page-builder/demo.jsx +145 -0
  275. package/registry/blocks/page-builder/grapes.js +18 -0
  276. package/registry/blocks/page-builder/index.js +11 -0
  277. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  278. package/registry/blocks/page-builder/page-view.jsx +33 -0
  279. package/registry/blocks/page-builder/page.js +118 -0
  280. package/registry/blocks/page-builder/panels.jsx +588 -0
  281. package/registry/blocks/page-builder/sections.js +209 -0
  282. package/registry/blocks/page-builder/theme.js +87 -0
  283. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  284. package/registry/blocks/page-builder/tokens.js +329 -0
  285. package/registry/blocks/payment-methods/README.md +104 -0
  286. package/registry/blocks/payment-methods/block.json +10 -0
  287. package/registry/blocks/payment-methods/demo.jsx +71 -0
  288. package/registry/blocks/payment-methods/index.js +4 -0
  289. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  290. package/registry/blocks/pdf-document/README.md +213 -0
  291. package/registry/blocks/pdf-document/block.json +13 -0
  292. package/registry/blocks/pdf-document/demo.jsx +136 -0
  293. package/registry/blocks/pdf-document/index.js +33 -0
  294. package/registry/blocks/pdf-document/money.js +83 -0
  295. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  296. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  297. package/registry/blocks/pdf-document/quote.jsx +179 -0
  298. package/registry/blocks/pdf-document/theme.js +193 -0
  299. package/registry/blocks/pdf-viewer/README.md +191 -0
  300. package/registry/blocks/pdf-viewer/block.json +14 -0
  301. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  302. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  303. package/registry/blocks/pdf-viewer/index.js +8 -0
  304. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  305. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  306. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  307. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  308. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  309. package/registry/blocks/product-detail/README.md +217 -0
  310. package/registry/blocks/product-detail/block.json +10 -0
  311. package/registry/blocks/product-detail/demo.jsx +233 -0
  312. package/registry/blocks/product-detail/index.js +7 -0
  313. package/registry/blocks/product-detail/price.jsx +115 -0
  314. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  315. package/registry/blocks/product-detail/product-media.jsx +102 -0
  316. package/registry/blocks/product-detail/product-options.jsx +144 -0
  317. package/registry/blocks/product-grid/README.md +162 -0
  318. package/registry/blocks/product-grid/block.json +10 -0
  319. package/registry/blocks/product-grid/demo.jsx +255 -0
  320. package/registry/blocks/product-grid/index.js +5 -0
  321. package/registry/blocks/product-grid/product-card.jsx +232 -0
  322. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  323. package/registry/blocks/record-form/README.md +196 -0
  324. package/registry/blocks/record-form/block.json +10 -0
  325. package/registry/blocks/record-form/demo.jsx +525 -0
  326. package/registry/blocks/record-form/index.js +4 -0
  327. package/registry/blocks/record-form/record-fields.jsx +457 -0
  328. package/registry/blocks/record-form/record-form.jsx +415 -0
  329. package/registry/blocks/record-form/rules.js +81 -0
  330. package/registry/blocks/record-notes/README.md +139 -0
  331. package/registry/blocks/record-notes/block.json +10 -0
  332. package/registry/blocks/record-notes/demo.jsx +179 -0
  333. package/registry/blocks/record-notes/index.js +4 -0
  334. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  335. package/registry/blocks/search-dialog/README.md +108 -0
  336. package/registry/blocks/search-dialog/block.json +10 -0
  337. package/registry/blocks/search-dialog/demo.jsx +116 -0
  338. package/registry/blocks/search-dialog/index.js +3 -0
  339. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  340. package/registry/blocks/settings-list/README.md +171 -0
  341. package/registry/blocks/settings-list/block.json +10 -0
  342. package/registry/blocks/settings-list/demo.jsx +333 -0
  343. package/registry/blocks/settings-list/index.js +4 -0
  344. package/registry/blocks/settings-list/row-state.jsx +93 -0
  345. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  346. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  347. package/registry/blocks/setup-checklist/README.md +142 -0
  348. package/registry/blocks/setup-checklist/block.json +10 -0
  349. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  350. package/registry/blocks/setup-checklist/index.js +4 -0
  351. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  352. package/registry/blocks/share-dialog/README.md +113 -0
  353. package/registry/blocks/share-dialog/block.json +10 -0
  354. package/registry/blocks/share-dialog/demo.jsx +140 -0
  355. package/registry/blocks/share-dialog/index.js +3 -0
  356. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  357. package/registry/blocks/sidebar/README.md +190 -0
  358. package/registry/blocks/sidebar/block.json +43 -0
  359. package/registry/blocks/sidebar/demo.jsx +577 -0
  360. package/registry/blocks/sidebar/index.js +4 -0
  361. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  362. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  363. package/registry/blocks/signature-pad/README.md +137 -0
  364. package/registry/blocks/signature-pad/block.json +13 -0
  365. package/registry/blocks/signature-pad/colors.js +115 -0
  366. package/registry/blocks/signature-pad/demo.jsx +94 -0
  367. package/registry/blocks/signature-pad/index.js +6 -0
  368. package/registry/blocks/signature-pad/pad.js +7 -0
  369. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  370. package/registry/blocks/signature-pad/signature.js +68 -0
  371. package/registry/blocks/sketch-canvas/README.md +280 -0
  372. package/registry/blocks/sketch-canvas/block.json +13 -0
  373. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  374. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  375. package/registry/blocks/sketch-canvas/index.js +9 -0
  376. package/registry/blocks/sketch-canvas/palette.js +226 -0
  377. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  378. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  379. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  380. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  381. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  382. package/registry/blocks/sketch-canvas/theme.js +131 -0
  383. package/registry/blocks/spreadsheet/README.md +307 -0
  384. package/registry/blocks/spreadsheet/block.json +13 -0
  385. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  386. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  387. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  388. package/registry/blocks/spreadsheet/grid.js +387 -0
  389. package/registry/blocks/spreadsheet/index.js +34 -0
  390. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  391. package/registry/blocks/spreadsheet/types.js +473 -0
  392. package/registry/blocks/stat-cards/README.md +173 -0
  393. package/registry/blocks/stat-cards/block.json +10 -0
  394. package/registry/blocks/stat-cards/demo.jsx +257 -0
  395. package/registry/blocks/stat-cards/index.js +4 -0
  396. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  397. package/registry/blocks/stat-cards/usage.jsx +243 -0
  398. package/registry/blocks/task-list/README.md +176 -0
  399. package/registry/blocks/task-list/block.json +10 -0
  400. package/registry/blocks/task-list/demo.jsx +134 -0
  401. package/registry/blocks/task-list/index.js +5 -0
  402. package/registry/blocks/task-list/task-list.jsx +907 -0
  403. package/registry/blocks/task-model/README.md +455 -0
  404. package/registry/blocks/task-model/block.json +167 -0
  405. package/registry/blocks/task-model/changes.js +89 -0
  406. package/registry/blocks/task-model/dates.js +371 -0
  407. package/registry/blocks/task-model/demo.jsx +215 -0
  408. package/registry/blocks/task-model/dnd.jsx +240 -0
  409. package/registry/blocks/task-model/index.js +97 -0
  410. package/registry/blocks/task-model/model.js +919 -0
  411. package/registry/blocks/task-model/parts.jsx +449 -0
  412. package/registry/blocks/task-model/toolbar.jsx +271 -0
  413. package/registry/blocks/testimonials/README.md +139 -0
  414. package/registry/blocks/testimonials/block.json +11 -0
  415. package/registry/blocks/testimonials/demo.jsx +137 -0
  416. package/registry/blocks/testimonials/index.js +4 -0
  417. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  418. package/registry/blocks/transaction-list/README.md +126 -0
  419. package/registry/blocks/transaction-list/block.json +10 -0
  420. package/registry/blocks/transaction-list/demo.jsx +79 -0
  421. package/registry/blocks/transaction-list/index.js +4 -0
  422. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  423. package/registry/blocks/whiteboard/README.md +179 -0
  424. package/registry/blocks/whiteboard/block.json +10 -0
  425. package/registry/blocks/whiteboard/demo.jsx +169 -0
  426. package/registry/blocks/whiteboard/index.js +6 -0
  427. package/registry/blocks/whiteboard/templates.js +150 -0
  428. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  429. package/src/cli.mjs +19 -6
  430. package/src/install.mjs +18 -0
  431. package/src/registry.mjs +38 -4
  432. package/src/shadcn.mjs +14 -1
  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/ui/avatar.jsx +141 -0
  437. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  438. package/templates/next/files/components/ui/button-group.jsx +70 -0
  439. package/templates/next/files/components/ui/button.jsx +132 -12
  440. package/templates/next/files/components/ui/calendar.jsx +609 -0
  441. package/templates/next/files/components/ui/carousel.jsx +281 -0
  442. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  443. package/templates/next/files/components/ui/combobox.jsx +608 -0
  444. package/templates/next/files/components/ui/command.jsx +577 -0
  445. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  446. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  447. package/templates/next/files/components/ui/distribution.jsx +117 -0
  448. package/templates/next/files/components/ui/feedback.jsx +143 -0
  449. package/templates/next/files/components/ui/field.jsx +115 -3
  450. package/templates/next/files/components/ui/file-input.jsx +234 -0
  451. package/templates/next/files/components/ui/icon.jsx +130 -8
  452. package/templates/next/files/components/ui/image.jsx +143 -0
  453. package/templates/next/files/components/ui/index.js +47 -2
  454. package/templates/next/files/components/ui/input-group.jsx +213 -0
  455. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  456. package/templates/next/files/components/ui/item.jsx +206 -0
  457. package/templates/next/files/components/ui/menu.jsx +454 -82
  458. package/templates/next/files/components/ui/notice.jsx +126 -14
  459. package/templates/next/files/components/ui/pagination.jsx +156 -0
  460. package/templates/next/files/components/ui/popover.jsx +284 -0
  461. package/templates/next/files/components/ui/radio.jsx +193 -0
  462. package/templates/next/files/components/ui/rating.jsx +131 -0
  463. package/templates/next/files/components/ui/resizable.jsx +338 -0
  464. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  465. package/templates/next/files/components/ui/separator.jsx +119 -0
  466. package/templates/next/files/components/ui/sheet.jsx +96 -11
  467. package/templates/next/files/components/ui/slider.jsx +174 -0
  468. package/templates/next/files/components/ui/stat.jsx +574 -0
  469. package/templates/next/files/components/ui/steps.jsx +338 -0
  470. package/templates/next/files/components/ui/swatch.jsx +33 -0
  471. package/templates/next/files/components/ui/table.jsx +130 -0
  472. package/templates/next/files/components/ui/toast.jsx +440 -0
  473. package/templates/next/files/components/ui/toggle.jsx +195 -0
  474. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  475. package/templates/next/template.json +264 -8
@@ -0,0 +1,101 @@
1
+ // Positions in a text, and the problems ("diagnostics") drawn on it.
2
+ //
3
+ // Plain functions of strings, so they run in node and on the server. The
4
+ // editor counts in offsets (0-based characters from the start); people and
5
+ // databases count in lines and columns (1-based). Both are accepted here.
6
+
7
+ /** Offset → { line, col }, both 1-based. */
8
+ export function lineCol(text, offset) {
9
+ const s = String(text ?? "");
10
+ const at = Math.max(0, Math.min(s.length, offset | 0));
11
+ let line = 1;
12
+ let start = 0;
13
+ for (let i = 0; i < at; i++) {
14
+ if (s.charCodeAt(i) === 10) {
15
+ line++;
16
+ start = i + 1;
17
+ }
18
+ }
19
+ return { line, col: at - start + 1 };
20
+ }
21
+
22
+ /** { line, col } (1-based) → offset, clamped into the text. A missing col
23
+ * is the start of the line. */
24
+ export function offsetOf(text, line, col = 1) {
25
+ const s = String(text ?? "");
26
+ let at = 0;
27
+ for (let n = 1; n < Math.max(1, line | 0); n++) {
28
+ const next = s.indexOf("\n", at);
29
+ if (next < 0) return s.length;
30
+ at = next + 1;
31
+ }
32
+ const end = s.indexOf("\n", at);
33
+ const lineEnd = end < 0 ? s.length : end;
34
+ return Math.min(lineEnd, at + Math.max(0, (col | 0) - 1));
35
+ }
36
+
37
+ /** The start and end offsets of line `line` (1-based). */
38
+ export function lineRange(text, line) {
39
+ const s = String(text ?? "");
40
+ const from = offsetOf(s, line, 1);
41
+ const end = s.indexOf("\n", from);
42
+ return { from, to: end < 0 ? s.length : end };
43
+ }
44
+
45
+ const SEVERITIES = new Set(["error", "warning", "info", "hint"]);
46
+
47
+ /**
48
+ * The problems a caller hands the editor, made exact: each one gets
49
+ * `from`/`to` offsets inside the text. A problem may say where it is as
50
+ * { from, to } offsets, or
51
+ * { line, col?, endLine?, endCol? } 1-based; no col = the whole line,
52
+ * { position } a 1-based character position, as
53
+ * Postgres reports an error
54
+ * plus `message` and `severity` ("error" default · "warning" · "info").
55
+ * An empty range is widened to the word under it (or one character), so
56
+ * there is always something to underline.
57
+ */
58
+ export function normalizeDiagnostics(text, list) {
59
+ const s = String(text ?? "");
60
+ const out = [];
61
+ for (const d of list ?? []) {
62
+ if (!d || !d.message) continue;
63
+ let from;
64
+ let to;
65
+ if (Number.isFinite(d.from)) {
66
+ from = d.from;
67
+ to = Number.isFinite(d.to) ? d.to : d.from;
68
+ } else if (Number.isFinite(d.position)) {
69
+ from = d.position - 1;
70
+ to = from;
71
+ } else if (Number.isFinite(d.line)) {
72
+ if (Number.isFinite(d.col)) {
73
+ from = offsetOf(s, d.line, d.col);
74
+ to = Number.isFinite(d.endLine) ? offsetOf(s, d.endLine, d.endCol ?? 1) : Number.isFinite(d.endCol) ? offsetOf(s, d.line, d.endCol) : from;
75
+ } else {
76
+ ({ from, to } = lineRange(s, d.line));
77
+ }
78
+ } else {
79
+ from = 0;
80
+ to = 0;
81
+ }
82
+ from = Math.max(0, Math.min(s.length, from));
83
+ to = Math.max(from, Math.min(s.length, to));
84
+ if (to === from) ({ from, to } = wordAt(s, from));
85
+ out.push({ from, to, severity: SEVERITIES.has(d.severity) ? d.severity : "error", message: String(d.message), source: d.source });
86
+ }
87
+ return out;
88
+ }
89
+
90
+ /** The word (letters, digits, _ $ .) at `at`, else one character. */
91
+ export function wordAt(text, at) {
92
+ const s = String(text ?? "");
93
+ const W = /[\w$.]/;
94
+ let from = at;
95
+ let to = at;
96
+ while (from > 0 && W.test(s[from - 1])) from--;
97
+ while (to < s.length && W.test(s[to])) to++;
98
+ if (to === from) to = Math.min(s.length, from + 1);
99
+ if (to === from && from > 0) from--;
100
+ return { from, to };
101
+ }
@@ -0,0 +1,186 @@
1
+ // CodeMirror in the workspace theme — the one place its look is mapped.
2
+ //
3
+ // CodeMirror styles itself with CSS it writes at run time, so its theme is
4
+ // CSS too: every colour below is `var(--color-…)`, the workspace's own
5
+ // token, read by the browser. Nothing is resolved in JavaScript, so a
6
+ // change of theme or of light/dark repaints the editor with no work here.
7
+ //
8
+ // Syntax colours are categories, not status, so they come from the chart
9
+ // hues (--color-chart-1 is the primary): keywords chart-1 and a little
10
+ // heavier (in a theme whose primary is its ink, weight still sets them
11
+ // apart), text in quotes chart-2, numbers and true/false/null chart-3,
12
+ // functions chart-4, names of columns, keys and types chart-5. Comments
13
+ // and punctuation step back into muted-foreground.
14
+ import { EditorView, HighlightStyle, tags as t } from "./codemirror";
15
+
16
+ const v = (token) => `var(--color-${token})`;
17
+
18
+ export const editorTheme = EditorView.theme({
19
+ "&": {
20
+ color: v("foreground"),
21
+ backgroundColor: "transparent",
22
+ fontSize: "var(--code-editor-size, 13px)",
23
+ },
24
+ "&.cm-focused": { outline: "none" },
25
+ ".cm-scroller": {
26
+ fontFamily: "var(--font-mono)",
27
+ lineHeight: "1.65",
28
+ overflow: "auto",
29
+ },
30
+ ".cm-content": {
31
+ padding: "10px 0",
32
+ caretColor: v("foreground"),
33
+ },
34
+ ".cm-line": { padding: "0 16px 0 12px" },
35
+ ".cm-cursor, .cm-dropCursor": { borderLeftColor: v("foreground"), borderLeftWidth: "2px" },
36
+ // Selection sits under the text (drawSelection), so an opaque tint reads.
37
+ ".cm-selectionBackground": { backgroundColor: v("accent") },
38
+ "&.cm-focused .cm-selectionBackground, &.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-content ::selection": {
39
+ backgroundColor: v("accent"),
40
+ },
41
+ ".cm-selectionMatch": { backgroundColor: v("muted"), borderRadius: "2px" },
42
+ "&.cm-focused .cm-matchingBracket": { backgroundColor: "transparent", outline: `1px solid ${v("muted-foreground")}`, borderRadius: "2px" },
43
+ "&.cm-focused .cm-nonmatchingBracket": { backgroundColor: "transparent", outline: `1px solid ${v("destructive")}`, borderRadius: "2px" },
44
+ ".cm-placeholder": { color: v("muted-foreground"), fontStyle: "normal" },
45
+
46
+ // The gutter: quiet numbers, the current one in ink.
47
+ ".cm-gutters": {
48
+ backgroundColor: "transparent",
49
+ color: v("muted-foreground"),
50
+ border: "none",
51
+ fontVariantNumeric: "tabular-nums",
52
+ },
53
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 4px 0 14px", minWidth: "36px", opacity: "0.7" },
54
+ ".cm-activeLineGutter": { backgroundColor: "transparent", color: v("foreground") },
55
+ ".cm-activeLineGutter.cm-gutterElement": { opacity: "1" },
56
+ ".cm-foldGutter .cm-gutterElement": { padding: "0 2px", cursor: "pointer" },
57
+ ".cm-fold-marker": {
58
+ display: "inline-grid",
59
+ placeItems: "center",
60
+ width: "14px",
61
+ height: "100%",
62
+ color: v("muted-foreground"),
63
+ transition: "transform 150ms ease, color 150ms ease",
64
+ },
65
+ ".cm-fold-marker:hover": { color: v("foreground") },
66
+ ".cm-fold-marker[data-open='false']": { transform: "rotate(-90deg)" },
67
+ ".cm-foldPlaceholder": {
68
+ backgroundColor: v("muted"),
69
+ border: "none",
70
+ color: v("muted-foreground"),
71
+ borderRadius: "4px",
72
+ padding: "0 6px",
73
+ margin: "0 2px",
74
+ },
75
+
76
+ // Problems: a wavy line under the text, a dot in the gutter.
77
+ ".cm-lintRange": { backgroundImage: "none", textDecorationLine: "underline", textDecorationStyle: "wavy", textDecorationSkipInk: "none", textUnderlineOffset: "3px" },
78
+ ".cm-lintRange-error": { textDecorationColor: v("destructive") },
79
+ ".cm-lintRange-warning": { textDecorationColor: v("warning") },
80
+ ".cm-lintRange-info, .cm-lintRange-hint": { textDecorationColor: v("info") },
81
+ ".cm-gutter-lint": { width: "14px" },
82
+ ".cm-gutter-lint .cm-gutterElement": { padding: "0", display: "grid", placeItems: "center" },
83
+ ".cm-lint-marker": { content: "normal", width: "6px", height: "6px", borderRadius: "9999px" },
84
+ // CodeMirror sets its icon as `content: url(…)` on each kind; ours is the dot.
85
+ ".cm-lint-marker-error": { content: "normal", backgroundColor: v("destructive") },
86
+ ".cm-lint-marker-warning": { content: "normal", backgroundColor: v("warning") },
87
+ ".cm-lint-marker-info": { content: "normal", backgroundColor: v("info") },
88
+
89
+ // Every floating panel: the popover surface and a hairline (the shadow
90
+ // is the kit's shadow-lg, set on the wrapper in code-editor.jsx).
91
+ ".cm-tooltip": {
92
+ backgroundColor: v("popover"),
93
+ color: v("popover-foreground"),
94
+ border: `1px solid ${v("border")}`,
95
+ borderRadius: "var(--radius-md)",
96
+ },
97
+ ".cm-tooltip.cm-tooltip-autocomplete > ul": {
98
+ fontFamily: "var(--font-mono)",
99
+ maxHeight: "16em",
100
+ padding: "4px",
101
+ },
102
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > li": {
103
+ padding: "3px 8px",
104
+ borderRadius: "4px",
105
+ lineHeight: "1.6",
106
+ display: "flex",
107
+ alignItems: "center",
108
+ gap: "6px",
109
+ },
110
+ ".cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]": {
111
+ backgroundColor: v("accent"),
112
+ color: v("accent-foreground"),
113
+ },
114
+ ".cm-completionLabel": { flex: "0 1 auto" },
115
+ ".cm-completionMatchedText": { textDecoration: "none", fontWeight: "600", color: v("foreground") },
116
+ ".cm-completionDetail": { marginLeft: "auto", paddingLeft: "12px", fontStyle: "normal", color: v("muted-foreground"), fontSize: "0.9em" },
117
+ ".cm-completionIcon": { width: "1.1em", opacity: "0.7", paddingRight: "0", color: v("muted-foreground"), fontSize: "0.85em" },
118
+ ".cm-completionIcon-keyword:after": { content: "'K'" },
119
+ ".cm-completionIcon-type:after": { content: "'T'" },
120
+ ".cm-completionIcon-property:after": { content: "'·'" },
121
+ ".cm-completionIcon-namespace:after": { content: "'S'" },
122
+ ".cm-completionInfo": {
123
+ backgroundColor: v("popover"),
124
+ color: v("popover-foreground"),
125
+ border: `1px solid ${v("border")}`,
126
+ borderRadius: "var(--radius-md)",
127
+ padding: "6px 10px",
128
+ fontFamily: "var(--font-sans)",
129
+ maxWidth: "280px",
130
+ },
131
+ ".cm-tooltip-lint": { padding: "2px" },
132
+ ".cm-diagnostic": { fontFamily: "var(--font-sans)", padding: "6px 10px", borderLeft: "3px solid transparent", borderRadius: "4px" },
133
+ ".cm-diagnostic-error": { borderLeftColor: v("destructive") },
134
+ ".cm-diagnostic-warning": { borderLeftColor: v("warning") },
135
+ ".cm-diagnostic-info, .cm-diagnostic-hint": { borderLeftColor: v("info") },
136
+
137
+ // Find and replace (Cmd/Ctrl+F): our fields and buttons, not the default grey.
138
+ ".cm-panels": { backgroundColor: v("card"), color: v("foreground") },
139
+ ".cm-panels.cm-panels-top": { borderBottom: `1px solid ${v("border")}` },
140
+ ".cm-panels.cm-panels-bottom": { borderTop: `1px solid ${v("border")}` },
141
+ ".cm-panel.cm-search": { padding: "8px 12px", fontFamily: "var(--font-sans)", fontSize: "13px", display: "flex", flexWrap: "wrap", alignItems: "center", gap: "6px" },
142
+ ".cm-panel.cm-search br": { display: "none" },
143
+ ".cm-panel.cm-search label": { display: "inline-flex", alignItems: "center", gap: "4px", color: v("muted-foreground") },
144
+ ".cm-panel.cm-search [name=close]": { position: "static", marginLeft: "auto", color: v("muted-foreground"), fontSize: "18px", padding: "0 6px" },
145
+ ".cm-textfield": {
146
+ backgroundColor: v("background"),
147
+ color: v("foreground"),
148
+ border: `1px solid ${v("input")}`,
149
+ borderRadius: "var(--radius-sm)",
150
+ padding: "4px 8px",
151
+ margin: "0",
152
+ fontSize: "13px",
153
+ },
154
+ ".cm-textfield:focus": { outline: `2px solid ${v("ring")}`, outlineOffset: "0" },
155
+ ".cm-button": {
156
+ backgroundImage: "none",
157
+ backgroundColor: v("secondary"),
158
+ color: v("secondary-foreground"),
159
+ border: `1px solid ${v("border")}`,
160
+ borderRadius: "var(--radius-sm)",
161
+ padding: "4px 10px",
162
+ margin: "0",
163
+ fontSize: "13px",
164
+ },
165
+ ".cm-button:hover": { backgroundColor: v("accent") },
166
+ ".cm-button:active": { backgroundImage: "none" },
167
+ ".cm-searchMatch": { backgroundColor: v("muted"), outline: `1px solid ${v("border")}`, borderRadius: "2px" },
168
+ ".cm-searchMatch.cm-searchMatch-selected": { backgroundColor: v("accent"), outline: `1px solid ${v("muted-foreground")}` },
169
+
170
+ // The statement that just ran, lit for a moment.
171
+ ".cm-ran": { backgroundColor: v("accent"), borderRadius: "2px", transition: "background-color 400ms ease" },
172
+ });
173
+
174
+ export const highlightStyle = HighlightStyle.define([
175
+ { tag: [t.keyword, t.operatorKeyword, t.modifier, t.controlKeyword, t.definitionKeyword], color: v("chart-1"), fontWeight: "600" },
176
+ { tag: [t.string, t.special(t.string), t.regexp], color: v("chart-2") },
177
+ { tag: [t.number, t.bool, t.null, t.atom], color: v("chart-3") },
178
+ { tag: [t.function(t.variableName), t.function(t.propertyName), t.standard(t.name)], color: v("chart-4") },
179
+ { tag: [t.propertyName, t.typeName, t.className, t.special(t.name), t.labelName], color: v("chart-5") },
180
+ { tag: [t.comment, t.lineComment, t.blockComment], color: v("muted-foreground"), fontStyle: "italic" },
181
+ { tag: [t.punctuation, t.separator, t.bracket, t.operator, t.derefOperator], color: v("muted-foreground") },
182
+ { tag: t.invalid, color: v("destructive") },
183
+ { tag: t.strong, fontWeight: "600" },
184
+ { tag: t.emphasis, fontStyle: "italic" },
185
+ { tag: t.link, textDecoration: "underline" },
186
+ ]);
@@ -0,0 +1,123 @@
1
+ # CommentBox
2
+
3
+ A comment field that takes rich text: select a word for bold, italic or a
4
+ link, start a line with `-` for a list, type `@` to mention a teammate
5
+ (they go in as a chip). Cmd/Ctrl+Enter posts, as does the Post button.
6
+ While a post is on its way the box is locked; when it fails the words
7
+ stay and the box says why; when it lands the box clears. Give it
8
+ `comments` and it draws the thread above: avatar, name, "5 min ago", the
9
+ body with its formatting and mentions.
10
+
11
+ It is `doc-editor` in its minimal mode (no `/` menu, no drag handles), so
12
+ a comment is BlockNote JSON — the same doc every text block uses.
13
+
14
+ ```jsx
15
+ import { CommentBox } from "../components/blocks/comment-box"; // a Makersclaw app ("./blocks/comment-box" from components/)
16
+ import { CommentBox } from "@/components/makersclaw/blocks/comment-box"; // a shadcn project
17
+ ```
18
+
19
+ It is a client component: render it from a `"use client"` component, and
20
+ load the thread in the server surface (README §4). `makersclaw add
21
+ comment-box` adds `doc-editor` with it (and its npm packages: run
22
+ `npm install` after).
23
+
24
+ ## The data
25
+
26
+ A comment in `comments`:
27
+
28
+ ```js
29
+ {
30
+ id: "c-81",
31
+ author: { id: "u-lena", name: "Lena Fischer", src: "https://…/lena.jpg" }, // or just "Lena Fischer"
32
+ body: [ /* the doc onPost gave you */ ], // or a plain string
33
+ createdAt: "2026-09-23T09:12:00Z", // ISO string, Date or ms
34
+ edited: false, // true adds "(edited)"
35
+ }
36
+ ```
37
+
38
+ Store `body` as it came out of `onPost` (a `jsonb` column). Keep a plain
39
+ copy beside it for search and notifications: `docToText(doc)` from
40
+ `doc-editor`. The people mentioned are `docMentions(doc)` — notify them.
41
+
42
+ ## Props
43
+
44
+ - `onPost(doc)` — required. `async`, returns `{ ok: true }` or
45
+ `{ ok: false, error? }` (`error` is shown under the box; without it,
46
+ "Couldn't post…"). A throw counts as a failure. Only an ok clears the
47
+ box. An empty box never posts.
48
+ - `comments` — the thread, oldest first, drawn above the box. Leave it out
49
+ for the field alone; `[]` shows `emptyText`.
50
+ - `author` — `{ name, src? }`, who is writing: their avatar sits beside
51
+ the box from 640px.
52
+ - `mentions` — `async (query) => [{ id, label, description? }]`: turns on
53
+ `@` (doc-editor's `mentions`).
54
+ - `placeholder` — `"Write a comment…"`.
55
+ - `postLabel` — the button, `"Post"` ("Reply", "Send").
56
+ - `label` — the field's accessible name, `"Comment"`.
57
+ - `threadLabel` — the list's accessible name, `"Comments"`.
58
+ - `emptyText` — `"No comments yet."`.
59
+ - `autoFocus` — `false`.
60
+ - `disabled` — `false`; `true` locks the box (no edit, no post).
61
+ - `className` — layout around it.
62
+
63
+ The other exports, for a thread of your own:
64
+
65
+ - `CommentComposer` — the field and its buttons: `onSubmit(doc)` (same
66
+ answer as `onPost`), `author`, `mentions`, `defaultValue` (a doc to
67
+ start from — editing a comment), `placeholder`, `submitLabel`
68
+ (`"Post"`), `submitIcon` (a kit icon name, `"send"`; `null` for none),
69
+ `busyLabel` (shown while it runs), `failedText`,
70
+ `onCancel` (adds a Cancel button), `cancelLabel`, `label`,
71
+ `autoFocus`, `disabled`, `clearOnSubmit` (`true`; `false` when the
72
+ composer goes away after a save), `className`.
73
+ - `CommentBody` — `{ doc, className }`: a doc drawn read-only as plain
74
+ HTML (server too): paragraphs, headings, lists, checklists, quotes,
75
+ code, tables, links, image links, mentions and fields as chips.
76
+ - `CommentTime` — `{ date, className }`: a `<time>`; the absolute date on
77
+ the server, "5 min ago" once mounted, kept current each minute.
78
+
79
+ ## Example
80
+
81
+ ```jsx
82
+ // components/TaskComments.jsx — client
83
+ "use client";
84
+ import { useState } from "react";
85
+ import { insertRow } from "../lib/actions";
86
+ import { CommentBox } from "./blocks/comment-box";
87
+ import { docToText } from "./blocks/doc-editor";
88
+
89
+ export default function TaskComments({ task, me, team, initial }) {
90
+ const [comments, setComments] = useState(initial);
91
+ const findPeople = async (q) =>
92
+ team.filter((p) => p.name.toLowerCase().includes(q.toLowerCase())).map((p) => ({ id: p.id, label: p.name }));
93
+
94
+ async function post(doc) {
95
+ const res = await insertRow({
96
+ source: "public.comments",
97
+ values: { task_id: task.id, author_id: me.id, body: doc, body_text: docToText(doc) },
98
+ });
99
+ if (!res.ok) return { ok: false, error: res.error };
100
+ setComments((c) => [...c, { id: res.id, author: me, body: doc, createdAt: new Date() }]);
101
+ return { ok: true };
102
+ }
103
+
104
+ return <CommentBox comments={comments} onPost={post} author={me} mentions={findPeople} />;
105
+ }
106
+ ```
107
+
108
+ ## What it will not do
109
+
110
+ - Edit or delete a posted comment, react, or reply in a nested thread: the
111
+ thread is read-only. Notes you keep, edit and delete on a record are
112
+ `record-notes`; build a richer thread from `CommentComposer` +
113
+ `CommentBody` in your own component.
114
+ - Attach files or images, or offer a `/` menu: it is a comment, not a
115
+ document (`doc-editor` for that).
116
+ - Notify anyone: read the mentions off the doc (`docMentions`) and send
117
+ them yourself.
118
+ - Load older comments or scroll the thread: it draws what it is given;
119
+ put it in a scrolling box and page it yourself.
120
+
121
+ An editor it cannot be is your own component in `components/` — not an
122
+ edit to this block. Its files are fixed: `npm run check` refuses a
123
+ change, and `makersclaw add comment-box` restores them.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "comment-box",
3
+ "title": "CommentBox",
4
+ "description": "A minimal rich comment field (DocEditor in minimal mode): bold, italic, links and lists from the selection toolbar or markdown shortcuts, @mentions as chips, Cmd/Ctrl+Enter to post. It posts through an async onPost(doc) that answers { ok }, keeps the draft and says why when it fails, and clears when it lands. With `comments` it draws the thread above it: avatar, name, relative time, the rich body. Also exports the composer alone, the read-only body renderer and the timestamp.",
5
+ "useWhen": "People comment on something in the app: a task, a design, a document, an approval, a support ticket; a reply field with @mentions under a thread. Not dated notes kept on a record with edit and delete (record-notes), not a conversation with an assistant (chat), not a long document (doc-editor, doc-page).",
6
+ "tags": ["comment", "comments", "thread", "reply", "mention", "composer", "discussion", "feedback", "rich text", "blocknote", "cmd enter"],
7
+ "exports": ["CommentBox", "CommentComposer", "CommentBody", "CommentTime"],
8
+ "files": ["index.js", "comment-box.jsx", "comment-body.jsx", "comment-time.jsx"],
9
+ "requires": ["doc-editor"]
10
+ }
@@ -0,0 +1,217 @@
1
+ // CommentBody — a posted doc, drawn read-only as plain React.
2
+ //
3
+ // Why not a read-only DocEditor: a thread is many small docs, and one
4
+ // BlockNote editor per comment is heavy and paints only after mount. This
5
+ // walks the same JSON (the shapes doc-editor's README lists) and renders
6
+ // on the server too. Mentions and fields look like the editor's chips.
7
+ // A block type it does not know shows its text, never nothing.
8
+ import { Fragment } from "react";
9
+ import { Icon, Separator, cx } from "../../ui";
10
+
11
+ const noText = (content) => inlineOf(content).every((c) => c?.type === "text" && !(c.text ?? "").trim());
12
+
13
+ const CHIP = "inline-flex items-baseline rounded-sm px-1 font-medium whitespace-nowrap";
14
+
15
+ /** The inline pieces of a block's content, whatever shape it came in. */
16
+ function inlineOf(content) {
17
+ if (typeof content === "string") return [{ type: "text", text: content, styles: {} }];
18
+ return Array.isArray(content) ? content : [];
19
+ }
20
+
21
+ function styled(text, styles, key) {
22
+ let node = text;
23
+ const s = styles ?? {};
24
+ if (s.code) node = <code className="rounded-sm bg-muted px-1 font-mono text-[0.9em]">{node}</code>;
25
+ if (s.bold) node = <strong className="font-semibold">{node}</strong>;
26
+ if (s.italic) node = <em>{node}</em>;
27
+ if (s.underline) node = <u>{node}</u>;
28
+ if (s.strike) node = <s>{node}</s>;
29
+ return <Fragment key={key}>{node}</Fragment>;
30
+ }
31
+
32
+ const safeHref = (href) => (typeof href === "string" && /^(https?:|mailto:|tel:|\/|#)/i.test(href.trim()) ? href.trim() : undefined);
33
+
34
+ function Inline({ content }) {
35
+ return inlineOf(content).map((c, i) => {
36
+ if (!c || typeof c !== "object") return null;
37
+ if (c.type === "text") return styled(c.text ?? "", c.styles, i);
38
+ if (c.type === "link")
39
+ return (
40
+ <a key={i} href={safeHref(c.href)} target="_blank" rel="noreferrer noopener" className="text-primary underline underline-offset-2">
41
+ <Inline content={c.content} />
42
+ </a>
43
+ );
44
+ if (c.type === "mention")
45
+ return (
46
+ <span key={i} className={cx(CHIP, "bg-primary/10 text-primary")} data-mention={c.props?.id}>
47
+ @{c.props?.label || c.props?.id}
48
+ </span>
49
+ );
50
+ if (c.type === "field")
51
+ return (
52
+ <span key={i} className={cx(CHIP, "border border-dashed border-border bg-muted text-muted-foreground")} title={`{${c.props?.key ?? ""}}`}>
53
+ {c.props?.label || c.props?.key}
54
+ </span>
55
+ );
56
+ return Array.isArray(c.content) ? <Inline key={i} content={c.content} /> : null;
57
+ });
58
+ }
59
+
60
+ const LISTS = { bulletListItem: "ul", numberedListItem: "ol", checkListItem: "ul", toggleListItem: "ul" };
61
+ const LIST_CLASS = {
62
+ bulletListItem: "list-disc ps-5",
63
+ numberedListItem: "list-decimal ps-5",
64
+ checkListItem: "",
65
+ toggleListItem: "list-disc ps-5",
66
+ };
67
+
68
+ function Children({ blocks }) {
69
+ return Array.isArray(blocks) && blocks.length ? (
70
+ <div className="mt-1 grid gap-1 ps-4">
71
+ <Blocks blocks={blocks} />
72
+ </div>
73
+ ) : null;
74
+ }
75
+
76
+ function ListItem({ block }) {
77
+ if (block.type === "checkListItem") {
78
+ const done = !!block.props?.checked;
79
+ return (
80
+ <li className="flex items-start gap-2">
81
+ <Icon name={done ? "check-circle" : "circle"} size={16} className={cx("mt-0.5 shrink-0", done ? "text-primary" : "text-muted-foreground")} />
82
+ <span className="sr-only">{done ? "Done: " : "To do: "}</span>
83
+ <div className={cx("min-w-0", done && "text-muted-foreground line-through")}>
84
+ <Inline content={block.content} />
85
+ <Children blocks={block.children} />
86
+ </div>
87
+ </li>
88
+ );
89
+ }
90
+ return (
91
+ <li>
92
+ <Inline content={block.content} />
93
+ <Children blocks={block.children} />
94
+ </li>
95
+ );
96
+ }
97
+
98
+ function tableRows(content) {
99
+ return (content?.rows ?? []).map((r) => (r?.cells ?? []).map((cell) => cell?.content ?? cell));
100
+ }
101
+
102
+ function Block({ block }) {
103
+ const { type, props } = block;
104
+ switch (type) {
105
+ case "heading":
106
+ return (
107
+ <p className={cx("font-semibold", props?.level === 1 ? "text-base" : "text-sm")}>
108
+ <Inline content={block.content} />
109
+ </p>
110
+ );
111
+ case "quote":
112
+ return (
113
+ <blockquote className="border-s-2 border-border ps-3 text-muted-foreground">
114
+ <Inline content={block.content} />
115
+ </blockquote>
116
+ );
117
+ case "codeBlock":
118
+ return (
119
+ <pre className="overflow-x-auto rounded-md bg-muted p-2 font-mono text-xs">
120
+ <code>
121
+ <Inline content={block.content} />
122
+ </code>
123
+ </pre>
124
+ );
125
+ case "divider":
126
+ return <Separator className="my-1" />;
127
+ case "image": {
128
+ const src = safeHref(props?.url);
129
+ return src ? (
130
+ <a href={src} target="_blank" rel="noreferrer noopener" className="inline-flex items-center gap-1.5 text-primary underline underline-offset-2">
131
+ <Icon name="image" size={14} />
132
+ {props?.caption || props?.name || "Image"}
133
+ </a>
134
+ ) : null;
135
+ }
136
+ case "table": {
137
+ const rows = tableRows(block.content);
138
+ if (!rows.length) return null;
139
+ return (
140
+ <div className="overflow-x-auto">
141
+ {/* raw: a doc's table is data drawn as it was typed, not a kit Table of records */}
142
+ <table className="text-xs">
143
+ <tbody>
144
+ {rows.map((r, i) => (
145
+ <tr key={i} className="border-b border-border last:border-0">
146
+ {r.map((cell, j) => (
147
+ <td key={j} className={cx("px-2 py-1 align-top", i === 0 && "font-medium")}>
148
+ <Inline content={cell} />
149
+ </td>
150
+ ))}
151
+ </tr>
152
+ ))}
153
+ </tbody>
154
+ </table>
155
+ </div>
156
+ );
157
+ }
158
+ default: {
159
+ const empty = noText(block.content);
160
+ return (
161
+ <>
162
+ <p className={empty ? "min-h-5" : undefined}>
163
+ <Inline content={block.content} />
164
+ </p>
165
+ <Children blocks={block.children} />
166
+ </>
167
+ );
168
+ }
169
+ }
170
+ }
171
+
172
+ /** Consecutive list items of one kind become one list. */
173
+ function Blocks({ blocks }) {
174
+ const out = [];
175
+ let run = null;
176
+ (Array.isArray(blocks) ? blocks : []).forEach((b, i) => {
177
+ if (!b || typeof b !== "object") return;
178
+ const tag = LISTS[b.type];
179
+ if (tag) {
180
+ if (!run || run.type !== b.type) {
181
+ run = { type: b.type, tag, items: [], key: b.id ?? `l${i}` };
182
+ out.push(run);
183
+ }
184
+ run.items.push(b);
185
+ return;
186
+ }
187
+ run = null;
188
+ out.push(b);
189
+ });
190
+ return out.map((x, i) => {
191
+ if (x.items) {
192
+ const Tag = x.tag;
193
+ return (
194
+ <Tag key={x.key} className={cx("grid gap-0.5", LIST_CLASS[x.type])}>
195
+ {x.items.map((b, j) => (
196
+ <ListItem key={b.id ?? j} block={b} />
197
+ ))}
198
+ </Tag>
199
+ );
200
+ }
201
+ return <Block key={x.id ?? `b${i}`} block={x} />;
202
+ });
203
+ }
204
+
205
+ /** A doc to read: `doc` is BlockNote JSON, or a plain string (one
206
+ * paragraph per line). Trailing empty paragraphs are dropped. */
207
+ export function CommentBody({ doc, className }) {
208
+ let blocks = typeof doc === "string" ? doc.split("\n").map((line) => ({ type: "paragraph", content: line })) : Array.isArray(doc) ? doc : [];
209
+ let end = blocks.length;
210
+ while (end > 0 && blocks[end - 1]?.type === "paragraph" && noText(blocks[end - 1].content) && !blocks[end - 1].children?.length) end--;
211
+ blocks = blocks.slice(0, end);
212
+ return (
213
+ <div className={cx("grid gap-1 break-words text-sm", className)}>
214
+ <Blocks blocks={blocks} />
215
+ </div>
216
+ );
217
+ }