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,41 @@
1
+ // The FlowCanvas block — `makersclaw add flow-canvas`. Fixed: compose it
2
+ // through its props (README.md beside this file). The board helpers are
3
+ // plain functions and work anywhere, the server included. The canvas
4
+ // blocks built on this one (account-map, process-map, journey-map,
5
+ // idea-board…) import it, never @xyflow/react directly.
6
+ export { FlowCanvas, useFlowCanvas } from "./flow-canvas";
7
+ export { useCanvas } from "./context";
8
+ export { NodeShell, NodeHandles, EditableText } from "./nodes";
9
+ export { Palette, StickySwatch, ColorDot, ShapeGlyph } from "./chrome";
10
+ export { colorClasses } from "./theme";
11
+ export {
12
+ GRID,
13
+ COLORS,
14
+ STICKY_COLORS,
15
+ COLOR_NAMES,
16
+ SHAPES,
17
+ emptyBoard,
18
+ createNode,
19
+ createEdge,
20
+ cleanBoard,
21
+ readBoard,
22
+ boardToText,
23
+ boardToMarkdown,
24
+ describeNode,
25
+ nodeText,
26
+ autoLayout,
27
+ alignNodes,
28
+ distributeNodes,
29
+ duplicateNodes,
30
+ removeNodes,
31
+ frameContents,
32
+ frameOf,
33
+ nodeRect,
34
+ boardBounds,
35
+ snapPoint,
36
+ snapToCell,
37
+ fitFontSize,
38
+ historyInit,
39
+ historyReducer,
40
+ starterTemplates,
41
+ } from "./board";
@@ -0,0 +1,392 @@
1
+ "use client";
2
+
3
+ // The built-in node types — sticky, shape, text, frame, card, image — and
4
+ // the two pieces a block's own node types are made from:
5
+ //
6
+ // NodeShell the chrome every node wears: the selection box, the four
7
+ // connection dots that show on hover, the resize handles,
8
+ // the lock mark, and the whole-card drop target while a
9
+ // connector is being dragged. Wrap your node's body in it.
10
+ // EditableText words that edit in place, laid out the same way shown and
11
+ // edited so nothing jumps when a double-click starts typing.
12
+ //
13
+ // Colours are token names in the node's data (theme.js turns them into
14
+ // classes); nothing here holds a colour of its own.
15
+ import { useEffect, useLayoutEffect, useRef } from "react";
16
+ import { Handle, NodeResizer, Position } from "@xyflow/react";
17
+ import { Badge, Icon, Image, cx } from "../../ui";
18
+ import { TEXT_SIZE_PX, fitFontSize } from "./board";
19
+ import { useCanvas } from "./context";
20
+ import { EDGE, FILL, SOLID, STROKE, TINT, WASH, tone } from "./theme";
21
+
22
+ // The dots sit just outside each side, so they never cover the words.
23
+ const DOT =
24
+ "size-3! min-w-0! min-h-0! rounded-full! border-2! border-primary! bg-background! opacity-0 transition-[opacity,scale] duration-150 motion-reduce:transition-none " +
25
+ "hover:scale-125 group-hover/node:opacity-100 [[data-connecting=true]_&]:opacity-100 [[data-tool=connector]_&]:opacity-100";
26
+ const SIDES = [
27
+ [Position.Top, "top", "-top-2!"],
28
+ [Position.Right, "right", "-right-2!"],
29
+ [Position.Bottom, "bottom", "-bottom-2!"],
30
+ [Position.Left, "left", "-left-2!"],
31
+ ];
32
+ // While a connector is in the air (or the connector tool is on), the whole
33
+ // card is one big invisible handle: drop anywhere on it to connect.
34
+ const BODY =
35
+ "absolute! inset-0! top-0! left-0! size-full! min-w-0! min-h-0! [transform:none]! rounded-none! border-0! bg-transparent! opacity-0! z-10";
36
+
37
+ /** The four connection dots. NodeShell draws them; a node that does not
38
+ * use NodeShell must draw these, or connectors cannot reach it. */
39
+ export function NodeHandles() {
40
+ return SIDES.map(([pos, id, place]) => <Handle key={id} type="source" id={id} position={pos} className={cx(DOT, place)} />);
41
+ }
42
+
43
+ /**
44
+ * The chrome around a node. Props:
45
+ * id, selected from the node's props (React Flow passes them)
46
+ * locked data.locked: no resize, a lock mark when selected
47
+ * resizable true (default) · false; minWidth/minHeight (default
48
+ * 40/30), keepAspectRatio
49
+ * autoHeight the node's height follows its content (text, cards)
50
+ * handles false: nothing connects to this node
51
+ * ring false: no selection box (draw your own)
52
+ * className the body's layout (never colour)
53
+ */
54
+ export function NodeShell({
55
+ id,
56
+ selected,
57
+ locked = false,
58
+ resizable = true,
59
+ minWidth = 40,
60
+ minHeight = 30,
61
+ keepAspectRatio = false,
62
+ autoHeight = false,
63
+ handles = true,
64
+ ring = true,
65
+ className,
66
+ children,
67
+ }) {
68
+ const { api, tool, readOnly, connecting } = useCanvas();
69
+ return (
70
+ <div className={cx("group/node relative", autoHeight ? "w-full" : "size-full", className)}>
71
+ {children}
72
+ {ring ? (
73
+ <span
74
+ aria-hidden="true"
75
+ className={cx(
76
+ "pointer-events-none absolute -inset-1 rounded-md transition-shadow duration-150 motion-reduce:transition-none",
77
+ selected ? "ring-2 ring-primary" : "ring-0 group-hover/node:ring-1 group-hover/node:ring-primary/50",
78
+ )}
79
+ />
80
+ ) : null}
81
+ {resizable && !readOnly ? (
82
+ <NodeResizer
83
+ isVisible={Boolean(selected) && !locked}
84
+ minWidth={minWidth}
85
+ minHeight={minHeight}
86
+ keepAspectRatio={keepAspectRatio}
87
+ onResizeEnd={() => api?.commit("resize", [id])}
88
+ />
89
+ ) : null}
90
+ {handles && !readOnly ? <NodeHandles /> : null}
91
+ {handles && !readOnly && (connecting || tool === "connector") ? <Handle type="source" id="body" position={Position.Top} className={BODY} /> : null}
92
+ {locked && selected ? (
93
+ <span className="pointer-events-none absolute -top-3 -right-3 grid size-6 place-items-center rounded-full border border-border bg-background text-muted-foreground shadow-sm">
94
+ <Icon name="lock" size={12} label="Locked" />
95
+ </span>
96
+ ) : null}
97
+ </div>
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Words that edit in place. Shown and edited in the same box, with the
103
+ * same classes, so starting to type moves nothing.
104
+ * value, editing the words; true while being edited
105
+ * onChange(text) every keystroke (update the node's data)
106
+ * onDone() Esc, a click away, Enter (singleLine), ⌘Enter
107
+ * placeholder shown while empty (and while editing)
108
+ * singleLine Enter finishes (a title, a label)
109
+ * label the field's accessible name
110
+ */
111
+ export function EditableText({ value, editing, onChange, onDone, placeholder, singleLine = false, label, className, style }) {
112
+ const ref = useRef(null);
113
+ useLayoutEffect(() => {
114
+ const el = ref.current;
115
+ if (!editing || !el) return;
116
+ el.innerText = value ?? "";
117
+ el.focus({ preventScroll: true });
118
+ // The caret at the end of the words, not the start.
119
+ const range = document.createRange();
120
+ range.selectNodeContents(el);
121
+ range.collapse(false);
122
+ const sel = window.getSelection();
123
+ sel?.removeAllRanges();
124
+ sel?.addRange(range);
125
+ // Only when editing starts: typing must not reset the caret.
126
+ // eslint-disable-next-line react-hooks/exhaustive-deps
127
+ }, [editing]);
128
+
129
+ if (!editing) {
130
+ return (
131
+ <div className={className} style={style}>
132
+ {value ? value : placeholder ? <span className="text-muted-foreground">{placeholder}</span> : null}
133
+ </div>
134
+ );
135
+ }
136
+ return (
137
+ // raw: a contentEditable box, not the kit's Textarea — the words keep
138
+ // the exact size, place and wrapping they have on the card while they
139
+ // are typed (a field would add its own border, padding and height).
140
+ <div
141
+ ref={ref}
142
+ role="textbox"
143
+ aria-label={label}
144
+ aria-multiline={!singleLine}
145
+ contentEditable="plaintext-only"
146
+ suppressContentEditableWarning
147
+ data-placeholder={placeholder ?? ""}
148
+ className={cx(
149
+ className,
150
+ "nodrag nopan nowheel cursor-text select-text outline-none",
151
+ "empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
152
+ )}
153
+ style={style}
154
+ onInput={(e) => onChange?.(e.currentTarget.innerText.replace(/\n$/, ""))}
155
+ onPaste={(e) => {
156
+ // Plain text only, in browsers without plaintext-only.
157
+ e.preventDefault();
158
+ const text = e.clipboardData.getData("text/plain");
159
+ document.execCommand("insertText", false, singleLine ? text.replace(/\s*\n\s*/g, " ") : text);
160
+ }}
161
+ onKeyDown={(e) => {
162
+ e.stopPropagation();
163
+ if (e.nativeEvent.isComposing) return;
164
+ if (e.key === "Escape" || (e.key === "Enter" && (singleLine || e.metaKey || e.ctrlKey))) {
165
+ e.preventDefault();
166
+ e.currentTarget.blur();
167
+ }
168
+ }}
169
+ onBlur={() => onDone?.()}
170
+ onPointerDown={(e) => e.stopPropagation()}
171
+ />
172
+ );
173
+ }
174
+
175
+ // Editing helpers shared by the built-in nodes.
176
+ function useWords(id, key = "text") {
177
+ const { api, editingNode, readOnly } = useCanvas();
178
+ const editing = !readOnly && editingNode === id;
179
+ return {
180
+ editing,
181
+ onChange: (text) => api?.updateNodeData(id, { [key]: text }, { commit: false }),
182
+ onDone: () => api?.stopEditing(id),
183
+ };
184
+ }
185
+
186
+ // ── sticky ───────────────────────────────────────────────────────────────
187
+
188
+ export function StickyNode({ id, data, selected, width, height }) {
189
+ const w = width ?? 200;
190
+ const h = height ?? 200;
191
+ const words = useWords(id);
192
+ const hasMeta = Boolean(data?.meta);
193
+ const size = fitFontSize(data?.text, w - 28, h - 28 - (hasMeta ? 18 : 0), { max: Math.min(30, Math.round(h / 5)) });
194
+ const badge = data?.badge != null && data.badge !== "" ? data.badge : null;
195
+ return (
196
+ <NodeShell id={id} selected={selected} locked={data?.locked} minWidth={80} minHeight={80}>
197
+ <div className="relative size-full overflow-hidden rounded-sm bg-card shadow-md transition-[box-shadow,translate] duration-150 group-hover/node:shadow-lg motion-reduce:transition-none">
198
+ <div aria-hidden="true" className={cx("absolute inset-0", tone(TINT, data?.color, "warning"))} />
199
+ <div className={cx("relative flex size-full items-center justify-center px-3.5", hasMeta ? "pt-3.5 pb-7" : "py-3.5")}>
200
+ <EditableText
201
+ {...words}
202
+ value={data?.text}
203
+ label="Sticky note"
204
+ placeholder={selected || words.editing ? "Type something" : ""}
205
+ className="max-h-full w-full overflow-hidden text-center leading-tight break-words whitespace-pre-wrap text-foreground"
206
+ style={{ fontSize: size }}
207
+ />
208
+ </div>
209
+ {badge !== null ? (
210
+ <Badge variant="soft" className="absolute top-2 right-2 tabular-nums">
211
+ {badge}
212
+ </Badge>
213
+ ) : null}
214
+ {hasMeta ? <span className="absolute right-3 bottom-2 left-3 truncate text-2xs text-muted-foreground">{data.meta}</span> : null}
215
+ </div>
216
+ </NodeShell>
217
+ );
218
+ }
219
+
220
+ // ── shape ────────────────────────────────────────────────────────────────
221
+
222
+ function Outline({ kind, w, h, className }) {
223
+ const i = 1;
224
+ if (kind === "ellipse") return <ellipse cx={w / 2} cy={h / 2} rx={w / 2 - i} ry={h / 2 - i} className={className} />;
225
+ if (kind === "diamond") return <polygon points={`${w / 2},${i} ${w - i},${h / 2} ${w / 2},${h - i} ${i},${h / 2}`} className={className} />;
226
+ const r = kind === "pill" ? (h - 2 * i) / 2 : Math.min(10, h / 6);
227
+ return <rect x={i} y={i} width={w - 2 * i} height={h - 2 * i} rx={r} className={className} />;
228
+ }
229
+
230
+ export function ShapeNode({ id, data, selected, width, height }) {
231
+ const w = width ?? 160;
232
+ const h = height ?? 100;
233
+ const kind = data?.shape ?? "rect";
234
+ const words = useWords(id);
235
+ // A diamond's words live in its middle; an ellipse's a little inside.
236
+ const inset = kind === "diamond" ? { x: w * 0.22, y: h * 0.22 } : kind === "ellipse" ? { x: w * 0.12, y: h * 0.12 } : { x: 12, y: 8 };
237
+ const max = TEXT_SIZE_PX[data?.textSize] ?? TEXT_SIZE_PX.md;
238
+ const size = fitFontSize(data?.text, w - inset.x * 2, h - inset.y * 2, { max, min: 10 });
239
+ const color = data?.color ?? "muted";
240
+ return (
241
+ <NodeShell id={id} selected={selected} locked={data?.locked} minWidth={40} minHeight={30}>
242
+ {/* raw: the outline is geometry on a canvas (a diamond, an ellipse), which no kit part draws. */}
243
+ <svg width={w} height={h} className="absolute inset-0 overflow-visible drop-shadow-sm" aria-hidden="true">
244
+ <Outline kind={kind} w={w} h={h} className="fill-card" />
245
+ <Outline
246
+ kind={kind}
247
+ w={w}
248
+ h={h}
249
+ className={cx(tone(FILL, color), tone(STROKE, color), "[stroke-width:1.5] transition-[fill,stroke] duration-150 motion-reduce:transition-none")}
250
+ />
251
+ </svg>
252
+ <div className="relative flex size-full items-center justify-center" style={{ padding: `${inset.y}px ${inset.x}px` }}>
253
+ <EditableText
254
+ {...words}
255
+ value={data?.text}
256
+ label={`${kind} text`}
257
+ placeholder={words.editing ? "Type something" : ""}
258
+ className="max-h-full w-full overflow-hidden text-center font-medium leading-tight break-words whitespace-pre-wrap text-foreground"
259
+ style={{ fontSize: size }}
260
+ />
261
+ </div>
262
+ </NodeShell>
263
+ );
264
+ }
265
+
266
+ // ── text ─────────────────────────────────────────────────────────────────
267
+
268
+ const ALIGN = { left: "text-left", center: "text-center", right: "text-right" };
269
+
270
+ export function TextNode({ id, data, selected, height }) {
271
+ const words = useWords(id);
272
+ const size = TEXT_SIZE_PX[data?.textSize] ?? TEXT_SIZE_PX.md;
273
+ return (
274
+ <NodeShell id={id} selected={selected} locked={data?.locked} autoHeight={!height} minWidth={60} minHeight={20}>
275
+ <EditableText
276
+ {...words}
277
+ value={data?.text}
278
+ label="Text"
279
+ placeholder={words.editing ? "Type something" : "Empty text"}
280
+ className={cx(
281
+ "w-full px-1 py-0.5 leading-snug break-words whitespace-pre-wrap text-foreground",
282
+ ALIGN[data?.align] ?? ALIGN.left,
283
+ (data?.textSize === "lg" || data?.textSize === "xl") && "font-semibold tracking-tight",
284
+ )}
285
+ style={{ fontSize: size }}
286
+ />
287
+ </NodeShell>
288
+ );
289
+ }
290
+
291
+ // ── frame ────────────────────────────────────────────────────────────────
292
+
293
+ export function FrameNode({ id, data, selected }) {
294
+ const words = useWords(id, "title");
295
+ const color = data?.color;
296
+ return (
297
+ <NodeShell id={id} selected={selected} locked={data?.locked} minWidth={120} minHeight={80} ring={false}>
298
+ <div
299
+ aria-hidden="true"
300
+ className={cx(
301
+ "absolute inset-0 rounded-lg border-2 transition-colors duration-150 motion-reduce:transition-none",
302
+ color ? cx(tone(WASH, color), tone(EDGE, color)) : "border-border bg-card/70",
303
+ selected ? "border-primary!" : "",
304
+ )}
305
+ />
306
+ {/* The edges take the pointer (drag the frame by its edge); the inside does not. */}
307
+ <span aria-hidden="true" className="pointer-events-auto absolute inset-x-0 -top-1 h-2" />
308
+ <span aria-hidden="true" className="pointer-events-auto absolute inset-x-0 -bottom-1 h-2" />
309
+ <span aria-hidden="true" className="pointer-events-auto absolute inset-y-0 -left-1 w-2" />
310
+ <span aria-hidden="true" className="pointer-events-auto absolute inset-y-0 -right-1 w-2" />
311
+ <div className="pointer-events-auto absolute -top-8 left-0 flex max-w-full items-center gap-1.5 rounded-md px-1 py-1 text-sm font-medium text-muted-foreground transition-colors duration-150 hover:text-foreground">
312
+ {color ? <span aria-hidden="true" className={cx("size-2.5 shrink-0 rounded-full", tone(SOLID, color))} /> : <Icon name="frame" size={14} />}
313
+ <EditableText {...words} singleLine value={data?.title} label="Frame title" placeholder="Untitled frame" className="min-w-8 truncate" />
314
+ </div>
315
+ </NodeShell>
316
+ );
317
+ }
318
+
319
+ // ── card ─────────────────────────────────────────────────────────────────
320
+
321
+ /** The card a block fills: `renderCard(node, ctx)` on FlowCanvas draws its
322
+ * inside (kit parts: Avatar, Badge…); without it, a title and a body. */
323
+ export function CardNode({ id, type, data, selected, width, height }) {
324
+ const { renderCard, api } = useCanvas();
325
+ const words = useWords(id, "title");
326
+ const node = { id, type, data: data ?? {}, width, height };
327
+ const inner = renderCard
328
+ ? renderCard(node, {
329
+ selected: Boolean(selected),
330
+ editing: words.editing,
331
+ update: (patch) => api?.updateNodeData(id, patch),
332
+ api,
333
+ })
334
+ : undefined;
335
+ const custom = inner !== undefined && inner !== null;
336
+ // A card the app draws has no words of ours to edit: hand editing back.
337
+ useEffect(() => {
338
+ if (custom && words.editing) api?.stopEditing(id);
339
+ }, [custom, words.editing, api, id]);
340
+ return (
341
+ <NodeShell id={id} selected={selected} locked={data?.locked} autoHeight={!height} minWidth={140} minHeight={60}>
342
+ <div
343
+ className={cx(
344
+ "w-full overflow-hidden rounded-lg border border-border bg-card text-card-foreground shadow-sm transition-shadow duration-150 group-hover/node:shadow-md motion-reduce:transition-none",
345
+ height ? "h-full" : "",
346
+ )}
347
+ >
348
+ {data?.color ? <div aria-hidden="true" className={cx("h-1", tone(SOLID, data.color))} /> : null}
349
+ {custom ? (
350
+ inner
351
+ ) : (
352
+ <div className="grid gap-1 p-3">
353
+ <div className="flex items-start gap-2">
354
+ {data?.icon ? <Icon name={data.icon} size={16} className="mt-0.5 shrink-0 text-muted-foreground" /> : null}
355
+ <EditableText
356
+ {...words}
357
+ singleLine
358
+ value={data?.title}
359
+ label="Card title"
360
+ placeholder="Untitled"
361
+ className="min-w-0 flex-1 text-sm font-medium leading-snug break-words"
362
+ />
363
+ {data?.badge ? <Badge variant="soft">{data.badge}</Badge> : null}
364
+ </div>
365
+ {data?.body ? <p className="text-sm leading-snug text-muted-foreground break-words whitespace-pre-wrap">{data.body}</p> : null}
366
+ </div>
367
+ )}
368
+ </div>
369
+ </NodeShell>
370
+ );
371
+ }
372
+
373
+ // ── image ────────────────────────────────────────────────────────────────
374
+
375
+ export function ImageNode({ id, data, selected }) {
376
+ return (
377
+ <NodeShell id={id} selected={selected} locked={data?.locked} keepAspectRatio minWidth={60} minHeight={40}>
378
+ <div className="size-full overflow-hidden rounded-md bg-card shadow-md">
379
+ <Image src={data?.src || undefined} alt={data?.alt ?? ""} fit="cover" rounded="md" loading="eager" className="size-full" draggable={false} />
380
+ </div>
381
+ </NodeShell>
382
+ );
383
+ }
384
+
385
+ export const BUILT_IN_NODES = {
386
+ sticky: StickyNode,
387
+ shape: ShapeNode,
388
+ text: TextNode,
389
+ frame: FrameNode,
390
+ card: CardNode,
391
+ image: ImageNode,
392
+ };
@@ -0,0 +1,174 @@
1
+ // React Flow in the workspace theme — the one place its look is mapped.
2
+ //
3
+ // React Flow paints itself from CSS variables (--xy-background-pattern-
4
+ // color, --xy-selection-border…) and a few fixed rules in its stylesheet
5
+ // (@xyflow/react/dist/style.css, imported by flow-canvas.jsx). Each one is
6
+ // pointed at a token here, as Tailwind arbitrary properties on the flow's
7
+ // root. Every class ends in `!`: the library's stylesheet is unlayered, and
8
+ // an unlayered rule beats any Tailwind utility (those live in @layer
9
+ // utilities) whatever its specificity; `!important` inside a layer is the
10
+ // one thing that outranks it. Our own nodes and connectors draw with
11
+ // token classes directly (nodes.jsx, edges.jsx), so the library's node and
12
+ // edge colours are never seen.
13
+ export const THEME = [
14
+ // the canvas: the page's background with dots in the muted ink
15
+ "[--xy-background-color:transparent]!",
16
+ "[--xy-background-pattern-color:var(--color-muted-foreground)]!",
17
+ "[&_.react-flow__background]:opacity-35!",
18
+ // the marquee, and the box around a multi-selection
19
+ "[&_.react-flow__selection]:bg-primary/8!",
20
+ "[&_.react-flow__selection]:border!",
21
+ "[&_.react-flow__selection]:border-solid!",
22
+ "[&_.react-flow__selection]:border-primary/70!",
23
+ "[&_.react-flow__selection]:rounded-sm!",
24
+ "[&_.react-flow__nodesselection-rect]:bg-transparent!",
25
+ "[&_.react-flow__nodesselection-rect]:border!",
26
+ "[&_.react-flow__nodesselection-rect]:border-dashed!",
27
+ "[&_.react-flow__nodesselection-rect]:border-primary/60!",
28
+ "[&_.react-flow__nodesselection-rect]:rounded-sm!",
29
+ // the line drawn while a connector is being dragged out
30
+ "[&_.react-flow__connection-path]:stroke-primary!",
31
+ "[&_.react-flow__connection-path]:[stroke-width:2]!",
32
+ // cursors that match the tool (flow-canvas.jsx sets data-tool on the root)
33
+ "[&_.react-flow__pane.selection]:cursor-default!",
34
+ "[&_.react-flow__node.draggable]:cursor-default!",
35
+ "[&_.react-flow__node.draggable.dragging]:cursor-grabbing!",
36
+ "data-[tool=hand]:[&_.react-flow__pane]:cursor-grab!",
37
+ "data-[tool=hand]:[&_.react-flow__pane.dragging]:cursor-grabbing!",
38
+ "data-[tool=hand]:[&_.react-flow__node]:cursor-grab!",
39
+ "data-[tool=place]:[&_.react-flow__pane]:cursor-crosshair!",
40
+ "data-[tool=text]:[&_.react-flow__pane]:cursor-text!",
41
+ "data-[tool=connector]:[&_.react-flow__node]:cursor-crosshair!",
42
+ // keyboard focus on a card: a visible ring (the library turns it off)
43
+ "[&_.react-flow__node:focus-visible]:outline-2!",
44
+ "[&_.react-flow__node:focus-visible]:outline-offset-4!",
45
+ "[&_.react-flow__node:focus-visible]:outline-ring!",
46
+ "[&_.react-flow__node:focus-visible]:[outline-style:solid]!",
47
+ // frames: only their title and edge take the pointer, so a double-click
48
+ // or a marquee inside one lands on the canvas (nodes.jsx)
49
+ "[&_.react-flow__node-frame]:pointer-events-none!",
50
+ // the resize handles on a selected card
51
+ "[&_.react-flow__resize-control.handle]:size-2.5!",
52
+ "[&_.react-flow__resize-control.handle]:rounded-xs!",
53
+ "[&_.react-flow__resize-control.handle]:border-primary!",
54
+ "[&_.react-flow__resize-control.handle]:bg-background!",
55
+ "[&_.react-flow__resize-control.handle]:pointer-events-auto!",
56
+ "[&_.react-flow__resize-control.line]:border-primary/0!",
57
+ "[&_.react-flow__resize-control.line]:pointer-events-auto!",
58
+ "[&_.react-flow__resize-control.line.left]:w-2!",
59
+ "[&_.react-flow__resize-control.line.right]:w-2!",
60
+ "[&_.react-flow__resize-control.line.top]:h-2!",
61
+ "[&_.react-flow__resize-control.line.bottom]:h-2!",
62
+ // the minimap: a card with the board in muted ink
63
+ "[--xy-minimap-background-color:var(--color-card)]!",
64
+ "[--xy-minimap-node-background-color:var(--color-muted-foreground)]!",
65
+ "[--xy-minimap-mask-background-color:var(--color-muted)]!",
66
+ "[&_.react-flow__minimap]:rounded-lg!",
67
+ "[&_.react-flow__minimap]:border!",
68
+ "[&_.react-flow__minimap]:border-border!",
69
+ "[&_.react-flow__minimap]:shadow-md!",
70
+ "[&_.react-flow__minimap]:overflow-hidden!",
71
+ "[&_.react-flow__minimap-node]:opacity-50!",
72
+ "[&_.react-flow__minimap-mask]:opacity-70!",
73
+ // React Flow's credit: kept (they ask for it), in the muted ink
74
+ "[&_.react-flow__attribution]:bg-transparent!",
75
+ "[&_.react-flow__attribution_a]:text-muted-foreground!",
76
+ // panels: ours sit in the corners with our own spacing
77
+ "[&_.react-flow__panel]:m-3!",
78
+ ].join(" ");
79
+
80
+ // Colour TOKENS → classes, written out whole so Tailwind generates them. A
81
+ // board stores the token name ("chart-3", "warning"); these turn it into
82
+ // paint. A sticky is the card surface with the hue laid over it, so it
83
+ // reads the same on a light or a dark workspace.
84
+ export const TINT = {
85
+ warning: "bg-warning/35",
86
+ "chart-1": "bg-chart-1/25",
87
+ "chart-2": "bg-chart-2/30",
88
+ "chart-3": "bg-chart-3/30",
89
+ "chart-4": "bg-chart-4/30",
90
+ "chart-5": "bg-chart-5/30",
91
+ success: "bg-success/30",
92
+ info: "bg-info/30",
93
+ destructive: "bg-destructive/25",
94
+ muted: "bg-muted",
95
+ };
96
+ /** A full-strength dot of the colour: the palette's swatches. */
97
+ export const SOLID = {
98
+ warning: "bg-warning",
99
+ "chart-1": "bg-chart-1",
100
+ "chart-2": "bg-chart-2",
101
+ "chart-3": "bg-chart-3",
102
+ "chart-4": "bg-chart-4",
103
+ "chart-5": "bg-chart-5",
104
+ success: "bg-success",
105
+ info: "bg-info",
106
+ destructive: "bg-destructive",
107
+ muted: "bg-muted-foreground/40",
108
+ };
109
+ /** Shapes (svg): a tinted fill over the card surface, the hue as the edge. */
110
+ export const FILL = {
111
+ warning: "fill-warning/35",
112
+ "chart-1": "fill-chart-1/25",
113
+ "chart-2": "fill-chart-2/30",
114
+ "chart-3": "fill-chart-3/30",
115
+ "chart-4": "fill-chart-4/30",
116
+ "chart-5": "fill-chart-5/30",
117
+ success: "fill-success/30",
118
+ info: "fill-info/30",
119
+ destructive: "fill-destructive/25",
120
+ muted: "fill-muted",
121
+ };
122
+ export const STROKE = {
123
+ warning: "stroke-warning",
124
+ "chart-1": "stroke-chart-1",
125
+ "chart-2": "stroke-chart-2",
126
+ "chart-3": "stroke-chart-3",
127
+ "chart-4": "stroke-chart-4",
128
+ "chart-5": "stroke-chart-5",
129
+ success: "stroke-success",
130
+ info: "stroke-info",
131
+ destructive: "stroke-destructive",
132
+ muted: "stroke-border",
133
+ };
134
+ /** A frame's faint wash of its colour (none: the plain card surface). */
135
+ export const WASH = {
136
+ warning: "bg-warning/8",
137
+ "chart-1": "bg-chart-1/8",
138
+ "chart-2": "bg-chart-2/8",
139
+ "chart-3": "bg-chart-3/8",
140
+ "chart-4": "bg-chart-4/8",
141
+ "chart-5": "bg-chart-5/8",
142
+ success: "bg-success/8",
143
+ info: "bg-info/8",
144
+ destructive: "bg-destructive/8",
145
+ muted: "bg-muted/60",
146
+ };
147
+ /** A frame's edge in its colour. */
148
+ export const EDGE = {
149
+ warning: "border-warning/60",
150
+ "chart-1": "border-chart-1/60",
151
+ "chart-2": "border-chart-2/60",
152
+ "chart-3": "border-chart-3/60",
153
+ "chart-4": "border-chart-4/60",
154
+ "chart-5": "border-chart-5/60",
155
+ success: "border-success/60",
156
+ info: "border-info/60",
157
+ destructive: "border-destructive/60",
158
+ muted: "border-border",
159
+ };
160
+ /** An unknown token falls back to this. */
161
+ export const tone = (map, token, fallback = "muted") => map[token] ?? map[fallback];
162
+
163
+ /** Every class for one colour token, for a block's own node types:
164
+ * colorClasses("chart-3").tint → "bg-chart-3/30". */
165
+ export function colorClasses(token) {
166
+ return {
167
+ tint: tone(TINT, token),
168
+ solid: tone(SOLID, token),
169
+ fill: tone(FILL, token),
170
+ stroke: tone(STROKE, token),
171
+ wash: tone(WASH, token),
172
+ edge: tone(EDGE, token),
173
+ };
174
+ }