makersclaw 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. package/THIRD-PARTY-NOTICES.md +180 -0
  2. package/package.json +3 -2
  3. package/r/annotate.json +62 -0
  4. package/r/approval-request.json +52 -0
  5. package/r/audio-player.json +74 -0
  6. package/r/auth-form.json +55 -0
  7. package/r/board.json +10 -6
  8. package/r/calendar-view.json +105 -0
  9. package/r/cart.json +62 -0
  10. package/r/chart.json +83 -0
  11. package/r/chat.json +95 -0
  12. package/r/code-editor.json +94 -0
  13. package/r/comment-box.json +64 -0
  14. package/r/contact-section.json +53 -0
  15. package/r/core.json +205 -8
  16. package/r/csv-import.json +63 -0
  17. package/r/data-table.json +69 -0
  18. package/r/diagram.json +74 -0
  19. package/r/doc-editor.json +82 -0
  20. package/r/doc-page.json +61 -0
  21. package/r/email-render.json +73 -0
  22. package/r/faq.json +50 -0
  23. package/r/file-upload.json +54 -0
  24. package/r/flow-canvas.json +93 -0
  25. package/r/footer.json +52 -0
  26. package/r/gantt.json +70 -0
  27. package/r/job-panel.json +12 -7
  28. package/r/json-editor.json +66 -0
  29. package/r/map.json +89 -0
  30. package/r/menubar.json +52 -0
  31. package/r/mind-map.json +67 -0
  32. package/r/navigation-menu.json +52 -0
  33. package/r/order-detail.json +54 -0
  34. package/r/org-chart.json +66 -0
  35. package/r/page-builder.json +105 -0
  36. package/r/payment-methods.json +51 -0
  37. package/r/pdf-document.json +79 -0
  38. package/r/pdf-viewer.json +88 -0
  39. package/r/product-detail.json +76 -0
  40. package/r/product-grid.json +65 -0
  41. package/r/record-form.json +67 -0
  42. package/r/record-notes.json +55 -0
  43. package/r/registry.json +3411 -29
  44. package/r/search-dialog.json +51 -0
  45. package/r/settings-list.json +66 -0
  46. package/r/setup-checklist.json +51 -0
  47. package/r/share-dialog.json +52 -0
  48. package/r/sidebar.json +69 -0
  49. package/r/signature-pad.json +72 -0
  50. package/r/sketch-canvas.json +99 -0
  51. package/r/spreadsheet.json +90 -0
  52. package/r/stat-cards.json +66 -0
  53. package/r/task-list.json +63 -0
  54. package/r/task-model.json +98 -0
  55. package/r/testimonials.json +52 -0
  56. package/r/transaction-list.json +53 -0
  57. package/r/whiteboard.json +66 -0
  58. package/registry/blocks/annotate/README.md +179 -0
  59. package/registry/blocks/annotate/annotate-data.js +250 -0
  60. package/registry/blocks/annotate/annotate.jsx +646 -0
  61. package/registry/blocks/annotate/block.json +10 -0
  62. package/registry/blocks/annotate/demo.jsx +135 -0
  63. package/registry/blocks/annotate/index.js +15 -0
  64. package/registry/blocks/approval-request/README.md +116 -0
  65. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  66. package/registry/blocks/approval-request/block.json +10 -0
  67. package/registry/blocks/approval-request/demo.jsx +127 -0
  68. package/registry/blocks/approval-request/index.js +4 -0
  69. package/registry/blocks/audio-player/README.md +167 -0
  70. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  71. package/registry/blocks/audio-player/block.json +14 -0
  72. package/registry/blocks/audio-player/colors.js +109 -0
  73. package/registry/blocks/audio-player/demo.jsx +209 -0
  74. package/registry/blocks/audio-player/index.js +6 -0
  75. package/registry/blocks/audio-player/time.js +67 -0
  76. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  77. package/registry/blocks/auth-form/README.md +126 -0
  78. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  79. package/registry/blocks/auth-form/block.json +10 -0
  80. package/registry/blocks/auth-form/demo.jsx +131 -0
  81. package/registry/blocks/auth-form/index.js +3 -0
  82. package/registry/blocks/board/README.md +55 -5
  83. package/registry/blocks/board/block.json +2 -2
  84. package/registry/blocks/board/board.jsx +230 -86
  85. package/registry/blocks/board/demo.jsx +103 -24
  86. package/registry/blocks/calendar-view/README.md +180 -0
  87. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  88. package/registry/blocks/calendar-view/block.json +76 -0
  89. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  90. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  91. package/registry/blocks/calendar-view/demo.jsx +195 -0
  92. package/registry/blocks/calendar-view/draft.jsx +49 -0
  93. package/registry/blocks/calendar-view/index.js +39 -0
  94. package/registry/blocks/calendar-view/month.jsx +346 -0
  95. package/registry/blocks/calendar-view/paint.js +69 -0
  96. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  97. package/registry/blocks/calendar-view/tray.jsx +87 -0
  98. package/registry/blocks/cart/README.md +146 -0
  99. package/registry/blocks/cart/block.json +10 -0
  100. package/registry/blocks/cart/cart.jsx +597 -0
  101. package/registry/blocks/cart/demo.jsx +98 -0
  102. package/registry/blocks/cart/index.js +4 -0
  103. package/registry/blocks/cart/money.js +28 -0
  104. package/registry/blocks/chart/README.md +316 -0
  105. package/registry/blocks/chart/block.json +10 -0
  106. package/registry/blocks/chart/cartesian.jsx +642 -0
  107. package/registry/blocks/chart/core.jsx +262 -0
  108. package/registry/blocks/chart/demo.jsx +357 -0
  109. package/registry/blocks/chart/heatmap.jsx +336 -0
  110. package/registry/blocks/chart/index.js +8 -0
  111. package/registry/blocks/chart/pie.jsx +245 -0
  112. package/registry/blocks/chart/sparkline.jsx +88 -0
  113. package/registry/blocks/chat/README.md +273 -0
  114. package/registry/blocks/chat/attachment.jsx +95 -0
  115. package/registry/blocks/chat/block.json +10 -0
  116. package/registry/blocks/chat/chat.jsx +132 -0
  117. package/registry/blocks/chat/composer.jsx +364 -0
  118. package/registry/blocks/chat/demo.jsx +578 -0
  119. package/registry/blocks/chat/header.jsx +34 -0
  120. package/registry/blocks/chat/index.js +9 -0
  121. package/registry/blocks/chat/message.jsx +450 -0
  122. package/registry/blocks/chat/scroller.jsx +247 -0
  123. package/registry/blocks/chat/text.jsx +104 -0
  124. package/registry/blocks/code-editor/README.md +210 -0
  125. package/registry/blocks/code-editor/block.json +22 -0
  126. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  127. package/registry/blocks/code-editor/codemirror.js +38 -0
  128. package/registry/blocks/code-editor/demo.jsx +205 -0
  129. package/registry/blocks/code-editor/index.js +8 -0
  130. package/registry/blocks/code-editor/json.js +317 -0
  131. package/registry/blocks/code-editor/sql.js +136 -0
  132. package/registry/blocks/code-editor/text.js +101 -0
  133. package/registry/blocks/code-editor/theme.js +186 -0
  134. package/registry/blocks/comment-box/README.md +123 -0
  135. package/registry/blocks/comment-box/block.json +10 -0
  136. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  137. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  138. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  139. package/registry/blocks/comment-box/demo.jsx +141 -0
  140. package/registry/blocks/comment-box/index.js +8 -0
  141. package/registry/blocks/contact-section/README.md +152 -0
  142. package/registry/blocks/contact-section/block.json +11 -0
  143. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  144. package/registry/blocks/contact-section/demo.jsx +93 -0
  145. package/registry/blocks/contact-section/index.js +4 -0
  146. package/registry/blocks/csv-import/README.md +133 -0
  147. package/registry/blocks/csv-import/block.json +13 -0
  148. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  149. package/registry/blocks/csv-import/demo.jsx +106 -0
  150. package/registry/blocks/csv-import/import.js +200 -0
  151. package/registry/blocks/csv-import/index.js +7 -0
  152. package/registry/blocks/data-table/README.md +386 -0
  153. package/registry/blocks/data-table/block.json +10 -0
  154. package/registry/blocks/data-table/data-table.jsx +1164 -0
  155. package/registry/blocks/data-table/demo.jsx +588 -0
  156. package/registry/blocks/data-table/index.js +5 -0
  157. package/registry/blocks/data-table/model.js +169 -0
  158. package/registry/blocks/diagram/README.md +108 -0
  159. package/registry/blocks/diagram/block.json +13 -0
  160. package/registry/blocks/diagram/demo.jsx +113 -0
  161. package/registry/blocks/diagram/diagram.jsx +481 -0
  162. package/registry/blocks/diagram/index.js +7 -0
  163. package/registry/blocks/diagram/mermaid.js +52 -0
  164. package/registry/blocks/diagram/palette.js +313 -0
  165. package/registry/blocks/diagram/source.js +98 -0
  166. package/registry/blocks/doc-editor/README.md +215 -0
  167. package/registry/blocks/doc-editor/block.json +15 -0
  168. package/registry/blocks/doc-editor/demo.jsx +225 -0
  169. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  170. package/registry/blocks/doc-editor/doc.js +309 -0
  171. package/registry/blocks/doc-editor/index.js +7 -0
  172. package/registry/blocks/doc-editor/schema.jsx +56 -0
  173. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  174. package/registry/blocks/doc-editor/theme.js +82 -0
  175. package/registry/blocks/doc-page/README.md +119 -0
  176. package/registry/blocks/doc-page/autosave.js +104 -0
  177. package/registry/blocks/doc-page/block.json +10 -0
  178. package/registry/blocks/doc-page/demo.jsx +137 -0
  179. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  180. package/registry/blocks/doc-page/index.js +4 -0
  181. package/registry/blocks/email-render/README.md +151 -0
  182. package/registry/blocks/email-render/block.json +14 -0
  183. package/registry/blocks/email-render/demo.jsx +153 -0
  184. package/registry/blocks/email-render/doc-email.jsx +210 -0
  185. package/registry/blocks/email-render/email.jsx +221 -0
  186. package/registry/blocks/email-render/index.js +10 -0
  187. package/registry/blocks/email-render/render.js +50 -0
  188. package/registry/blocks/email-render/theme.js +215 -0
  189. package/registry/blocks/faq/README.md +101 -0
  190. package/registry/blocks/faq/block.json +11 -0
  191. package/registry/blocks/faq/demo.jsx +89 -0
  192. package/registry/blocks/faq/faq.jsx +220 -0
  193. package/registry/blocks/faq/index.js +4 -0
  194. package/registry/blocks/file-upload/README.md +138 -0
  195. package/registry/blocks/file-upload/block.json +10 -0
  196. package/registry/blocks/file-upload/demo.jsx +204 -0
  197. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  198. package/registry/blocks/file-upload/index.js +4 -0
  199. package/registry/blocks/flow-canvas/README.md +420 -0
  200. package/registry/blocks/flow-canvas/block.json +13 -0
  201. package/registry/blocks/flow-canvas/board.js +819 -0
  202. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  203. package/registry/blocks/flow-canvas/context.jsx +35 -0
  204. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  205. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  206. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  207. package/registry/blocks/flow-canvas/index.js +41 -0
  208. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  209. package/registry/blocks/flow-canvas/theme.js +174 -0
  210. package/registry/blocks/footer/README.md +133 -0
  211. package/registry/blocks/footer/block.json +11 -0
  212. package/registry/blocks/footer/demo.jsx +119 -0
  213. package/registry/blocks/footer/footer.jsx +406 -0
  214. package/registry/blocks/footer/index.js +4 -0
  215. package/registry/blocks/gantt/README.md +220 -0
  216. package/registry/blocks/gantt/block.json +10 -0
  217. package/registry/blocks/gantt/demo.jsx +148 -0
  218. package/registry/blocks/gantt/gantt.jsx +923 -0
  219. package/registry/blocks/gantt/index.js +7 -0
  220. package/registry/blocks/gantt/rows.jsx +468 -0
  221. package/registry/blocks/gantt/schedule.js +278 -0
  222. package/registry/blocks/job-panel/README.md +80 -0
  223. package/registry/blocks/job-panel/block.json +3 -3
  224. package/registry/blocks/job-panel/demo.jsx +230 -3
  225. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  226. package/registry/blocks/json-editor/README.md +133 -0
  227. package/registry/blocks/json-editor/block.json +10 -0
  228. package/registry/blocks/json-editor/demo.jsx +92 -0
  229. package/registry/blocks/json-editor/index.js +7 -0
  230. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  231. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  232. package/registry/blocks/json-editor/tree.js +225 -0
  233. package/registry/blocks/map/README.md +221 -0
  234. package/registry/blocks/map/block.json +14 -0
  235. package/registry/blocks/map/demo.jsx +201 -0
  236. package/registry/blocks/map/geo.js +198 -0
  237. package/registry/blocks/map/index.js +8 -0
  238. package/registry/blocks/map/list.jsx +128 -0
  239. package/registry/blocks/map/map-view.jsx +715 -0
  240. package/registry/blocks/map/maplibre.js +30 -0
  241. package/registry/blocks/map/marks.jsx +146 -0
  242. package/registry/blocks/map/theme.js +142 -0
  243. package/registry/blocks/menubar/README.md +109 -0
  244. package/registry/blocks/menubar/block.json +10 -0
  245. package/registry/blocks/menubar/demo.jsx +128 -0
  246. package/registry/blocks/menubar/index.js +4 -0
  247. package/registry/blocks/menubar/menubar.jsx +199 -0
  248. package/registry/blocks/mind-map/README.md +206 -0
  249. package/registry/blocks/mind-map/block.json +10 -0
  250. package/registry/blocks/mind-map/demo.jsx +103 -0
  251. package/registry/blocks/mind-map/index.js +31 -0
  252. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  253. package/registry/blocks/mind-map/topic.jsx +143 -0
  254. package/registry/blocks/mind-map/tree.js +645 -0
  255. package/registry/blocks/navigation-menu/README.md +124 -0
  256. package/registry/blocks/navigation-menu/block.json +10 -0
  257. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  258. package/registry/blocks/navigation-menu/index.js +4 -0
  259. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  260. package/registry/blocks/order-detail/README.md +109 -0
  261. package/registry/blocks/order-detail/block.json +10 -0
  262. package/registry/blocks/order-detail/demo.jsx +88 -0
  263. package/registry/blocks/order-detail/index.js +4 -0
  264. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  265. package/registry/blocks/org-chart/README.md +145 -0
  266. package/registry/blocks/org-chart/block.json +10 -0
  267. package/registry/blocks/org-chart/demo.jsx +94 -0
  268. package/registry/blocks/org-chart/index.js +7 -0
  269. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  270. package/registry/blocks/org-chart/org.js +245 -0
  271. package/registry/blocks/org-chart/person.jsx +96 -0
  272. package/registry/blocks/page-builder/README.md +257 -0
  273. package/registry/blocks/page-builder/block.json +14 -0
  274. package/registry/blocks/page-builder/demo.jsx +145 -0
  275. package/registry/blocks/page-builder/grapes.js +18 -0
  276. package/registry/blocks/page-builder/index.js +11 -0
  277. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  278. package/registry/blocks/page-builder/page-view.jsx +33 -0
  279. package/registry/blocks/page-builder/page.js +118 -0
  280. package/registry/blocks/page-builder/panels.jsx +588 -0
  281. package/registry/blocks/page-builder/sections.js +209 -0
  282. package/registry/blocks/page-builder/theme.js +87 -0
  283. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  284. package/registry/blocks/page-builder/tokens.js +329 -0
  285. package/registry/blocks/payment-methods/README.md +104 -0
  286. package/registry/blocks/payment-methods/block.json +10 -0
  287. package/registry/blocks/payment-methods/demo.jsx +71 -0
  288. package/registry/blocks/payment-methods/index.js +4 -0
  289. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  290. package/registry/blocks/pdf-document/README.md +213 -0
  291. package/registry/blocks/pdf-document/block.json +13 -0
  292. package/registry/blocks/pdf-document/demo.jsx +136 -0
  293. package/registry/blocks/pdf-document/index.js +33 -0
  294. package/registry/blocks/pdf-document/money.js +83 -0
  295. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  296. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  297. package/registry/blocks/pdf-document/quote.jsx +179 -0
  298. package/registry/blocks/pdf-document/theme.js +193 -0
  299. package/registry/blocks/pdf-viewer/README.md +191 -0
  300. package/registry/blocks/pdf-viewer/block.json +14 -0
  301. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  302. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  303. package/registry/blocks/pdf-viewer/index.js +8 -0
  304. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  305. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  306. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  307. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  308. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  309. package/registry/blocks/product-detail/README.md +217 -0
  310. package/registry/blocks/product-detail/block.json +10 -0
  311. package/registry/blocks/product-detail/demo.jsx +233 -0
  312. package/registry/blocks/product-detail/index.js +7 -0
  313. package/registry/blocks/product-detail/price.jsx +115 -0
  314. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  315. package/registry/blocks/product-detail/product-media.jsx +102 -0
  316. package/registry/blocks/product-detail/product-options.jsx +144 -0
  317. package/registry/blocks/product-grid/README.md +162 -0
  318. package/registry/blocks/product-grid/block.json +10 -0
  319. package/registry/blocks/product-grid/demo.jsx +255 -0
  320. package/registry/blocks/product-grid/index.js +5 -0
  321. package/registry/blocks/product-grid/product-card.jsx +232 -0
  322. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  323. package/registry/blocks/record-form/README.md +196 -0
  324. package/registry/blocks/record-form/block.json +10 -0
  325. package/registry/blocks/record-form/demo.jsx +525 -0
  326. package/registry/blocks/record-form/index.js +4 -0
  327. package/registry/blocks/record-form/record-fields.jsx +457 -0
  328. package/registry/blocks/record-form/record-form.jsx +415 -0
  329. package/registry/blocks/record-form/rules.js +81 -0
  330. package/registry/blocks/record-notes/README.md +139 -0
  331. package/registry/blocks/record-notes/block.json +10 -0
  332. package/registry/blocks/record-notes/demo.jsx +179 -0
  333. package/registry/blocks/record-notes/index.js +4 -0
  334. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  335. package/registry/blocks/search-dialog/README.md +108 -0
  336. package/registry/blocks/search-dialog/block.json +10 -0
  337. package/registry/blocks/search-dialog/demo.jsx +116 -0
  338. package/registry/blocks/search-dialog/index.js +3 -0
  339. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  340. package/registry/blocks/settings-list/README.md +171 -0
  341. package/registry/blocks/settings-list/block.json +10 -0
  342. package/registry/blocks/settings-list/demo.jsx +333 -0
  343. package/registry/blocks/settings-list/index.js +4 -0
  344. package/registry/blocks/settings-list/row-state.jsx +93 -0
  345. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  346. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  347. package/registry/blocks/setup-checklist/README.md +142 -0
  348. package/registry/blocks/setup-checklist/block.json +10 -0
  349. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  350. package/registry/blocks/setup-checklist/index.js +4 -0
  351. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  352. package/registry/blocks/share-dialog/README.md +113 -0
  353. package/registry/blocks/share-dialog/block.json +10 -0
  354. package/registry/blocks/share-dialog/demo.jsx +140 -0
  355. package/registry/blocks/share-dialog/index.js +3 -0
  356. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  357. package/registry/blocks/sidebar/README.md +190 -0
  358. package/registry/blocks/sidebar/block.json +43 -0
  359. package/registry/blocks/sidebar/demo.jsx +577 -0
  360. package/registry/blocks/sidebar/index.js +4 -0
  361. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  362. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  363. package/registry/blocks/signature-pad/README.md +137 -0
  364. package/registry/blocks/signature-pad/block.json +13 -0
  365. package/registry/blocks/signature-pad/colors.js +115 -0
  366. package/registry/blocks/signature-pad/demo.jsx +94 -0
  367. package/registry/blocks/signature-pad/index.js +6 -0
  368. package/registry/blocks/signature-pad/pad.js +7 -0
  369. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  370. package/registry/blocks/signature-pad/signature.js +68 -0
  371. package/registry/blocks/sketch-canvas/README.md +280 -0
  372. package/registry/blocks/sketch-canvas/block.json +13 -0
  373. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  374. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  375. package/registry/blocks/sketch-canvas/index.js +9 -0
  376. package/registry/blocks/sketch-canvas/palette.js +226 -0
  377. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  378. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  379. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  380. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  381. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  382. package/registry/blocks/sketch-canvas/theme.js +131 -0
  383. package/registry/blocks/spreadsheet/README.md +307 -0
  384. package/registry/blocks/spreadsheet/block.json +13 -0
  385. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  386. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  387. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  388. package/registry/blocks/spreadsheet/grid.js +387 -0
  389. package/registry/blocks/spreadsheet/index.js +34 -0
  390. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  391. package/registry/blocks/spreadsheet/types.js +473 -0
  392. package/registry/blocks/stat-cards/README.md +173 -0
  393. package/registry/blocks/stat-cards/block.json +10 -0
  394. package/registry/blocks/stat-cards/demo.jsx +257 -0
  395. package/registry/blocks/stat-cards/index.js +4 -0
  396. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  397. package/registry/blocks/stat-cards/usage.jsx +243 -0
  398. package/registry/blocks/task-list/README.md +176 -0
  399. package/registry/blocks/task-list/block.json +10 -0
  400. package/registry/blocks/task-list/demo.jsx +134 -0
  401. package/registry/blocks/task-list/index.js +5 -0
  402. package/registry/blocks/task-list/task-list.jsx +907 -0
  403. package/registry/blocks/task-model/README.md +455 -0
  404. package/registry/blocks/task-model/block.json +167 -0
  405. package/registry/blocks/task-model/changes.js +89 -0
  406. package/registry/blocks/task-model/dates.js +371 -0
  407. package/registry/blocks/task-model/demo.jsx +215 -0
  408. package/registry/blocks/task-model/dnd.jsx +240 -0
  409. package/registry/blocks/task-model/index.js +97 -0
  410. package/registry/blocks/task-model/model.js +919 -0
  411. package/registry/blocks/task-model/parts.jsx +449 -0
  412. package/registry/blocks/task-model/toolbar.jsx +271 -0
  413. package/registry/blocks/testimonials/README.md +139 -0
  414. package/registry/blocks/testimonials/block.json +11 -0
  415. package/registry/blocks/testimonials/demo.jsx +137 -0
  416. package/registry/blocks/testimonials/index.js +4 -0
  417. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  418. package/registry/blocks/transaction-list/README.md +126 -0
  419. package/registry/blocks/transaction-list/block.json +10 -0
  420. package/registry/blocks/transaction-list/demo.jsx +79 -0
  421. package/registry/blocks/transaction-list/index.js +4 -0
  422. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  423. package/registry/blocks/whiteboard/README.md +179 -0
  424. package/registry/blocks/whiteboard/block.json +10 -0
  425. package/registry/blocks/whiteboard/demo.jsx +169 -0
  426. package/registry/blocks/whiteboard/index.js +6 -0
  427. package/registry/blocks/whiteboard/templates.js +150 -0
  428. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  429. package/src/cli.mjs +19 -6
  430. package/src/install.mjs +18 -0
  431. package/src/registry.mjs +38 -4
  432. package/src/shadcn.mjs +14 -1
  433. package/templates/next/files/README.md +145 -11
  434. package/templates/next/files/app/globals.css +55 -4
  435. package/templates/next/files/check/run.mjs +3 -3
  436. package/templates/next/files/components/ui/avatar.jsx +141 -0
  437. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  438. package/templates/next/files/components/ui/button-group.jsx +70 -0
  439. package/templates/next/files/components/ui/button.jsx +132 -12
  440. package/templates/next/files/components/ui/calendar.jsx +609 -0
  441. package/templates/next/files/components/ui/carousel.jsx +281 -0
  442. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  443. package/templates/next/files/components/ui/combobox.jsx +608 -0
  444. package/templates/next/files/components/ui/command.jsx +577 -0
  445. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  446. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  447. package/templates/next/files/components/ui/distribution.jsx +117 -0
  448. package/templates/next/files/components/ui/feedback.jsx +143 -0
  449. package/templates/next/files/components/ui/field.jsx +115 -3
  450. package/templates/next/files/components/ui/file-input.jsx +234 -0
  451. package/templates/next/files/components/ui/icon.jsx +130 -8
  452. package/templates/next/files/components/ui/image.jsx +143 -0
  453. package/templates/next/files/components/ui/index.js +47 -2
  454. package/templates/next/files/components/ui/input-group.jsx +213 -0
  455. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  456. package/templates/next/files/components/ui/item.jsx +206 -0
  457. package/templates/next/files/components/ui/menu.jsx +454 -82
  458. package/templates/next/files/components/ui/notice.jsx +126 -14
  459. package/templates/next/files/components/ui/pagination.jsx +156 -0
  460. package/templates/next/files/components/ui/popover.jsx +284 -0
  461. package/templates/next/files/components/ui/radio.jsx +193 -0
  462. package/templates/next/files/components/ui/rating.jsx +131 -0
  463. package/templates/next/files/components/ui/resizable.jsx +338 -0
  464. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  465. package/templates/next/files/components/ui/separator.jsx +119 -0
  466. package/templates/next/files/components/ui/sheet.jsx +96 -11
  467. package/templates/next/files/components/ui/slider.jsx +174 -0
  468. package/templates/next/files/components/ui/stat.jsx +574 -0
  469. package/templates/next/files/components/ui/steps.jsx +338 -0
  470. package/templates/next/files/components/ui/swatch.jsx +33 -0
  471. package/templates/next/files/components/ui/table.jsx +130 -0
  472. package/templates/next/files/components/ui/toast.jsx +440 -0
  473. package/templates/next/files/components/ui/toggle.jsx +195 -0
  474. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  475. package/templates/next/template.json +264 -8
