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,225 @@
1
+ "use client";
2
+
3
+ // DocEditor three ways — the gallery's and the smoke test's surface. Not
4
+ // installed into apps.
5
+ // Document the full editor: / menu, drag handles, @mentions; beside
6
+ // it what the helpers read out of the doc (markdown, the
7
+ // checklist). Read-only behind a switch.
8
+ // Comment minimal mode: no side menu, no / menu; @mentions,
9
+ // Cmd/Ctrl+Enter posts, the box clears through its handle.
10
+ // Merge an email body with merge fields ({ or /), previewed for
11
+ // each recipient, with a warning for a value the recipient lacks.
12
+ import { useMemo, useState } from "react";
13
+ import { Avatar, Badge, Button, Card, Field, IconButton, KbdGroup, Notice, Select, Switch, TabPanel, Tabs } from "../components/ui";
14
+ import {
15
+ DocEditor,
16
+ docChecklist,
17
+ docFields,
18
+ docToMarkdown,
19
+ docToText,
20
+ isDocEmpty,
21
+ setChecklistItem,
22
+ useDocEditor,
23
+ } from "../components/blocks/doc-editor";
24
+
25
+ const PEOPLE = [
26
+ { id: "u-priya", label: "Priya Raman", description: "Design" },
27
+ { id: "u-tomas", label: "Tomás Ortega", description: "Engineering" },
28
+ { id: "u-june", label: "June Okafor", description: "Growth" },
29
+ { id: "u-lena", label: "Lena Fischer", description: "Sales" },
30
+ ];
31
+ const findPeople = async (query) => {
32
+ const q = query.toLowerCase();
33
+ return PEOPLE.filter((p) => p.label.toLowerCase().includes(q));
34
+ };
35
+
36
+ const t = (text, styles = {}) => ({ type: "text", text, styles });
37
+ const who = (id) => ({ type: "mention", props: { id, label: PEOPLE.find((p) => p.id === id).label } });
38
+
39
+ // Written by hand, so each block gets its id here: the checklist beside
40
+ // the editor ticks items by id before the first edit has come back.
41
+ const LAUNCH_DOC = [
42
+ { type: "heading", props: { level: 1 }, content: [t("Harbor 2.0 launch")] },
43
+ {
44
+ type: "paragraph",
45
+ content: [t("We ship on "), t("14 November", { bold: true }), t(". This page is the one place for the plan; "), who("u-june"), t(" owns it.")],
46
+ },
47
+ { type: "heading", props: { level: 2 }, content: [t("Before launch")] },
48
+ { type: "checkListItem", props: { checked: true }, content: [t("Freeze the pricing page copy")] },
49
+ { type: "checkListItem", content: [who("u-priya"), t(" final hero screenshots")] },
50
+ { type: "checkListItem", content: [who("u-tomas"), t(" migrate the waitlist to the new plan table")] },
51
+ { type: "heading", props: { level: 2 }, content: [t("Launch day")] },
52
+ { type: "numberedListItem", content: [t("Changelog post at 9:00")] },
53
+ { type: "numberedListItem", content: [t("Email to the waitlist at 10:00")] },
54
+ { type: "numberedListItem", content: [t("Founders post on LinkedIn")] },
55
+ { type: "quote", content: [t("Say what changed for the customer, not what we built.")] },
56
+ ].map((b, i) => ({ id: `launch-${i + 1}`, ...b }));
57
+
58
+ function DocumentDemo() {
59
+ const [doc, setDoc] = useState(LAUNCH_DOC);
60
+ const [readOnly, setReadOnly] = useState(false);
61
+ const [view, setView] = useState("checklist");
62
+ const items = useMemo(() => docChecklist(doc), [doc]);
63
+ return (
64
+ <div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_20rem]">
65
+ <Card padding="lg" actions={<Switch id="doc-ro" label="Read-only" checked={readOnly} onChange={(e) => setReadOnly(e.target.checked)} />}>
66
+ <DocEditor value={doc} onChange={setDoc} editable={!readOnly} mentions={findPeople} placeholder="Start writing, or press / for blocks" label="Launch plan" />
67
+ </Card>
68
+ <Card padding="none" className="min-w-0">
69
+ <Tabs
70
+ aria-label="What the helpers read"
71
+ className="px-3"
72
+ value={view}
73
+ onChange={setView}
74
+ tabs={[
75
+ { key: "checklist", label: `Checklist (${items.length})` },
76
+ { key: "markdown", label: "Markdown" },
77
+ ]}
78
+ />
79
+ <TabPanel tab="checklist" value={view} className="p-3">
80
+ {items.length === 0 ? (
81
+ <p className="text-sm text-muted-foreground">No checklist items. Type [] in the doc to start one.</p>
82
+ ) : (
83
+ <ul className="grid gap-2">
84
+ {items.map((it) => (
85
+ <li key={it.id} className="flex items-start gap-2 text-sm">
86
+ <IconButton
87
+ size="sm"
88
+ icon={it.checked ? "check-circle" : "circle"}
89
+ label={it.checked ? "Mark not done" : "Mark done"}
90
+ onClick={() => setDoc((d) => setChecklistItem(d, it.id, !it.checked))}
91
+ />
92
+ <span className={it.checked ? "pt-1.5 text-muted-foreground line-through" : "pt-1.5"}>{it.text || "Untitled item"}</span>
93
+ {it.mentions[0] ? <Avatar name={it.mentions[0].label} size="xs" className="ml-auto mt-1 shrink-0" /> : null}
94
+ </li>
95
+ ))}
96
+ </ul>
97
+ )}
98
+ </TabPanel>
99
+ <TabPanel tab="markdown" value={view} className="p-3">
100
+ <pre className="max-h-96 overflow-auto whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground">{docToMarkdown(doc)}</pre>
101
+ </TabPanel>
102
+ </Card>
103
+ </div>
104
+ );
105
+ }
106
+
107
+ const THREAD = [
108
+ { id: "c1", author: "Lena Fischer", text: "Can we move the email to 11:00? The EU list opens later." },
109
+ { id: "c2", author: "June Okafor", text: "@Lena Fischer fine by me — @Tomás Ortega does the send job care?" },
110
+ ];
111
+
112
+ function CommentDemo() {
113
+ const [comments, setComments] = useState(THREAD);
114
+ const [draft, setDraft] = useState(null);
115
+ const box = useDocEditor();
116
+ const post = (doc) => {
117
+ if (isDocEmpty(doc)) return;
118
+ setComments((c) => [...c, { id: `c${c.length + 1}`, author: "You", text: docToText(doc) }]);
119
+ box.current?.clear();
120
+ setDraft(null);
121
+ };
122
+ return (
123
+ <Card title="Comments" description="Minimal mode: no side menu, no / menu. @ mentions someone." className="max-w-xl">
124
+ <ul className="mb-4 grid gap-3">
125
+ {comments.map((c) => (
126
+ <li key={c.id} className="flex gap-3">
127
+ <Avatar name={c.author} size="sm" />
128
+ <div className="min-w-0">
129
+ <p className="text-sm font-medium">{c.author}</p>
130
+ <p className="whitespace-pre-wrap break-words text-sm text-muted-foreground">{c.text}</p>
131
+ </div>
132
+ </li>
133
+ ))}
134
+ </ul>
135
+ <div className="rounded-md border border-input bg-background px-3 py-2 focus-within:ring-2 focus-within:ring-ring">
136
+ <DocEditor minimal editorRef={box} onChange={setDraft} onSubmit={post} mentions={findPeople} placeholder="Write a comment…" label="Comment" />
137
+ </div>
138
+ <div className="mt-2 flex items-center justify-between gap-3">
139
+ <KbdGroup keys={["⌘", "Enter"]} className="text-xs text-muted-foreground" />
140
+ <Button size="sm" variant="primary" disabled={!draft || isDocEmpty(draft)} onClick={() => post(box.current?.getDoc())}>
141
+ Post
142
+ </Button>
143
+ </div>
144
+ </Card>
145
+ );
146
+ }
147
+
148
+ const FIELDS = [
149
+ { key: "first_name", label: "First name" },
150
+ { key: "company", label: "Company" },
151
+ { key: "last_order", label: "Last order" },
152
+ ];
153
+ const RECIPIENTS = [
154
+ { id: "r1", name: "Ana Souza", values: { first_name: "Ana", company: "Fernhill Bakery", last_order: "Sourdough starter kit" } },
155
+ { id: "r2", name: "Marcus Webb", values: { first_name: "Marcus", company: "Webb & Daughters", last_order: "" } },
156
+ { id: "r3", name: "Keiko Tan", values: { first_name: "Keiko", company: "", last_order: "Rye flour, 10 kg" } },
157
+ ];
158
+ const field = (key) => ({ type: "field", props: { key, label: FIELDS.find((f) => f.key === key).label } });
159
+ const EMAIL_BODY = [
160
+ { type: "paragraph", content: [t("Hi "), field("first_name"), t(",")] },
161
+ { type: "paragraph", content: [] },
162
+ { type: "paragraph", content: [t("Thanks for your last order ("), field("last_order"), t("). We've opened wholesale accounts for teams like "), field("company"), t(" — 12% off from the second bag.")] },
163
+ { type: "paragraph", content: [] },
164
+ { type: "paragraph", content: [t("Reply to this email and I'll set it up.")] },
165
+ ];
166
+
167
+ function MergeDemo() {
168
+ const [body, setBody] = useState(EMAIL_BODY);
169
+ const [to, setTo] = useState(RECIPIENTS[0].id);
170
+ const recipient = RECIPIENTS.find((r) => r.id === to);
171
+ const used = docFields(body);
172
+ const missing = used.filter((f) => !recipient.values[f.key]);
173
+ return (
174
+ <div className="grid gap-4 lg:grid-cols-2">
175
+ <Card title="Body" description="Type { or / to insert a field.">
176
+ <DocEditor value={body} onChange={setBody} fields={FIELDS} placeholder="Write the email…" label="Email body" />
177
+ <div className="mt-3 flex flex-wrap gap-1.5">
178
+ {used.map((f) => (
179
+ <Badge key={f.key}>
180
+ {f.label} ×{f.count}
181
+ </Badge>
182
+ ))}
183
+ </div>
184
+ </Card>
185
+ <Card title="Preview">
186
+ <Field id="merge-to" label="Recipient" className="mb-3">
187
+ <Select id="merge-to" value={to} onChange={(e) => setTo(e.target.value)} options={RECIPIENTS.map((r) => ({ value: r.id, label: r.name }))} />
188
+ </Field>
189
+ {missing.length ? (
190
+ <Notice tone="warning" className="mb-3">
191
+ {recipient.name} has no {missing.map((f) => f.label.toLowerCase()).join(" or ")}: the email would say {missing.map((f) => `{${f.key}}`).join(", ")}.
192
+ </Notice>
193
+ ) : null}
194
+ <p className="whitespace-pre-wrap break-words rounded-md border border-border bg-background p-3 text-sm">{docToText(body, { fields: recipient.values })}</p>
195
+ </Card>
196
+ </div>
197
+ );
198
+ }
199
+
200
+ export default function DocEditorDemo() {
201
+ const [tab, setTab] = useState("document");
202
+ return (
203
+ <div className="grid gap-4">
204
+ <Tabs
205
+ aria-label="DocEditor variants"
206
+ value={tab}
207
+ onChange={setTab}
208
+ tabs={[
209
+ { key: "document", label: "Document" },
210
+ { key: "comment", label: "Comment" },
211
+ { key: "merge", label: "Merge fields" },
212
+ ]}
213
+ />
214
+ <TabPanel tab="document" value={tab}>
215
+ <DocumentDemo />
216
+ </TabPanel>
217
+ <TabPanel tab="comment" value={tab}>
218
+ <CommentDemo />
219
+ </TabPanel>
220
+ <TabPanel tab="merge" value={tab}>
221
+ <MergeDemo />
222
+ </TabPanel>
223
+ </div>
224
+ );
225
+ }
@@ -0,0 +1,291 @@
1
+ "use client";
2
+
3
+ // DocEditor — BlockNote, in the workspace theme, behind one set of props.
4
+ //
5
+ // Client only, one static bundle. BlockNote needs the DOM, and the app's
6
+ // check refuses import() (so no next/dynamic): the modules load with the
7
+ // page, and the editor itself is created only after the first effect
8
+ // (the mount guard). Until then — on the server and in the first client
9
+ // paint — a placeholder shows the doc's words in the same box, so the
10
+ // server HTML already reads right and nothing jumps.
11
+ import "@blocknote/shadcn/style.css";
12
+ import { useEffect, useMemo, useRef, useState } from "react";
13
+ import { filterSuggestionItems } from "@blocknote/core/extensions";
14
+ import { en } from "@blocknote/core/locales";
15
+ import {
16
+ DragHandleMenu,
17
+ FormattingToolbar,
18
+ FormattingToolbarController,
19
+ RemoveBlockItem,
20
+ SideMenu,
21
+ SideMenuController,
22
+ SuggestionMenuController,
23
+ TableColumnHeaderItem,
24
+ TableRowHeaderItem,
25
+ getDefaultReactSlashMenuItems,
26
+ getFormattingToolbarItems,
27
+ useCreateBlockNote,
28
+ } from "@blocknote/react";
29
+ import { BlockNoteView } from "@blocknote/shadcn";
30
+ import { Icon, cx } from "../../ui";
31
+ import { SCHEMA } from "./schema";
32
+ import { THEME } from "./theme";
33
+ import { docToText, emptyDoc, isDocEmpty } from "./doc";
34
+
35
+ /** A ref for the editor's handle: `const ed = useDocEditor()`, then
36
+ * `<DocEditor editorRef={ed} />` and `ed.current?.insertField("first_name")`. */
37
+ export function useDocEditor() {
38
+ return useRef(null);
39
+ }
40
+
41
+ const nonEmpty = (doc) => (Array.isArray(doc) && doc.length ? doc : null);
42
+
43
+ // The box, the same in the placeholder and the live editor.
44
+ const BOX = {
45
+ full: "min-h-40",
46
+ minimal: "min-h-10",
47
+ };
48
+ // `compact`: the full editor (menus, handles) in a short box, for a doc cut
49
+ // into many small sections (brief-doc). A className cannot lower min-h-40:
50
+ // cx joins classes without merging, and min-h-40 won (2026-09-24).
51
+ const boxOf = (minimal, compact) => (minimal ? BOX.minimal : compact ? "min-h-16" : BOX.full);
52
+ // BlockNote's editor element: its own padding off (54px each side, for the
53
+ // drag handles), ours on. Full mode keeps room for the handles from 640px;
54
+ // on a phone there is no hover, so no handles and no gutter.
55
+ const EDITOR = {
56
+ full: "[&_.bn-editor]:px-0! [&_.bn-editor]:py-1! sm:[&_.bn-editor]:ps-12! text-base",
57
+ minimal: "[&_.bn-editor]:px-0! [&_.bn-editor]:py-0! text-sm",
58
+ };
59
+
60
+ export function DocEditor(props) {
61
+ const [mounted, setMounted] = useState(false);
62
+ useEffect(() => setMounted(true), []);
63
+ if (!mounted) return <DocPlaceholder {...props} />;
64
+ return <LiveEditor {...props} />;
65
+ }
66
+
67
+ /** What the server renders (and the first client paint): the doc's words,
68
+ * or the placeholder, in the editor's box. Not editable, not focusable. */
69
+ function DocPlaceholder({ value, defaultValue, placeholder, minimal = false, compact = false, className }) {
70
+ const doc = nonEmpty(value) ?? nonEmpty(defaultValue);
71
+ const text = doc && !isDocEmpty(doc) ? docToText(doc) : "";
72
+ const mode = minimal ? "minimal" : "full";
73
+ return (
74
+ <div className={cx(boxOf(minimal, compact), className)} aria-busy="true">
75
+ <div className={cx(EDITOR[mode], !minimal && "sm:ps-12", "whitespace-pre-wrap", text ? "text-foreground" : "text-muted-foreground")}>
76
+ {text || placeholder || " "}
77
+ </div>
78
+ </div>
79
+ );
80
+ }
81
+
82
+ /** Keep the members of a group together, in first-seen order: BlockNote's
83
+ * menu draws a group heading each time the group changes. */
84
+ function grouped(items) {
85
+ const order = [];
86
+ const by = new Map();
87
+ for (const it of items) {
88
+ const g = it.group ?? "";
89
+ if (!by.has(g)) {
90
+ by.set(g, []);
91
+ order.push(g);
92
+ }
93
+ by.get(g).push(it);
94
+ }
95
+ return order.flatMap((g) => by.get(g));
96
+ }
97
+
98
+ const iconOf = (icon) => (typeof icon === "string" ? <Icon name={icon} size={18} /> : icon);
99
+
100
+ /** The workspace's light or dark, read off <html> (the desk sets data-theme). */
101
+ function schemeOf() {
102
+ const root = document.documentElement;
103
+ if (root.dataset.theme === "light" || root.dataset.theme === "dark") return root.dataset.theme;
104
+ const cs = getComputedStyle(root).colorScheme || "";
105
+ return /\blight\b/.test(cs) && !/\bdark\b/.test(cs) ? "light" : "dark";
106
+ }
107
+
108
+ function LiveEditor({
109
+ value,
110
+ defaultValue,
111
+ onChange,
112
+ editable = true,
113
+ placeholder,
114
+ slashItems,
115
+ mentions,
116
+ fields,
117
+ minimal = false,
118
+ compact = false,
119
+ autoFocus = false,
120
+ onSubmit,
121
+ onKeyDown,
122
+ uploadFile,
123
+ editorRef,
124
+ className,
125
+ label,
126
+ }) {
127
+ const mode = minimal ? "minimal" : "full";
128
+ const initial = useRef(nonEmpty(value) ?? nonEmpty(defaultValue) ?? emptyDoc());
129
+ const dictionary = useMemo(
130
+ () => ({
131
+ ...en,
132
+ placeholders: {
133
+ ...en.placeholders,
134
+ emptyDocument: placeholder || undefined,
135
+ // "type '/' for commands" is a lie with no slash menu.
136
+ default: minimal ? undefined : en.placeholders.default,
137
+ },
138
+ }),
139
+ // The editor is created once; a new placeholder needs a new key.
140
+ // eslint-disable-next-line react-hooks/exhaustive-deps
141
+ [],
142
+ );
143
+ const editor = useCreateBlockNote({ schema: SCHEMA, initialContent: initial.current, dictionary, uploadFile, trailingBlock: !minimal }, []);
144
+ const [scheme, setScheme] = useState("dark");
145
+ useEffect(() => {
146
+ setScheme(schemeOf());
147
+ const obs = new MutationObserver(() => setScheme(schemeOf()));
148
+ obs.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "class", "style"] });
149
+ return () => obs.disconnect();
150
+ }, []);
151
+
152
+ // Controlled: a `value` that is not what we last sent replaces the doc.
153
+ const last = useRef(JSON.stringify(initial.current));
154
+ const applying = useRef(false);
155
+ useEffect(() => {
156
+ if (value === undefined) return;
157
+ const next = nonEmpty(value) ?? emptyDoc();
158
+ const s = JSON.stringify(next);
159
+ if (s === last.current) return;
160
+ last.current = s;
161
+ applying.current = true;
162
+ try {
163
+ editor.replaceBlocks(editor.document, next);
164
+ } finally {
165
+ applying.current = false;
166
+ }
167
+ }, [value, editor]);
168
+
169
+ const emit = () => {
170
+ if (applying.current) return;
171
+ const doc = editor.document;
172
+ last.current = JSON.stringify(doc);
173
+ onChange?.(doc);
174
+ };
175
+
176
+ // The handle a block reaches through editorRef / useDocEditor().
177
+ const handle = useMemo(
178
+ () => ({
179
+ editor,
180
+ focus: () => editor.focus(),
181
+ getDoc: () => editor.document,
182
+ setDoc: (doc) => editor.replaceBlocks(editor.document, nonEmpty(doc) ?? emptyDoc()),
183
+ clear: () => editor.replaceBlocks(editor.document, emptyDoc()),
184
+ isEmpty: () => isDocEmpty(editor.document),
185
+ insertText: (text) => editor.insertInlineContent([String(text ?? "")]),
186
+ insertMention: ({ id, label: l }) => editor.insertInlineContent([{ type: "mention", props: { id: String(id), label: String(l ?? id) } }, " "]),
187
+ insertField: (key, l) => {
188
+ const f = (fields ?? []).find((x) => x.key === key);
189
+ editor.insertInlineContent([{ type: "field", props: { key, label: l ?? f?.label ?? key } }, " "]);
190
+ },
191
+ }),
192
+ [editor, fields],
193
+ );
194
+ useEffect(() => {
195
+ if (!editorRef) return;
196
+ editorRef.current = handle;
197
+ return () => {
198
+ if (editorRef.current === handle) editorRef.current = null;
199
+ };
200
+ }, [editorRef, handle]);
201
+
202
+ const fieldItems = (query, group) =>
203
+ filterSuggestionItems(
204
+ (fields ?? []).map((f) => ({
205
+ title: f.label ?? f.key,
206
+ subtext: `{${f.key}}`,
207
+ aliases: [f.key, "field", "merge"],
208
+ group,
209
+ icon: iconOf("tag"),
210
+ onItemClick: () => handle.insertField(f.key, f.label),
211
+ })),
212
+ query,
213
+ );
214
+
215
+ const getSlashItems = async (query) => {
216
+ const own = (slashItems ?? []).map((it) => ({
217
+ title: it.title,
218
+ subtext: it.subtext,
219
+ aliases: it.aliases,
220
+ group: it.group ?? "Other",
221
+ icon: iconOf(it.icon),
222
+ onItemClick: () => it.onSelect?.(handle),
223
+ }));
224
+ const all = grouped([...getDefaultReactSlashMenuItems(editor), ...own]);
225
+ return [...filterSuggestionItems(all, query), ...(fields?.length ? fieldItems(query, "Fields") : [])];
226
+ };
227
+
228
+ const getMentionItems = async (query) => {
229
+ let people = [];
230
+ try {
231
+ people = (await mentions(query)) ?? [];
232
+ } catch {
233
+ people = [];
234
+ }
235
+ return people.slice(0, 20).map((p) => ({
236
+ title: p.label ?? String(p.id),
237
+ subtext: p.description,
238
+ icon: iconOf("user"),
239
+ onItemClick: () => handle.insertMention({ id: p.id, label: p.label }),
240
+ }));
241
+ };
242
+
243
+ // Cmd/Ctrl+Enter submits, before BlockNote sees the Enter.
244
+ const keyDown = (e) => {
245
+ if (onSubmit && e.key === "Enter" && (e.metaKey || e.ctrlKey) && !e.nativeEvent.isComposing) {
246
+ e.preventDefault();
247
+ e.stopPropagation();
248
+ onSubmit(editor.document);
249
+ return;
250
+ }
251
+ onKeyDown?.(e);
252
+ };
253
+
254
+ return (
255
+ // raw: a plain box that hears keys on their way into BlockNote's
256
+ // contenteditable (capture), for Cmd/Ctrl+Enter; no control of its own.
257
+ <div className={cx(boxOf(minimal, compact), className)} onKeyDownCapture={keyDown}>
258
+ <BlockNoteView
259
+ editor={editor}
260
+ editable={editable}
261
+ autoFocus={autoFocus}
262
+ theme={scheme}
263
+ className={cx(THEME, EDITOR[mode])}
264
+ onChange={emit}
265
+ aria-label={label}
266
+ slashMenu={false}
267
+ sideMenu={false}
268
+ formattingToolbar={false}
269
+ emojiPicker={!minimal}
270
+ >
271
+ <FormattingToolbarController formattingToolbar={Toolbar} />
272
+ {!minimal && <SideMenuController sideMenu={Handles} />}
273
+ {!minimal && <SuggestionMenuController triggerCharacter="/" getItems={getSlashItems} />}
274
+ {mentions && <SuggestionMenuController triggerCharacter="@" getItems={getMentionItems} />}
275
+ {fields?.length ? <SuggestionMenuController triggerCharacter="{" getItems={async (q) => fieldItems(q)} /> : null}
276
+ </BlockNoteView>
277
+ </div>
278
+ );
279
+ }
280
+
281
+ // BlockNote's toolbar and block menu without their colour pickers: the
282
+ // theme has no red or purple to offer (theme.js maps what is stored).
283
+ const Toolbar = () => <FormattingToolbar>{getFormattingToolbarItems().filter((el) => el.key !== "colorStyleButton")}</FormattingToolbar>;
284
+ const BlockMenu = () => (
285
+ <DragHandleMenu>
286
+ <RemoveBlockItem>{en.drag_handle.delete_menuitem}</RemoveBlockItem>
287
+ <TableRowHeaderItem>{en.drag_handle.header_row_menuitem}</TableRowHeaderItem>
288
+ <TableColumnHeaderItem>{en.drag_handle.header_column_menuitem}</TableColumnHeaderItem>
289
+ </DragHandleMenu>
290
+ );
291
+ const Handles = (props) => <SideMenu {...props} dragHandleMenu={BlockMenu} />;