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,179 @@
1
+ "use client";
2
+
3
+ // QuoteDocument — the default business document: a quote, an estimate or
4
+ // an invoice, from data. The quote-builder and proposal blocks print
5
+ // through it; an app can too (renderPdf(<QuoteDocument … />)).
6
+ //
7
+ // The layout is the classic one people trust: who it is from at the top
8
+ // left, what it is and its number at the top right, then who it is for,
9
+ // the dates and the amount in a row of labelled fields, the lines in a
10
+ // table, the sums flush right, and notes, terms and how to pay at the
11
+ // foot. One accent (the theme's primary): the bar along the top edge and
12
+ // the amount due. Everything else is ink and grey on paper.
13
+ import { Image, View } from "@react-pdf/renderer";
14
+ import {
15
+ PdfBadge,
16
+ PdfCallout,
17
+ PdfCol,
18
+ PdfDivider,
19
+ PdfDocument,
20
+ PdfField,
21
+ PdfHeading,
22
+ PdfLabel,
23
+ PdfLines,
24
+ PdfRow,
25
+ PdfStack,
26
+ PdfTable,
27
+ PdfText,
28
+ PdfTotals,
29
+ } from "./primitives";
30
+ import { formatMoney, formatPdfDate, formatQuantity, quoteTotals } from "./money";
31
+
32
+ const WORDS = {
33
+ quote: { title: "Quote", to: "Prepared for", date: "Issued", until: "Valid until", total: "Total" },
34
+ estimate: { title: "Estimate", to: "Prepared for", date: "Issued", until: "Valid until", total: "Estimated total" },
35
+ invoice: { title: "Invoice", to: "Billed to", date: "Issued", until: "Due", total: "Amount due" },
36
+ };
37
+
38
+ /** A quote, estimate or invoice. See README ## QuoteDocument for every prop. */
39
+ export function QuoteDocument({
40
+ kind = "quote",
41
+ number,
42
+ title,
43
+ issued,
44
+ until,
45
+ from = {},
46
+ to = {},
47
+ items = [],
48
+ currency = "USD",
49
+ locale = "en-US",
50
+ dateLocale = "en-GB",
51
+ taxRate,
52
+ taxLabel,
53
+ discount,
54
+ paid,
55
+ status,
56
+ statusTone = "success",
57
+ notes,
58
+ terms,
59
+ payment,
60
+ reference,
61
+ footer,
62
+ size = "A4",
63
+ }) {
64
+ const w = WORDS[kind] ?? WORDS.quote;
65
+ const sums = quoteTotals({ items, discount, taxRate, paid });
66
+ const money = (n) => formatMoney(n, currency, locale);
67
+ const docTitle = title ?? w.title;
68
+ const fromLines = [from.name, ...(from.lines ?? []), from.email, from.phone, from.taxId ? `Tax ID ${from.taxId}` : null];
69
+ const toLines = [to.name, to.company, ...(to.lines ?? []), to.email];
70
+ const amountLabel = kind === "invoice" && sums.paid > 0 ? "Balance due" : w.total;
71
+ const hasSums = sums.discount > 0 || sums.tax > 0 || sums.paid > 0;
72
+
73
+ return (
74
+ <PdfDocument
75
+ title={[docTitle, number].filter(Boolean).join(" ")}
76
+ author={from.name}
77
+ subject={to.company ?? to.name}
78
+ size={size}
79
+ footer={footer ?? [from.name, from.email, from.website].filter(Boolean).join(" · ")}
80
+ >
81
+ {/* Top: the sender (logo or name), and what this is. */}
82
+ <PdfRow justify="between" align="start" gap={24}>
83
+ <PdfCol>
84
+ {from.logo ? <Image src={from.logo} style={{ height: 28, objectFit: "contain", objectPosition: "left", marginBottom: 10, alignSelf: "flex-start" }} /> : null}
85
+ <PdfLines lines={fromLines} first={!from.logo} />
86
+ </PdfCol>
87
+ <PdfCol flex={0} style={{ alignItems: "flex-end" }}>
88
+ <PdfHeading level={1} align="right">
89
+ {docTitle}
90
+ </PdfHeading>
91
+ {number ? (
92
+ <PdfText tone="muted" align="right" style={{ marginTop: 4 }}>
93
+ {number}
94
+ </PdfText>
95
+ ) : null}
96
+ {status ? (
97
+ <View style={{ marginTop: 8, alignSelf: "flex-end" }}>
98
+ <PdfBadge tone={statusTone}>{status}</PdfBadge>
99
+ </View>
100
+ ) : null}
101
+ </PdfCol>
102
+ </PdfRow>
103
+
104
+ <PdfDivider space={24} />
105
+
106
+ {/* Who it is for, the dates, and the one number that matters. */}
107
+ <PdfRow gap={24} align="start">
108
+ <PdfCol flex={1.6}>
109
+ <PdfLabel>{w.to}</PdfLabel>
110
+ <PdfLines lines={toLines} />
111
+ </PdfCol>
112
+ <PdfCol>
113
+ <PdfStack gap={10}>
114
+ {issued ? <PdfField label={w.date}>{formatPdfDate(issued, dateLocale)}</PdfField> : null}
115
+ {until ? <PdfField label={w.until}>{formatPdfDate(until, dateLocale)}</PdfField> : null}
116
+ {reference ? <PdfField label="Reference">{reference}</PdfField> : null}
117
+ </PdfStack>
118
+ </PdfCol>
119
+ <PdfCol style={{ alignItems: "flex-end" }}>
120
+ <PdfLabel align="right">{amountLabel}</PdfLabel>
121
+ <PdfText bold size="xl" tone="accent" align="right">
122
+ {money(sums.due)}
123
+ </PdfText>
124
+ </PdfCol>
125
+ </PdfRow>
126
+
127
+ {/* The lines. */}
128
+ <PdfTable
129
+ style={{ marginTop: 28 }}
130
+ empty="No line items yet."
131
+ columns={[
132
+ { key: "description", label: "Description", flex: 3 },
133
+ { key: "quantity", label: "Qty", width: 48, align: "right", render: (r) => [formatQuantity(r.quantity ?? 1, locale), r.unit].filter(Boolean).join(" ") },
134
+ { key: "unitPrice", label: "Unit price", width: 84, align: "right", render: (r) => money(r.unitPrice) },
135
+ { key: "amount", label: "Amount", width: 88, align: "right", render: (r, i) => money(sums.lines[i]) },
136
+ ]}
137
+ rows={items.map((it, i) => ({ ...it, id: it.id ?? i, detail: [it.detail, it.discountPercent ? `${formatQuantity(it.discountPercent, locale)}% off` : null].filter(Boolean).join(" · ") || undefined }))}
138
+ />
139
+
140
+ <PdfTotals
141
+ rows={[
142
+ hasSums && { label: "Subtotal", value: money(sums.subtotal) },
143
+ sums.discount > 0 && { label: discount?.label ?? (discount?.percent ? `Discount (${formatQuantity(discount.percent, locale)}%)` : "Discount"), value: `-${money(sums.discount)}` },
144
+ sums.tax > 0 && { label: taxLabel ?? `Tax (${formatQuantity(taxRate, locale)}%)`, value: money(sums.tax) },
145
+ sums.paid > 0 && { label: "Total", value: money(sums.total) },
146
+ sums.paid > 0 && { label: "Paid", value: `-${money(sums.paid)}` },
147
+ { label: amountLabel, value: money(sums.due), strong: true },
148
+ ]}
149
+ />
150
+
151
+ {/* The foot: notes, terms, how to pay. */}
152
+ {notes || terms || payment ? (
153
+ <PdfStack gap={16} style={{ marginTop: 32 }} wrap={false}>
154
+ {notes ? <PdfCallout title="Notes">{notes}</PdfCallout> : null}
155
+ {terms || payment ? (
156
+ <PdfRow gap={24}>
157
+ {terms ? (
158
+ <PdfCol>
159
+ <PdfHeading level={3} style={{ marginBottom: 3 }}>
160
+ Terms
161
+ </PdfHeading>
162
+ <PdfText tone="muted">{terms}</PdfText>
163
+ </PdfCol>
164
+ ) : null}
165
+ {payment ? (
166
+ <PdfCol>
167
+ <PdfHeading level={3} style={{ marginBottom: 3 }}>
168
+ How to pay
169
+ </PdfHeading>
170
+ {Array.isArray(payment) ? <PdfLines lines={payment} first={false} /> : <PdfText tone="muted">{payment}</PdfText>}
171
+ </PdfCol>
172
+ ) : null}
173
+ </PdfRow>
174
+ ) : null}
175
+ </PdfStack>
176
+ ) : null}
177
+ </PdfDocument>
178
+ );
179
+ }
@@ -0,0 +1,193 @@
1
+ // The PDF's colours, from the workspace theme.
2
+ //
3
+ // A PDF cannot read a CSS variable: every colour in it is a concrete
4
+ // value written into the file. So the theme is read ONCE, at the moment
5
+ // the PDF is made, from the page's own variables (--color-primary…), and
6
+ // passed into the document as plain values. Change the theme and the next
7
+ // PDF follows; a PDF already made keeps the colours it was made with.
8
+ //
9
+ // Two schemes:
10
+ // paper (the default) — what gets printed, emailed, signed. White paper,
11
+ // near-black ink, grey rules, and the theme's PRIMARY as the one
12
+ // accent. A dark workspace still sends a light invoice. When the
13
+ // theme's primary is too pale to read on white (a mint, a lemon),
14
+ // the text uses a darker shade of it (accentInk, 4.5:1 or more)
15
+ // while bars and fills keep the colour itself.
16
+ // theme — the workspace's own background, text and borders, for a PDF
17
+ // meant to be read on screen in the brand's look.
18
+ //
19
+ // No colour value is written in this file: the paper constants are byte
20
+ // triples turned into strings at run time, and everything else is read
21
+ // from the page. Everything but resolvePdfTheme() is a plain function, so
22
+ // it runs in node and on the server (where the fallback theme is used).
23
+
24
+ /** The slots read from the page. */
25
+ export const PDF_SLOTS = ["background", "foreground", "muted", "muted-foreground", "border", "primary", "primary-foreground", "success", "warning", "destructive", "info"];
26
+
27
+ const clamp = (n, lo = 0, hi = 255) => Math.max(lo, Math.min(hi, n));
28
+ const byte = (n) => clamp(Math.round(n)).toString(16).padStart(2, "0");
29
+
30
+ /** [r, g, b] (0-255) → a "#rrggbb" string. */
31
+ export function toHex([r, g, b]) {
32
+ return "#" + byte(r) + byte(g) + byte(b);
33
+ }
34
+
35
+ /** "#rrggbb" → [r, g, b], or null. */
36
+ export function parseHex(value) {
37
+ const m = /^#?([0-9a-f]{6})$/i.exec(String(value ?? "").trim());
38
+ if (!m) return null;
39
+ const n = parseInt(m[1], 16);
40
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
41
+ }
42
+
43
+ /** t of colour a over (1 - t) of colour b. */
44
+ export function mix(a, b, t) {
45
+ const x = parseHex(a);
46
+ const y = parseHex(b);
47
+ if (!x || !y) return a ?? b;
48
+ const k = clamp(t, 0, 1);
49
+ return toHex([0, 1, 2].map((i) => x[i] * k + y[i] * (1 - k)));
50
+ }
51
+
52
+ /** WCAG relative luminance of a hex colour (0 black … 1 white). */
53
+ export function luminance(hex) {
54
+ const c = parseHex(hex);
55
+ if (!c) return 0;
56
+ const lin = c.map((v) => {
57
+ const s = v / 255;
58
+ return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
59
+ });
60
+ return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
61
+ }
62
+
63
+ /** WCAG contrast ratio of two hex colours (1 … 21). */
64
+ export function contrast(a, b) {
65
+ const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
66
+ return (hi + 0.05) / (lo + 0.05);
67
+ }
68
+
69
+ /** `colour`, darkened toward `ink` (or lightened, on a dark ground) until
70
+ * it reads on `ground` at `ratio` — the shade used for accent TEXT. */
71
+ export function readableOn(colour, ground, ink, ratio = 4.5) {
72
+ if (!parseHex(colour)) return ink;
73
+ if (contrast(colour, ground) >= ratio) return colour;
74
+ for (let t = 0.9; t >= 0; t -= 0.05) {
75
+ const c = mix(colour, ink, t);
76
+ if (contrast(c, ground) >= ratio) return c;
77
+ }
78
+ return ink;
79
+ }
80
+
81
+ /** Black or white, whichever reads better on `fill`. */
82
+ export function inkOn(fill) {
83
+ return luminance(fill) > 0.179 ? PAPER.ink : PAPER.paper;
84
+ }
85
+
86
+ // Print constants: paper, ink, a quiet grey for secondary text (4.5:1 on
87
+ // the paper), a hairline rule and a faint band.
88
+ const PAPER = {
89
+ paper: toHex([255, 255, 255]),
90
+ ink: toHex([23, 23, 27]),
91
+ muted: toHex([107, 107, 118]),
92
+ rule: toHex([226, 226, 231]),
93
+ band: toHex([246, 246, 248]),
94
+ };
95
+
96
+ // The fallback accent and tones: used on the server and wherever the page
97
+ // has no theme to read.
98
+ const FALLBACK = {
99
+ primary: toHex([36, 99, 235]),
100
+ success: toHex([21, 112, 58]),
101
+ warning: toHex([154, 74, 6]),
102
+ destructive: toHex([192, 28, 28]),
103
+ info: toHex([29, 78, 216]),
104
+ };
105
+
106
+ /** The theme a PDF is drawn with, from slot → hex (as read from the page).
107
+ *
108
+ * paper, ink, muted, rule, band the page, body text, secondary text,
109
+ * hairlines, a faint fill (table head)
110
+ * accent the theme's primary, for bars and fills
111
+ * accentInk the accent as text: 4.5:1 on the paper
112
+ * accentSoft a light tint of it, for a callout
113
+ * onAccent text on an accent fill
114
+ * success, warning, danger, info status tones, readable on the paper
115
+ * font, fontBold the PDF's faces (see registerPdfFont)
116
+ */
117
+ export function buildPdfTheme(slots = {}, { scheme = "paper", font } = {}) {
118
+ const s = Object.fromEntries(Object.entries(slots).filter(([, v]) => parseHex(v)));
119
+ const own = scheme === "theme" && s.background && s.foreground;
120
+ const paper = own ? s.background : PAPER.paper;
121
+ const ink = own ? s.foreground : PAPER.ink;
122
+ const muted = own ? readableOn(s["muted-foreground"] ?? mix(ink, paper, 0.62), paper, ink, 4.5) : PAPER.muted;
123
+ const rule = own ? (s.border ?? mix(ink, paper, 0.14)) : PAPER.rule;
124
+ const band = own ? (s.muted ?? mix(ink, paper, 0.05)) : PAPER.band;
125
+ const accent = s.primary ?? FALLBACK.primary;
126
+ const tone = (slot) => readableOn(s[slot] ?? FALLBACK[slot], paper, ink, 4.5);
127
+ return {
128
+ scheme: own ? "theme" : "paper",
129
+ paper,
130
+ ink,
131
+ muted,
132
+ rule,
133
+ band,
134
+ accent,
135
+ accentInk: readableOn(accent, paper, ink, 4.5),
136
+ accentSoft: mix(accent, paper, 0.08),
137
+ onAccent: own && s["primary-foreground"] && contrast(s["primary-foreground"], accent) >= 4.5 ? s["primary-foreground"] : inkOn(accent),
138
+ success: tone("success"),
139
+ warning: tone("warning"),
140
+ danger: tone("destructive"),
141
+ info: tone("info"),
142
+ font: font?.family ?? "Helvetica",
143
+ fontBold: font?.bold ?? font?.family ?? "Helvetica-Bold",
144
+ };
145
+ }
146
+
147
+ /** The theme with nothing read from a page: paper, ink and a blue accent. */
148
+ export const DEFAULT_PDF_THEME = buildPdfTheme({});
149
+
150
+ // ---- the browser half -------------------------------------------------------
151
+
152
+ /** Read the workspace theme from the CSS variables in effect at `root`
153
+ * (default: <body>, so a data-theme or a theme scoped to an ancestor
154
+ * counts) and build the PDF theme. A hidden probe takes
155
+ * `color: var(--color-<slot>)`; the browser resolves var(), color-mix()
156
+ * and oklch() into its computed colour, and a 1×1 canvas turns that into
157
+ * bytes whatever syntax it came back in. On the server it returns the
158
+ * fallback theme. */
159
+ export function resolvePdfTheme(root, options) {
160
+ if (typeof document === "undefined") return buildPdfTheme({}, options);
161
+ const host = root ?? document.body;
162
+ if (!host) return buildPdfTheme({}, options);
163
+ const probe = document.createElement("span");
164
+ probe.setAttribute("aria-hidden", "true");
165
+ probe.style.position = "absolute";
166
+ probe.style.visibility = "hidden";
167
+ probe.style.pointerEvents = "none";
168
+ host.appendChild(probe);
169
+ const canvas = document.createElement("canvas");
170
+ canvas.width = 1;
171
+ canvas.height = 1;
172
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
173
+ const slots = {};
174
+ try {
175
+ for (const slot of PDF_SLOTS) {
176
+ probe.style.color = "";
177
+ probe.style.color = `var(--color-${slot})`;
178
+ const computed = getComputedStyle(probe).color;
179
+ if (!computed || !ctx) continue;
180
+ ctx.clearRect(0, 0, 1, 1);
181
+ ctx.fillStyle = "transparent";
182
+ ctx.fillStyle = computed;
183
+ ctx.fillRect(0, 0, 1, 1);
184
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
185
+ if (a === 0) continue;
186
+ // A translucent token (a tint) is laid on the paper, as it would print.
187
+ slots[slot] = a >= 255 ? toHex([r, g, b]) : mix(toHex([r, g, b]), PAPER.paper, a / 255);
188
+ }
189
+ } finally {
190
+ probe.remove();
191
+ }
192
+ return buildPdfTheme(slots, options);
193
+ }
@@ -0,0 +1,191 @@
1
+ # PdfViewer
2
+
3
+ A PDF on screen, in the workspace theme. The pages scroll in one column;
4
+ a rail of thumbnails sits on the left and a page box in the toolbar
5
+ jumps anywhere. Zoom by steps, fit the width, fit the page, or hold
6
+ Ctrl/⌘ and scroll (a trackpad pinch works too) — the line under the
7
+ pointer stays put. ⌘F finds words in the text: every match is marked on
8
+ the page, Enter walks them.
9
+
10
+ People can highlight. Select a sentence and a small bar offers
11
+ **Highlight**, **Add note** and **Copy**. A highlight shows as a marker
12
+ stroke in a theme colour; its note sits in the Highlights list beside
13
+ the pages, where it is edited, recoloured or deleted (with Undo). Every
14
+ change shows at once and saves through your callback; when a save fails,
15
+ the change goes back and a toast says why.
16
+
17
+ A narrow viewer (under 900px wide — a phone, a side column) turns the
18
+ page rail and the Highlights list into sheets. Long files stay fast:
19
+ only the pages near the window are drawn. Password-protected files ask
20
+ for their password. A file that will not open says why and offers Try
21
+ again.
22
+
23
+ It is [React-PDF](https://github.com/wojtekmaj/react-pdf) (MIT) over
24
+ Mozilla's [PDF.js](https://github.com/mozilla/pdf.js) (Apache-2.0)
25
+ underneath: they parse and draw the pages and the selectable text. The
26
+ toolbar, rails, search, highlights and states are ours, in the kit. The
27
+ blocks built on this one (proposal-accept, a contract review screen…)
28
+ import it, never `react-pdf` or `pdfjs-dist`.
29
+
30
+ ```jsx
31
+ import { PdfViewer } from "../components/blocks/pdf-viewer"; // a Makersclaw app ("./blocks/pdf-viewer" from components/)
32
+ import { PdfViewer } from "@/components/makersclaw/blocks/pdf-viewer"; // a shadcn project
33
+ ```
34
+
35
+ `PdfViewer` is a client component: render it from a `"use client"`
36
+ component. The helpers (`findMatches`, `toPageRects`, `sortHighlights`…)
37
+ are plain functions and work on the server.
38
+
39
+ ## The file, and the worker
40
+
41
+ `file` is a URL (same origin, or a server that allows CORS), a `Blob` /
42
+ `File` (an upload, or a PDF made with the `pdf-document` block), or the
43
+ bytes (`ArrayBuffer` / `Uint8Array`, copied — your buffer stays usable).
44
+
45
+ PDF.js parses in a Web Worker. Nothing to set up: the block points
46
+ PDF.js at `new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url)`,
47
+ which the app's bundler resolves at build time and emits as a hashed
48
+ file under `/_next/static/media/`, with the base path applied. So the
49
+ worker ships with the app, always matches the PDF.js version that calls
50
+ it, and comes from the app's own origin — no file in `public/`, no CDN.
51
+
52
+ ## The data
53
+
54
+ A highlight is one row:
55
+
56
+ ```js
57
+ {
58
+ id: "hl_81", // yours
59
+ page: 3, // 1-based
60
+ rects: [{ x, y, w, h }], // fractions of the page (0…1), top-left origin — hold at any zoom
61
+ text: "Fees rise by 4% at each annual renewal", // the words highlighted
62
+ note: "Ask for a 3% cap.", // optional
63
+ tone: "warning", // warning (default) · info · success · destructive · primary
64
+ author: "Priya Raman", // optional, shown under the note
65
+ createdAt: "2026-09-21", // optional
66
+ }
67
+ ```
68
+
69
+ `rects` may be left out: a highlight given only by its `text` (and
70
+ optionally its `page`) is placed where those words first appear, once
71
+ the pages' text has been read. That is how an agent or a server flags a
72
+ clause without knowing any geometry. A quote that is not in the text is
73
+ listed under "Not found in the text". Store the `rects` the viewer sends
74
+ you in `onHighlight` — they are exact; placing by words is close (the
75
+ width inside a line is shared out by characters) and assumes pages that
76
+ are not rotated.
77
+
78
+ Store a highlight as a row in its own table (`document_id`, `page`,
79
+ `rects` jsonb, `text`, `note`, `tone`, `author`, `created_at`).
80
+
81
+ ## Props
82
+
83
+ - `file` — the PDF (see above). `null` shows the empty state.
84
+ - `title` — names the viewer for screen readers and shows in the
85
+ toolbar on a wide viewer. Default `"PDF document"` for readers, nothing
86
+ shown.
87
+ - `fileName` — what Download saves as. Default: the title + `.pdf`.
88
+ - `highlights` — the rows above. Default `[]`.
89
+ - `onHighlight(h)` — save a new highlight: `h` is `{ page, rects, text,
90
+ note, tone }`. Return `{ ok: true, id }` (your id replaces the viewer's
91
+ temporary one) or `{ ok: false, error }` (a throw counts as failed): it
92
+ is removed and a toast shows `error`. **Without `onHighlight` the viewer
93
+ is read-only**: no selection bar, and the Highlights list (shown only
94
+ when there are highlights) cannot edit.
95
+ - `onHighlightChange(id, patch)` — `patch` is `{ note }` or `{ tone }`.
96
+ Same return; a failure puts the old value back.
97
+ - `onHighlightDelete(id)` — called 5 seconds after a delete, once the
98
+ Undo in its toast has passed (or at once if the viewer unmounts). Same
99
+ return; a failure puts the highlight back.
100
+ - `initialPage` — the page to open on. Default `1`.
101
+ - `onPageChange(page, pageCount)` — whenever the page at the top of the
102
+ window changes.
103
+ - `defaultZoom` — `"fit"` (width, the default) · `"page"` · a number
104
+ (`1` is 100%).
105
+ - `thumbnails` — the page rail. Default `true`.
106
+ - `search` — find in the text. Default `true`.
107
+ - `download` — the Download button. Default `true`.
108
+ - `notes` — open the Highlights list on a wide viewer at first. Default:
109
+ open when there are highlights.
110
+ - `height` — the viewer's height, any CSS length. Default
111
+ `"min(80vh, 860px)"`; it never goes under 384px.
112
+ - `loading` — `true` shows the skeleton (while you fetch or make the
113
+ file) instead of the empty state.
114
+ - `emptyTitle` · `emptyBody` — the words when `file` is empty. Default
115
+ "No document yet" / "When a PDF is attached, it shows here."
116
+ - `viewerRef` — a ref from `usePdfViewer()`; `ref.current` then has
117
+ `goToPage(n)`, `goToHighlight(id)`, `search(text)`, `setZoom(z)`, and
118
+ `page` / `pageCount`.
119
+ - `className` — added to the frame (a margin, a width). Its border,
120
+ radius and height are the block's; set height through `height`.
121
+
122
+ Keys, while focus is in the viewer: ⌘/Ctrl + F find, Enter / Shift+Enter
123
+ next / previous match, Esc closes find; ⌘/Ctrl + `+` / `-` zoom, `0`
124
+ fits the width; Page Up / Page Down and the arrows scroll; Tab reaches
125
+ every control and each page thumbnail. Notes: ⌘/Ctrl + Enter saves, Esc
126
+ cancels.
127
+
128
+ ## Example
129
+
130
+ ```jsx
131
+ "use client";
132
+ import { useState } from "react";
133
+ import { PdfViewer } from "../components/blocks/pdf-viewer";
134
+ import { insertRow, updateRow, deleteRow } from "../lib/actions";
135
+
136
+ const source = "public.highlights";
137
+
138
+ export function ContractReview({ doc, rows }) {
139
+ const [highlights, setHighlights] = useState(rows);
140
+ return (
141
+ <PdfViewer
142
+ file={doc.url}
143
+ title={doc.title}
144
+ highlights={highlights}
145
+ onHighlight={async (h) => {
146
+ const r = await insertRow({ source, values: { document_id: doc.id, ...h } });
147
+ if (r.ok) setHighlights((list) => [...list, { ...h, id: r.id }]);
148
+ return r;
149
+ }}
150
+ onHighlightChange={async (id, patch) => {
151
+ const r = await updateRow({ source, id, patch });
152
+ if (r.ok) setHighlights((list) => list.map((x) => (x.id === id ? { ...x, ...patch } : x)));
153
+ return r;
154
+ }}
155
+ onHighlightDelete={async (id) => {
156
+ const r = await deleteRow({ source, id });
157
+ if (r.ok) setHighlights((list) => list.filter((x) => x.id !== id));
158
+ return r;
159
+ }}
160
+ />
161
+ );
162
+ }
163
+ ```
164
+
165
+ Preview a PDF you make (the `pdf-document` block):
166
+
167
+ ```jsx
168
+ const { blob } = usePdf(() => <QuoteDocument {...quote} />, [quote]);
169
+ <PdfViewer file={blob} loading={!blob} title={`Quote ${quote.number}`} thumbnails={false} />
170
+ ```
171
+
172
+ ## What it will not do
173
+
174
+ - Edit the PDF: fill its forms, sign it, rotate or reorder pages, or
175
+ write highlights into the file. Highlights are rows you store; the PDF
176
+ is untouched. (For signing, the `signature-pad` block.)
177
+ - Search across a line break in one phrase: PDF.js splits text into
178
+ lines, and a match must sit inside one (like most quick finds).
179
+ - Highlight in a scanned PDF (an image with no text layer): there is no
180
+ text to select or find.
181
+ - Keep the old pages up while a NEW file loads: a changed `file` shows
182
+ the skeleton until it has opened.
183
+ - Open a URL on another origin that does not allow CORS: fetch it on
184
+ your server and pass the bytes.
185
+ - Print; the browser's own PDF reader does that from Download.
186
+
187
+ ## Credits
188
+
189
+ Built on [React-PDF](https://github.com/wojtekmaj/react-pdf) by Wojciech
190
+ Maj (MIT) and [PDF.js](https://github.com/mozilla/pdf.js) by Mozilla
191
+ (Apache-2.0), used unmodified. See THIRD-PARTY-NOTICES.md.
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "pdf-viewer",
3
+ "title": "PdfViewer",
4
+ "description": "A PDF on screen, in the workspace theme (react-pdf + pdf.js): pages in one smooth scrolling column (only the pages near the window are drawn, so long files stay fast), a thumbnail rail, a page box, zoom by steps, fit width, fit page and Ctrl/⌘ + wheel or pinch, find in the text with every match marked, and highlights with notes: select text, choose Highlight or Add note, and it saves through onHighlight; notes are edited in a side list, colours are theme tokens, delete has Undo. Opens a URL, a Blob or bytes; password-protected files ask for the password; a narrow viewer turns its rails into sheets. The pdf.js worker ships with the app (no public/ file, no CDN).",
5
+ "useWhen": "A screen shows an existing PDF: a contract or proposal to review, a signed agreement, an uploaded invoice or statement, a report, a generated quote before it is sent; or people mark up a PDF and leave notes on passages. Pair it with pdf-document to preview a PDF you make. Not for making PDFs (pdf-document), for rich text people edit (doc-editor), or for marking up a screenshot (annotate).",
6
+ "tags": ["pdf", "viewer", "document", "reader", "preview", "highlight", "annotate", "notes", "search", "thumbnails", "zoom", "contract", "proposal", "react-pdf", "pdfjs"],
7
+ "exports": ["PdfViewer", "usePdfViewer", "HIGHLIGHT_TONES", "findMatches", "toPageRects", "mergeRects", "sortHighlights", "highlightAt", "fitScale", "ZOOM_STEPS"],
8
+ "files": ["index.js", "pdf-viewer.jsx", "notes.jsx", "helpers.js", "pdfjs.js", "ssr-shim.js", "ssr-shim-end.js"],
9
+ "requires": [],
10
+ "dependencies": {
11
+ "react-pdf": "11.0.0",
12
+ "pdfjs-dist": "6.3.289"
13
+ }
14
+ }