@@ -0,0 +1,119 @@
1
+ # DocPage
2
+
3
+ One Notion-style page: an emoji icon, a big title, and the rich text
4
+ under it. The text is the `doc-editor` block (type `/` for headings,
5
+ lists, checklists, tables; `@` mentions a person). Edits save themselves
6
+ through `onSave` a moment after typing stops; the top bar says **Saved**,
7
+ **Saving…** or **Couldn't save** with a Retry. Cmd/Ctrl+S saves at once.
8
+ Read-only shows the same page with nothing to edit. It is the wiki page:
9
+ `knowledge-base` puts a page tree beside it.
10
+
11
+ ```jsx
12
+ import { DocPage } from "../components/blocks/doc-page"; // a Makersclaw app ("./blocks/doc-page" from components/)
13
+ import { DocPage } from "@/components/makersclaw/blocks/doc-page"; // a shadcn project
14
+ ```
15
+
16
+ It is a client component: render it from a `"use client"` component, and
17
+ load the page in the server surface (README §4). `makersclaw add
18
+ doc-page` adds `doc-editor` too (and its BlockNote packages: run `npm
19
+ install` after).
20
+
21
+ ## The data
22
+
23
+ A page is `{ id, title, icon, doc }`:
24
+
25
+ - `id` — the page's key.
26
+ - `title` — plain text, one line (it wraps on screen).
27
+ - `icon` — an emoji, or `null` for none.
28
+ - `doc` — the body as BlockNote JSON (see the doc-editor README): store
29
+ it as it comes, in a `jsonb` column.
30
+
31
+ `onSave` receives the whole page, every time.
32
+
33
+ ## Props
34
+
35
+ - `id` — which page this is. The page reads `title`, `icon` and `doc`
36
+ when it mounts and again whenever `id` changes; in between it owns the
37
+ draft, so a parent re-rendering with older props never throws away
38
+ typing. To show another page, change `id`.
39
+ - `title` — default `""`.
40
+ - `icon` — default `null`.
41
+ - `doc` — default an empty doc.
42
+ - `onSave(page)` — `async ({ id, title, icon, doc }) => ({ ok, error? })`.
43
+ Called `saveDelay` ms after the last edit, one save at a time (edits
44
+ made during a save go out right after it). `{ ok: false, error }` or a
45
+ throw shows "Couldn't save" with `error` as the reason and a Retry; the
46
+ edits stay on screen and the next edit tries again. Without `onSave`
47
+ there is no save state (an editor you read from `onChange`).
48
+ - `onChange(page)` — every edit, with the whole page (to update a title
49
+ in a list beside it as it is typed). Not a save.
50
+ - `readOnly` — `false` (default). `true`: the title is a heading, the
51
+ icon a picture, the editor read-only; no save state.
52
+ - `saveDelay` — ms of quiet before a save, default `1000`.
53
+ - `placeholder` — the empty body's hint, default "Write something, or
54
+ press / for blocks".
55
+ - `titlePlaceholder` — default "Untitled".
56
+ - `icons` — the emoji offered by the icon picker (default 24 common
57
+ ones). `[]` turns picking off (a given `icon` still shows).
58
+ - `meta` — a node under the title: "Edited by June · 2 days ago".
59
+ - `breadcrumb` — a node at the left of the top bar (where the page
60
+ sits).
61
+ - `actions` — a node at the right of the top bar: a kit `Menu` of page
62
+ actions, a Share button.
63
+ - `width` — `"normal"` (default, a reading column) · `"wide"` · `"full"`.
64
+ - `autoFocus` — put the caret in the title when it mounts (a page just
65
+ created).
66
+ - `mentions`, `fields`, `slashItems`, `uploadFile` — passed to the
67
+ editor; see the doc-editor README.
68
+ - `className` — layout around it. Never colour.
69
+
70
+ Keys: Enter or ↓ at the end of the title moves into the body; Cmd/Ctrl+S
71
+ saves now. A tab closed with an edit unsaved asks first; a page left
72
+ (another `id`, the surface unmounted) sends its unsent edit on the way
73
+ out without waiting for the answer.
74
+
75
+ ## Example
76
+
77
+ ```jsx
78
+ // components/WikiPage.jsx — client
79
+ "use client";
80
+ import { updateRow } from "../lib/actions";
81
+ import { DocPage } from "./blocks/doc-page";
82
+
83
+ export default function WikiPage({ page, team, canEdit }) {
84
+ return (
85
+ <DocPage
86
+ id={page.id}
87
+ title={page.title}
88
+ icon={page.icon}
89
+ doc={page.body}
90
+ readOnly={!canEdit}
91
+ meta={`Edited by ${page.edited_by_name}`}
92
+ onSave={({ id, title, icon, doc }) =>
93
+ updateRow({ source: "public.wiki_pages", id, patch: { title, icon, body: doc } })
94
+ }
95
+ mentions={async (q) =>
96
+ team.filter((p) => p.name.toLowerCase().includes(q.toLowerCase())).map((p) => ({ id: p.id, label: p.name }))
97
+ }
98
+ />
99
+ );
100
+ }
101
+ ```
102
+
103
+ For search or a preview, keep a plain-text copy beside the doc:
104
+ `docToText(doc)` from the doc-editor block, saved in the same `onSave`.
105
+
106
+ ## What it will not do
107
+
108
+ - Hold more than one page, or a tree of them: that is `knowledge-base`.
109
+ - Collaborate live: saves are last-write-wins, whole page at a time.
110
+ - Keep an edit when the browser is closed without an answer: the tab
111
+ asks before closing while an edit is unsaved; after that it is gone.
112
+ - Cover images, page history, comments or sharing: put your own
113
+ controls in `actions`.
114
+ - Pick any emoji in the world: the grid is `icons`.
115
+
116
+ A page it cannot be is your own component in `components/`, built on
117
+ the doc-editor block — not an edit to this block. Its files are fixed:
118
+ `npm run check` refuses a change, and `makersclaw add doc-page` restores
119
+ them.
@@ -0,0 +1,104 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+
5
+ // useAutosave — the save loop behind DocPage, kept apart so it reads on
6
+ // its own. Every edit bumps a version and (re)starts a timer; when the
7
+ // timer fires the latest page goes out through `save`. One save at a
8
+ // time: edits made while one is in flight are sent right after it. A
9
+ // failure keeps the edits, says so, and the next edit (or `flush`) tries
10
+ // again. Leaving (unmount) sends what is still unsent, without waiting.
11
+ //
12
+ // status "saved" · "pending" (an edit waits for the timer) ·
13
+ // "saving" · "error"
14
+ // error the failure's text while status is "error"
15
+ // change(payload) an edit: payload is what `save` will receive
16
+ // flush() save now (Cmd/Ctrl+S, Retry)
17
+
18
+ export function useAutosave(save, delay = 1000) {
19
+ const [status, setStatus] = useState("saved");
20
+ const [error, setError] = useState(null);
21
+ const saveRef = useRef(save);
22
+ saveRef.current = save;
23
+ const latest = useRef(null);
24
+ const version = useRef(0);
25
+ const saved = useRef(0);
26
+ const busy = useRef(false);
27
+ const timer = useRef(null);
28
+ const alive = useRef(true);
29
+
30
+ const run = useCallback(async () => {
31
+ clearTimeout(timer.current);
32
+ timer.current = null;
33
+ if (busy.current || !saveRef.current) return;
34
+ if (version.current === saved.current) {
35
+ setStatus("saved");
36
+ return;
37
+ }
38
+ const v = version.current;
39
+ busy.current = true;
40
+ setStatus("saving");
41
+ let res;
42
+ try {
43
+ res = await saveRef.current(latest.current);
44
+ } catch (e) {
45
+ res = { ok: false, error: e?.message };
46
+ }
47
+ busy.current = false;
48
+ if (!alive.current) return;
49
+ if (res?.ok === false) {
50
+ setError(res.error || "Couldn't reach the server.");
51
+ setStatus("error");
52
+ return;
53
+ }
54
+ saved.current = Math.max(saved.current, v);
55
+ setError(null);
56
+ if (version.current !== saved.current) run();
57
+ else setStatus("saved");
58
+ }, []);
59
+
60
+ const change = useCallback(
61
+ (payload) => {
62
+ latest.current = payload;
63
+ version.current += 1;
64
+ if (!saveRef.current) return;
65
+ setStatus((s) => (s === "saving" ? s : "pending"));
66
+ clearTimeout(timer.current);
67
+ timer.current = setTimeout(run, delay);
68
+ },
69
+ [delay, run],
70
+ );
71
+
72
+ const flush = useCallback(() => {
73
+ run();
74
+ }, [run]);
75
+
76
+ // Unsent edits on the way out: warn before the tab closes, and send them
77
+ // when the page goes (another page opened, the surface left).
78
+ const unsent = status !== "saved";
79
+ useEffect(() => {
80
+ if (!unsent) return;
81
+ const warn = (e) => {
82
+ e.preventDefault();
83
+ e.returnValue = "";
84
+ };
85
+ window.addEventListener("beforeunload", warn);
86
+ return () => window.removeEventListener("beforeunload", warn);
87
+ }, [unsent]);
88
+
89
+ useEffect(() => {
90
+ alive.current = true;
91
+ return () => {
92
+ alive.current = false;
93
+ clearTimeout(timer.current);
94
+ if (version.current !== saved.current && saveRef.current) {
95
+ saved.current = version.current;
96
+ Promise.resolve()
97
+ .then(() => saveRef.current(latest.current))
98
+ .catch(() => {});
99
+ }
100
+ };
101
+ }, []);
102
+
103
+ return { status, error, change, flush };
104
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "doc-page",
3
+ "title": "DocPage",
4
+ "description": "A Notion-style page: an emoji icon (picked from a grid), a big plain title, and the rich-text editor under it (doc-editor: / menu, markdown shortcuts, @mentions). Edits autosave through an async onSave a moment after typing stops, with Saved / Saving… / Couldn't save + Retry in the top bar, Cmd/Ctrl+S to save now and unsent edits sent when the page is left. A read-only mode shows the same page with nothing to edit; slots for a breadcrumb, actions and a meta line.",
5
+ "useWhen": "A screen is one document someone reads and writes: a wiki or handbook page, a playbook, a policy, a project page, a one-pager. The knowledge-base block puts a page tree beside it. Not for a short field of rich text inside a form (doc-editor), notes on a record (record-notes) or a comment (comment-box).",
6
+ "tags": ["page", "document", "doc", "wiki", "notion", "editor", "rich text", "autosave", "title", "icon", "emoji", "read-only", "handbook", "notes"],
7
+ "exports": ["DocPage"],
8
+ "files": ["index.js", "doc-page.jsx", "autosave.js"],
9
+ "requires": ["doc-editor"]
10
+ }
@@ -0,0 +1,137 @@
1
+ "use client";
2
+
3
+ // DocPage two ways — the gallery's and the smoke test's surface. Not
4
+ // installed into apps.
5
+ // Editable a handbook page that autosaves. Pick whether the pretend
6
+ // server takes the save or refuses it, and watch the bar go
7
+ // Saving… → Saved, or → Couldn't save with Retry.
8
+ // Read-only the same page for someone who may only read it.
9
+ import { useState } from "react";
10
+ import { Card, Kicker, Menu, ToggleGroup } from "../components/ui";
11
+ import { DocPage } from "../components/blocks/doc-page";
12
+ import { docToText } from "../components/blocks/doc-editor";
13
+
14
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
15
+ const t = (text, styles = {}) => ({ type: "text", text, styles });
16
+
17
+ const PEOPLE = [
18
+ { id: "u-june", label: "June Okafor", description: "People ops" },
19
+ { id: "u-tomas", label: "Tomás Ortega", description: "Engineering" },
20
+ { id: "u-lena", label: "Lena Fischer", description: "Sales" },
21
+ ];
22
+ const findPeople = async (q) => PEOPLE.filter((p) => p.label.toLowerCase().includes(q.toLowerCase()));
23
+
24
+ const HANDBOOK_PAGE = {
25
+ id: "page-onboarding",
26
+ icon: "👋",
27
+ title: "Your first week at Larkspur",
28
+ doc: [
29
+ { type: "paragraph", content: [t("Welcome aboard. This page is the one place to look during week one; "), { type: "mention", props: { id: "u-june", label: "June Okafor" } }, t(" keeps it current.")] },
30
+ { type: "heading", props: { level: 2 }, content: [t("Day one")] },
31
+ { type: "checkListItem", props: { checked: true }, content: [t("Pick up your laptop from the front desk")] },
32
+ { type: "checkListItem", content: [t("Set up SSO and the password manager")] },
33
+ { type: "checkListItem", content: [t("Book a 30-minute intro with your manager")] },
34
+ { type: "heading", props: { level: 2 }, content: [t("How we work")] },
35
+ { type: "bulletListItem", content: [t("Writing beats meetings: "), t("decisions live in docs", { bold: true }), t(", not in threads.")] },
36
+ { type: "bulletListItem", content: [t("Core hours are 10:00–15:00 in your own time zone.")] },
37
+ { type: "bulletListItem", content: [t("Ship small, ship on Tuesdays and Thursdays.")] },
38
+ { type: "quote", content: [t("If you are unsure who owns something, ask in the team channel. Nobody minds.")] },
39
+ ],
40
+ };
41
+
42
+ function EditableDemo() {
43
+ const [outcome, setOutcome] = useState("ok");
44
+ const [last, setLast] = useState(null);
45
+ const save = async (page) => {
46
+ await wait(700);
47
+ if (outcome === "fail") return { ok: false, error: "The server is not answering. Your edits are still here." };
48
+ setLast({ title: page.title || "Untitled", words: docToText(page.doc ?? []).split(/\s+/).filter(Boolean).length, icon: page.icon });
49
+ return { ok: true };
50
+ };
51
+ return (
52
+ <div className="grid gap-4">
53
+ <div className="flex flex-wrap items-center gap-3">
54
+ <Kicker>Saves</Kicker>
55
+ <ToggleGroup
56
+ type="single"
57
+ size="sm"
58
+ aria-label="What the pretend server does"
59
+ value={outcome}
60
+ onChange={(v) => v && setOutcome(v)}
61
+ items={[
62
+ { value: "ok", label: "Succeed" },
63
+ { value: "fail", label: "Fail" },
64
+ ]}
65
+ />
66
+ <span className="text-sm text-muted-foreground">
67
+ {last ? `Last saved: ${last.icon ?? ""} ${last.title} · ${last.words} words` : "Nothing saved yet: edit the title or the page."}
68
+ </span>
69
+ </div>
70
+ <Card>
71
+ <DocPage
72
+ {...HANDBOOK_PAGE}
73
+ onSave={save}
74
+ mentions={findPeople}
75
+ meta="Edited by June Okafor · 2 days ago"
76
+ breadcrumb={<span className="truncate text-sm text-muted-foreground">Handbook / People</span>}
77
+ actions={
78
+ <Menu
79
+ label="Page actions"
80
+ items={[
81
+ { label: "Copy link", icon: "link", onSelect: () => {} },
82
+ { label: "Move to…", icon: "folder", onSelect: () => {} },
83
+ { type: "separator" },
84
+ { label: "Delete page", icon: "trash", tone: "danger", onSelect: () => {} },
85
+ ]}
86
+ />
87
+ }
88
+ />
89
+ </Card>
90
+ </div>
91
+ );
92
+ }
93
+
94
+ function ReadOnlyDemo() {
95
+ return (
96
+ <Card>
97
+ <DocPage {...HANDBOOK_PAGE} id="page-onboarding-ro" readOnly meta="You can read this page. Ask June Okafor to edit it." />
98
+ </Card>
99
+ );
100
+ }
101
+
102
+ function BlankDemo() {
103
+ const [saved, setSaved] = useState(0);
104
+ return (
105
+ <Card>
106
+ <DocPage
107
+ id="page-new"
108
+ onSave={async () => {
109
+ await wait(400);
110
+ setSaved((n) => n + 1);
111
+ return { ok: true };
112
+ }}
113
+ meta={saved ? `Saved ${saved} time${saved === 1 ? "" : "s"}` : "A new page: no icon, no title yet."}
114
+ />
115
+ </Card>
116
+ );
117
+ }
118
+
119
+ export default function DocPageDemo() {
120
+ const [view, setView] = useState("edit");
121
+ return (
122
+ <div className="grid gap-4">
123
+ <ToggleGroup
124
+ type="single"
125
+ aria-label="Which page"
126
+ value={view}
127
+ onChange={(v) => v && setView(v)}
128
+ items={[
129
+ { value: "edit", label: "Editable" },
130
+ { value: "read", label: "Read-only" },
131
+ { value: "blank", label: "New page" },
132
+ ]}
133
+ />
134
+ {view === "edit" ? <EditableDemo /> : view === "read" ? <ReadOnlyDemo /> : <BlankDemo />}
135
+ </div>
136
+ );
137
+ }
@@ -0,0 +1,276 @@
1
+ "use client";
2
+
3
+ // DocPage — one Notion-style page: an icon, a title, the rich text under
4
+ // it (DocEditor), and a save state in the top bar. Edits save themselves
5
+ // through `onSave` a moment after typing stops (useAutosave), and the bar
6
+ // says "Saved", "Saving…" or "Couldn't save" with a Retry. Read-only
7
+ // shows the same page with nothing to edit.
8
+ //
9
+ // The page reads `title`, `icon` and `doc` when it mounts and whenever
10
+ // `id` changes (another page opened); in between it owns the draft, so a
11
+ // parent re-rendering with stale props never throws away typing. Leaving
12
+ // a page with an edit still unsent sends it on the way out.
13
+ import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
14
+ import { Button, Icon, Popover, Spinner, cx } from "../../ui";
15
+ import { DocEditor, emptyDoc, useDocEditor } from "../doc-editor";
16
+ import { useAutosave } from "./autosave";
17
+
18
+ const DEFAULT_ICONS = [
19
+ "📄", "📘", "📝", "📌", "📎", "🗂️",
20
+ "💡", "🎯", "🚀", "📈", "🧭", "🛠️",
21
+ "🤝", "👋", "📣", "🧪", "🔒", "⚙️",
22
+ "🗓️", "✅", "❓", "⭐", "🌱", "🏁",
23
+ ];
24
+
25
+ const WIDTHS = { normal: "max-w-3xl", wide: "max-w-5xl", full: "max-w-none" };
26
+
27
+ export function DocPage({ id, ...props }) {
28
+ // A new id is a new page: remount, so the draft, the editor and the save
29
+ // loop start from that page (the old one flushes on its way out).
30
+ return <PageBody key={id ?? "page"} id={id} {...props} />;
31
+ }
32
+
33
+ function PageBody({
34
+ id,
35
+ title: initialTitle = "",
36
+ icon: initialIcon = null,
37
+ doc: initialDoc,
38
+ onSave,
39
+ onChange,
40
+ readOnly = false,
41
+ saveDelay = 1000,
42
+ placeholder = "Write something, or press / for blocks",
43
+ titlePlaceholder = "Untitled",
44
+ icons = DEFAULT_ICONS,
45
+ meta,
46
+ breadcrumb,
47
+ actions,
48
+ width = "normal",
49
+ autoFocus = false,
50
+ mentions,
51
+ fields,
52
+ slashItems,
53
+ uploadFile,
54
+ className,
55
+ }) {
56
+ const [title, setTitle] = useState(initialTitle ?? "");
57
+ const [icon, setIcon] = useState(initialIcon || null);
58
+ // The page as last edited, read by every save (the editor's onChange and
59
+ // the title's fire from different renders).
60
+ const current = useRef({ id, title: initialTitle ?? "", icon: initialIcon || null, doc: Array.isArray(initialDoc) && initialDoc.length ? initialDoc : emptyDoc() });
61
+ const editorRef = useDocEditor();
62
+ const titleRef = useRef(null);
63
+ const saving = useAutosave(onSave && !readOnly ? onSave : null, saveDelay);
64
+
65
+ const edit = (patch) => {
66
+ const page = { ...current.current, ...patch };
67
+ current.current = page;
68
+ onChange?.(page);
69
+ saving.change(page);
70
+ };
71
+
72
+ // The title grows with its text (it wraps on a phone) and never holds a
73
+ // line break: Enter moves into the page instead.
74
+ useLayoutEffect(() => {
75
+ const el = titleRef.current;
76
+ if (!el) return;
77
+ el.style.height = "auto";
78
+ el.style.height = `${el.scrollHeight}px`;
79
+ }, [title]);
80
+ useEffect(() => {
81
+ if (autoFocus && !readOnly) titleRef.current?.focus();
82
+ }, [autoFocus, readOnly]);
83
+
84
+ const onTitleKey = (e) => {
85
+ if (e.key === "Enter" && !e.nativeEvent.isComposing) {
86
+ e.preventDefault();
87
+ editorRef.current?.focus();
88
+ } else if (e.key === "ArrowDown" && e.currentTarget.selectionStart === e.currentTarget.value.length) {
89
+ e.preventDefault();
90
+ editorRef.current?.focus();
91
+ }
92
+ };
93
+
94
+ // Cmd/Ctrl+S saves now instead of the browser's "save page as".
95
+ const onKeyDown = (e) => {
96
+ if (!onSave || readOnly) return;
97
+ if ((e.metaKey || e.ctrlKey) && !e.altKey && e.key.toLowerCase() === "s") {
98
+ e.preventDefault();
99
+ saving.flush();
100
+ }
101
+ };
102
+
103
+ const showBar = breadcrumb || actions || (onSave && !readOnly);
104
+
105
+ return (
106
+ // raw: a plain box that hears Cmd/Ctrl+S from the title and the editor
107
+ // inside it; no control of its own.
108
+ <article className={cx("group/page mx-auto w-full min-w-0", WIDTHS[width] ?? WIDTHS.normal, className)} onKeyDown={onKeyDown}>
109
+ {showBar ? (
110
+ <div className="flex min-h-11 items-center gap-2">
111
+ <div className="min-w-0 flex-1">{breadcrumb}</div>
112
+ {onSave && !readOnly ? <SaveState status={saving.status} error={saving.error} onRetry={saving.flush} /> : null}
113
+ {actions ? <div className="flex shrink-0 items-center gap-1">{actions}</div> : null}
114
+ </div>
115
+ ) : null}
116
+
117
+ <header className="pt-6 sm:ps-12 sm:pt-10">
118
+ {readOnly ? (
119
+ icon ? (
120
+ <div className="mb-2 text-5xl leading-none" aria-hidden="true">
121
+ {icon}
122
+ </div>
123
+ ) : null
124
+ ) : (
125
+ <IconPicker icon={icon} icons={icons} onPick={(next) => {
126
+ setIcon(next);
127
+ edit({ icon: next });
128
+ }} />
129
+ )}
130
+
131
+ {readOnly ? (
132
+ <h1 className="text-3xl font-bold leading-tight tracking-tight text-foreground [overflow-wrap:anywhere] sm:text-4xl">
133
+ {title || <span className="text-muted-foreground">{titlePlaceholder}</span>}
134
+ </h1>
135
+ ) : (
136
+ // raw: a page title is heading-sized text that wraps with no box
137
+ // around it; the kit's Input and Textarea are boxed form fields.
138
+ <textarea
139
+ ref={titleRef}
140
+ rows={1}
141
+ value={title}
142
+ placeholder={titlePlaceholder}
143
+ aria-label="Page title"
144
+ spellCheck
145
+ onChange={(e) => {
146
+ const next = e.target.value.replace(/\r?\n/g, " ");
147
+ setTitle(next);
148
+ edit({ title: next });
149
+ }}
150
+ onKeyDown={onTitleKey}
151
+ className="block w-full resize-none overflow-hidden border-0 bg-transparent p-0 text-3xl font-bold leading-tight tracking-tight text-foreground outline-none placeholder:text-muted-foreground/70 focus-visible:outline-none sm:text-4xl"
152
+ />
153
+ )}
154
+ {meta ? <div className="mt-2 text-sm text-muted-foreground">{meta}</div> : null}
155
+ </header>
156
+
157
+ <div className="mt-4 pb-16">
158
+ <DocEditor
159
+ defaultValue={initialDoc}
160
+ onChange={(doc) => edit({ doc })}
161
+ editable={!readOnly}
162
+ placeholder={placeholder}
163
+ editorRef={editorRef}
164
+ label={title || titlePlaceholder}
165
+ mentions={mentions}
166
+ fields={fields}
167
+ slashItems={slashItems}
168
+ uploadFile={uploadFile}
169
+ className="min-h-64"
170
+ />
171
+ </div>
172
+ </article>
173
+ );
174
+ }
175
+
176
+ /** "Saved" · "Saving…" · "Couldn't save" + Retry, announced politely. */
177
+ function SaveState({ status, error, onRetry }) {
178
+ return (
179
+ <div role="status" aria-live="polite" className="flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground">
180
+ {status === "error" ? (
181
+ <>
182
+ <span className="flex items-center gap-1 text-destructive" title={error || undefined}>
183
+ <Icon name="warning" size={14} />
184
+ Couldn't save
185
+ </span>
186
+ <span className="sr-only">{error}</span>
187
+ <Button variant="link" size="sm" onClick={onRetry}>
188
+ Retry
189
+ </Button>
190
+ </>
191
+ ) : status === "saved" ? (
192
+ <span className="flex items-center gap-1">
193
+ <Icon name="check" size={14} />
194
+ Saved
195
+ </span>
196
+ ) : (
197
+ <span className="flex items-center gap-1.5">
198
+ <Spinner size="sm" label={null} />
199
+ Saving…
200
+ </span>
201
+ )}
202
+ </div>
203
+ );
204
+ }
205
+
206
+ /** The page's icon: a big emoji that opens a grid of others, or "Add icon"
207
+ * while there is none. An empty `icons` list turns picking off. */
208
+ function IconPicker({ icon, icons, onPick }) {
209
+ const [open, setOpen] = useState(false);
210
+ const gridId = useId();
211
+ if (!icons?.length) {
212
+ return icon ? (
213
+ <div className="mb-2 text-5xl leading-none" aria-hidden="true">
214
+ {icon}
215
+ </div>
216
+ ) : null;
217
+ }
218
+ const pick = (next) => {
219
+ onPick(next);
220
+ setOpen(false);
221
+ };
222
+ return (
223
+ <div className={cx(icon ? "mb-2" : "mb-1 -ms-3")}>
224
+ <Popover
225
+ open={open}
226
+ onOpenChange={setOpen}
227
+ side="bottom"
228
+ align="start"
229
+ width="auto"
230
+ label="Page icon"
231
+ className="p-2"
232
+ trigger={(p) =>
233
+ icon ? (
234
+ // raw: the page icon is a 64px emoji you press; the kit's
235
+ // Button squares are 36 and 44px and cx cannot resize them.
236
+ <button
237
+ {...p}
238
+ type="button"
239
+ aria-label={`Page icon ${icon}, change it`}
240
+ className="-ms-2 grid size-16 place-items-center rounded-md outline-none hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring"
241
+ >
242
+ <span className="text-5xl leading-none" aria-hidden="true">
243
+ {icon}
244
+ </span>
245
+ </button>
246
+ ) : (
247
+ <Button
248
+ {...p}
249
+ variant="quiet"
250
+ size="sm"
251
+ icon="plus"
252
+ className="text-muted-foreground opacity-0 transition-opacity group-hover/page:opacity-100 group-focus-within/page:opacity-100 focus-visible:opacity-100 [@media(hover:none)]:opacity-100"
253
+ >
254
+ Add icon
255
+ </Button>
256
+ )
257
+ }
258
+ >
259
+ <div id={gridId} role="group" aria-label="Choose an icon" className="grid grid-cols-6 gap-1">
260
+ {icons.map((e) => (
261
+ <Button key={e} variant="quiet" iconOnly aria-label={e} aria-pressed={e === icon} onClick={() => pick(e)} className="aria-pressed:bg-accent">
262
+ <span className="text-2xl leading-none">{e}</span>
263
+ </Button>
264
+ ))}
265
+ </div>
266
+ {icon ? (
267
+ <div className="mt-2 border-t border-border pt-2">
268
+ <Button variant="quiet" size="sm" icon="trash" onClick={() => pick(null)} className="w-full">
269
+ Remove icon
270
+ </Button>
271
+ </div>
272
+ ) : null}
273
+ </Popover>
274
+ </div>
275
+ );
276
+ }
@@ -0,0 +1,4 @@
1
+ // The DocPage block — `makersclaw add doc-page`. Fixed: compose it through
2
+ // its props (README.md beside this file). A page it cannot be is your own
3
+ // component in components/, built on the doc-editor block.
4
+ export { DocPage } from "./doc-page";