makersclaw 0.2.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 (473) 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/install.mjs +18 -0
  430. package/src/shadcn.mjs +8 -0
  431. package/templates/next/files/README.md +145 -11
  432. package/templates/next/files/app/globals.css +55 -4
  433. package/templates/next/files/check/run.mjs +3 -3
  434. package/templates/next/files/components/ui/avatar.jsx +141 -0
  435. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  436. package/templates/next/files/components/ui/button-group.jsx +70 -0
  437. package/templates/next/files/components/ui/button.jsx +132 -12
  438. package/templates/next/files/components/ui/calendar.jsx +609 -0
  439. package/templates/next/files/components/ui/carousel.jsx +281 -0
  440. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  441. package/templates/next/files/components/ui/combobox.jsx +608 -0
  442. package/templates/next/files/components/ui/command.jsx +577 -0
  443. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  444. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  445. package/templates/next/files/components/ui/distribution.jsx +117 -0
  446. package/templates/next/files/components/ui/feedback.jsx +143 -0
  447. package/templates/next/files/components/ui/field.jsx +115 -3
  448. package/templates/next/files/components/ui/file-input.jsx +234 -0
  449. package/templates/next/files/components/ui/icon.jsx +130 -8
  450. package/templates/next/files/components/ui/image.jsx +143 -0
  451. package/templates/next/files/components/ui/index.js +47 -2
  452. package/templates/next/files/components/ui/input-group.jsx +213 -0
  453. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  454. package/templates/next/files/components/ui/item.jsx +206 -0
  455. package/templates/next/files/components/ui/menu.jsx +454 -82
  456. package/templates/next/files/components/ui/notice.jsx +126 -14
  457. package/templates/next/files/components/ui/pagination.jsx +156 -0
  458. package/templates/next/files/components/ui/popover.jsx +284 -0
  459. package/templates/next/files/components/ui/radio.jsx +193 -0
  460. package/templates/next/files/components/ui/rating.jsx +131 -0
  461. package/templates/next/files/components/ui/resizable.jsx +338 -0
  462. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  463. package/templates/next/files/components/ui/separator.jsx +119 -0
  464. package/templates/next/files/components/ui/sheet.jsx +96 -11
  465. package/templates/next/files/components/ui/slider.jsx +174 -0
  466. package/templates/next/files/components/ui/stat.jsx +574 -0
  467. package/templates/next/files/components/ui/steps.jsx +338 -0
  468. package/templates/next/files/components/ui/swatch.jsx +33 -0
  469. package/templates/next/files/components/ui/table.jsx +130 -0
  470. package/templates/next/files/components/ui/toast.jsx +440 -0
  471. package/templates/next/files/components/ui/toggle.jsx +195 -0
  472. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  473. package/templates/next/template.json +264 -8
@@ -0,0 +1,195 @@
1
+ "use client";
2
+
3
+ // CalendarView three ways — the gallery's and the smoke test's surface.
4
+ // Not installed into apps: `makersclaw add calendar-view` lays the block's
5
+ // files only.
6
+ // Team a launch team's September: meetings, deadlines, spans, a
7
+ // tray of undated work; saves in memory (a switch makes them
8
+ // fail, to show the rollback); an item opens a sheet.
9
+ // Booking the available-time layer: working hours, busy meetings,
10
+ // open slots from getSlots (freeSlots) to pick one.
11
+ // Empty no tasks yet: click any day to add one.
12
+ import { useCallback, useState } from "react";
13
+ import { Button, Notice, Sheet, Switch, TabPanel, Tabs } from "../components/ui";
14
+ import { CalendarView, eventTimeLabel, eventOf, freeSlots, minutesLabel } from "../components/blocks/calendar-view";
15
+ import { applyChange, formatDay } from "../components/blocks/task-model";
16
+
17
+ const TODAY = "2026-09-23";
18
+ const NOW = "2026-09-23T10:40";
19
+
20
+ const STATUSES = [
21
+ { id: "todo", label: "To do", tone: "neutral" },
22
+ { id: "doing", label: "In progress", tone: "info" },
23
+ { id: "review", label: "In review", tone: "warning" },
24
+ { id: "done", label: "Done", tone: "success", done: true },
25
+ ];
26
+
27
+ const PEOPLE = [
28
+ { id: "maya", name: "Maya Chen" },
29
+ { id: "leo", name: "Leo Park" },
30
+ { id: "priya", name: "Priya Nair" },
31
+ { id: "sam", name: "Sam Okafor" },
32
+ ];
33
+
34
+ const PROJECTS = [
35
+ { id: "site", name: "Website relaunch", hue: 1 },
36
+ { id: "q4", name: "Q4 campaign", hue: 3 },
37
+ { id: "team", name: "Team", hue: 5 },
38
+ ];
39
+
40
+ const TEAM_TASKS = [
41
+ { id: "c1", title: "Weekly planning", status: "done", assignees: ["maya", "leo", "priya", "sam"], start: "2026-09-21T09:00", due: "2026-09-21T09:45", project: "team" },
42
+ { id: "c2", title: "Q4 campaign brief", status: "doing", assignees: ["sam"], start: "2026-09-22", due: "2026-09-24", project: "q4", priority: "high" },
43
+ { id: "c3", title: "Finalise pricing page copy", status: "doing", assignees: ["maya"], due: "2026-09-23", project: "site", priority: "high" },
44
+ { id: "c4", title: "Design review: pricing page", status: "todo", assignees: ["maya", "priya"], start: "2026-09-23T11:00", due: "2026-09-23T12:00", project: "site" },
45
+ { id: "c5", title: "Call with Northwind", status: "todo", assignees: ["sam"], start: "2026-09-23T11:30", due: "2026-09-23T12:15", project: "q4" },
46
+ { id: "c6", title: "Write the launch email", status: "todo", assignees: ["sam"], start: "2026-09-23T14:00", due: "2026-09-23T16:00", project: "q4", estimate: 2 },
47
+ { id: "c7", title: "Reply to the press list", status: "todo", assignees: ["leo"], due: "2026-09-23", project: "q4" },
48
+ { id: "c8", title: "Order launch swag", status: "todo", assignees: ["priya"], due: "2026-09-23", project: "team" },
49
+ { id: "c9", title: "Interview: product designer", status: "todo", assignees: ["maya"], start: "2026-09-24T10:00", due: "2026-09-24T11:00", project: "team" },
50
+ { id: "c10", title: "Set up redirects from the old site", status: "review", assignees: ["leo"], due: "2026-09-24T17:00", project: "site", priority: "medium" },
51
+ { id: "c11", title: "Product photo shoot", status: "todo", assignees: ["leo", "priya"], start: "2026-09-25T09:00", due: "2026-09-25T13:00", project: "q4", priority: "urgent" },
52
+ { id: "c12", title: "Launch week", status: "todo", assignees: ["maya", "leo", "priya", "sam"], start: "2026-09-28", due: "2026-10-02", project: "site" },
53
+ { id: "c13", title: "Pay contractor invoices", status: "todo", assignees: ["sam"], due: "2026-09-30", project: "team" },
54
+ { id: "c14", title: "Board update", status: "todo", assignees: ["maya"], due: "2026-10-06T15:00", project: "team" },
55
+ { id: "c15", title: "Team offsite", status: "todo", assignees: ["maya", "leo", "priya", "sam"], start: "2026-10-08", due: "2026-10-09", project: "team" },
56
+ { id: "c16", title: "Choose the analytics events", status: "done", assignees: ["sam"], due: "2026-09-18", project: "site" },
57
+ { id: "c17", title: "Brief the paid social agency", status: "done", assignees: ["maya"], start: "2026-09-17T15:00", due: "2026-09-17T16:00", project: "q4" },
58
+ { id: "c18", title: "Accessibility pass on the new nav", status: "todo", assignees: ["priya"], due: "2026-09-29", project: "site" },
59
+ { id: "c19", title: "Draft the customer story", status: "todo", assignees: [], project: "q4", estimate: 3 },
60
+ { id: "c20", title: "Refresh the pitch deck", status: "todo", assignees: ["maya"], project: "team", estimate: 2 },
61
+ { id: "c21", title: "Shortlist offsite venues", status: "todo", assignees: ["priya"], project: "team" },
62
+ ];
63
+
64
+ const MEETINGS = [
65
+ { id: "m1", title: "Team standup", status: "todo", assignees: ["maya"], start: "2026-09-23T09:00", due: "2026-09-23T09:30", project: "team" },
66
+ { id: "m2", title: "Pipeline review", status: "todo", assignees: ["maya"], start: "2026-09-23T13:00", due: "2026-09-23T14:00", project: "q4" },
67
+ { id: "m3", title: "Customer call: Lumen Labs", status: "todo", assignees: ["maya"], start: "2026-09-24T11:00", due: "2026-09-24T12:00", project: "q4" },
68
+ { id: "m4", title: "Focus time", status: "todo", assignees: ["maya"], start: "2026-09-25T09:00", due: "2026-09-25T11:30", project: "site" },
69
+ ];
70
+
71
+ const HOURS = { days: [1, 2, 3, 4, 5], from: "09:00", to: "17:00" };
72
+
73
+ function useTasks(start, failRef) {
74
+ const [tasks, setTasks] = useState(start);
75
+ const onChange = async (change) => {
76
+ await new Promise((r) => setTimeout(r, 350));
77
+ if (failRef?.current) return { ok: false, error: "the server did not answer" };
78
+ setTasks((all) => applyChange(all, change));
79
+ return { ok: true };
80
+ };
81
+ return [tasks, onChange];
82
+ }
83
+
84
+ export default function CalendarDemo() {
85
+ const [tab, setTab] = useState("team");
86
+ const [fail, setFail] = useState(false);
87
+ const failRef = { current: fail };
88
+ const [tasks, onChange] = useTasks(TEAM_TASKS, failRef);
89
+ const [none, onChangeNone] = useTasks([]);
90
+ const [open, setOpen] = useState(null);
91
+ const [picked, setPicked] = useState(null);
92
+ const [booked, setBooked] = useState(null);
93
+ const meetings = booked
94
+ ? [...MEETINGS, { id: "b1", title: "Intro call: Ada from Brightwave", status: "todo", assignees: ["maya"], start: booked.start, due: booked.end, project: "q4" }]
95
+ : MEETINGS;
96
+ const getSlots = useCallback(
97
+ ({ from, to }) =>
98
+ freeSlots({ from, to, availability: HOURS, busy: booked ? [...MEETINGS, booked] : MEETINGS, minutes: 30, step: 60, notice: 60, now: NOW }),
99
+ [booked],
100
+ );
101
+ const openEvent = open ? eventOf(open) : null;
102
+ return (
103
+ <div className="grid gap-4">
104
+ <Tabs
105
+ aria-label="Calendar examples"
106
+ value={tab}
107
+ onChange={setTab}
108
+ tabs={[
109
+ { key: "team", label: "Team" },
110
+ { key: "booking", label: "Booking" },
111
+ { key: "empty", label: "Empty" },
112
+ ]}
113
+ />
114
+ <TabPanel tab="team" value={tab}>
115
+ <div className="grid gap-4">
116
+ <Switch id="calendar-fail" label="Make saves fail" checked={fail} onChange={(e) => setFail(e.target.checked)} />
117
+ <CalendarView
118
+ label="Launch calendar"
119
+ tasks={tasks}
120
+ statuses={STATUSES}
121
+ people={PEOPLE}
122
+ projects={PROJECTS}
123
+ today={TODAY}
124
+ now={NOW}
125
+ onChange={onChange}
126
+ onOpen={setOpen}
127
+ defaultMode="week"
128
+ />
129
+ <Sheet
130
+ open={Boolean(open)}
131
+ onClose={() => setOpen(null)}
132
+ title={open?.title}
133
+ description={openEvent ? `${formatDay(openEvent.start, TODAY)} · ${eventTimeLabel(openEvent)}` : "No date yet"}
134
+ >
135
+ <p className="text-sm text-muted-foreground">The task's own page goes here: its description, comments and history.</p>
136
+ </Sheet>
137
+ </div>
138
+ </TabPanel>
139
+ <TabPanel tab="booking" value={tab}>
140
+ <div className="grid gap-4">
141
+ <CalendarView
142
+ label="Pick a time"
143
+ tasks={meetings}
144
+ projects={PROJECTS}
145
+ today={TODAY}
146
+ now={NOW}
147
+ modes={["week", "day"]}
148
+ defaultMode="week"
149
+ toolbar={false}
150
+ tray={false}
151
+ availability={HOURS}
152
+ getSlots={getSlots}
153
+ slotLabel="Book"
154
+ selectedSlot={picked?.id}
155
+ onSlotClick={(s) => setPicked(s)}
156
+ height="30rem"
157
+ />
158
+ {booked ? (
159
+ <Notice tone="success" onDismiss={() => setBooked(null)}>
160
+ Booked for {formatDay(booked.day, TODAY)} at {minutesLabel(booked.from)}. A confirmation is on its way.
161
+ </Notice>
162
+ ) : null}
163
+ <div className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border bg-card p-3">
164
+ <p className="text-sm text-muted-foreground">
165
+ {picked ? (
166
+ <>
167
+ <span className="font-medium text-foreground">
168
+ {formatDay(picked.day, TODAY)}, {minutesLabel(picked.from)} – {minutesLabel(picked.to)}
169
+ </span>{" "}
170
+ · 30 minutes
171
+ </>
172
+ ) : (
173
+ "Pick an open time on the calendar."
174
+ )}
175
+ </p>
176
+ <Button
177
+ variant="primary"
178
+ size="sm"
179
+ disabled={!picked}
180
+ onClick={() => {
181
+ setBooked(picked);
182
+ setPicked(null);
183
+ }}
184
+ >
185
+ Book this time
186
+ </Button>
187
+ </div>
188
+ </div>
189
+ </TabPanel>
190
+ <TabPanel tab="empty" value={tab}>
191
+ <CalendarView label="My calendar" tasks={none} statuses={STATUSES} people={PEOPLE} today={TODAY} now={NOW} onChange={onChangeNone} />
192
+ </TabPanel>
193
+ </div>
194
+ );
195
+ }
@@ -0,0 +1,49 @@
1
+ "use client";
2
+
3
+ import { useRef, useState } from "react";
4
+ import { cx } from "../../ui";
5
+
6
+ // The quick-add field that opens where the founder clicked: an empty
7
+ // month day, a stretch of the time grid, the top of an agenda day. Type a
8
+ // title, Enter saves (the item appears at once), Escape or leaving it
9
+ // empty puts it away; leaving it with words in it saves them.
10
+ export function DraftInput({ label, placeholder = "New task", onSubmit, onCancel, className }) {
11
+ const [value, setValue] = useState("");
12
+ const settled = useRef(false);
13
+ function submit() {
14
+ if (settled.current) return;
15
+ const title = value.trim();
16
+ settled.current = true;
17
+ if (!title) onCancel?.();
18
+ else onSubmit?.(title);
19
+ }
20
+ return (
21
+ // The title is typed straight into the new item's own box, the way a
22
+ // calendar names a new event; the box around it is the border.
23
+ // raw: a kit Input is a 44px bordered form field, too big for a slot.
24
+ <input
25
+ type="text"
26
+ autoFocus
27
+ aria-label={label}
28
+ value={value}
29
+ placeholder={placeholder}
30
+ enterKeyHint="done"
31
+ onChange={(e) => setValue(e.target.value)}
32
+ onPointerDown={(e) => e.stopPropagation()}
33
+ onClick={(e) => e.stopPropagation()}
34
+ onKeyDown={(e) => {
35
+ e.stopPropagation();
36
+ if (e.key === "Enter" && !e.nativeEvent.isComposing) {
37
+ e.preventDefault();
38
+ submit();
39
+ } else if (e.key === "Escape") {
40
+ e.preventDefault();
41
+ settled.current = true;
42
+ onCancel?.();
43
+ }
44
+ }}
45
+ onBlur={submit}
46
+ className={cx("w-full min-w-0 bg-transparent text-xs font-medium text-foreground outline-none placeholder:font-normal placeholder:text-muted-foreground", className)}
47
+ />
48
+ );
49
+ }
@@ -0,0 +1,39 @@
1
+ // The calendar-view block — `makersclaw add calendar-view` (it brings task-model).
2
+ // Tasks on a month, week, day or agenda: drag to move, drag an end to
3
+ // resize, an unscheduled tray, a line at now, click an empty slot to add.
4
+ // Fixed: compose it through its props (README.md beside this file). The
5
+ // helpers in calendar-model.js are pure (the server included): where a
6
+ // task sits, overlap and lane layout, the patches a gesture saves, and
7
+ // the available-time layer (availabilityOn, freeSlots) booking-page uses.
8
+ export { CalendarView } from "./calendar";
9
+ export {
10
+ CALENDAR_MODES,
11
+ MODE_LABELS,
12
+ DAY_MINUTES,
13
+ UNSCHEDULE,
14
+ snapMinutes,
15
+ durationOf,
16
+ eventOf,
17
+ eventsOf,
18
+ unscheduledOf,
19
+ layoutTimed,
20
+ layoutLanes,
21
+ moveEventPatch,
22
+ resizeEventPatch,
23
+ placeEventPatch,
24
+ timedPatch,
25
+ dayPatch,
26
+ allDayPatch,
27
+ extendPatch,
28
+ rangeFor,
29
+ stepAnchor,
30
+ rangeLabel,
31
+ titleFor,
32
+ hourLabel,
33
+ minutesLabel,
34
+ eventTimeLabel,
35
+ availabilityOn,
36
+ closedOn,
37
+ freeSlots,
38
+ normalizeSlots,
39
+ } from "./calendar-model";
@@ -0,0 +1,346 @@
1
+ "use client";
2
+
3
+ import { useMemo, useRef, useState } from "react";
4
+ import { IconButton, Popover, cx } from "../../ui";
5
+ import { TaskChip, formatDate, isDone, isWeekend, useDraggableTask, useDropTarget } from "../task-model";
6
+ import { layoutLanes, minutesLabel } from "./calendar-model";
7
+ import { DraftInput } from "./draft";
8
+ import { paintOf, withKeys } from "./paint";
9
+ import { AgendaDay } from "./agenda";
10
+
11
+ // The month: weeks of seven days. All-day tasks and spans are tinted bars
12
+ // that run across the days they cover (stacked in lanes, never over each
13
+ // other); a timed task is a dot, its time and its title. Three lanes show;
14
+ // past that a day says "2 more" and opens its full list. Drag a bar to
15
+ // another day, drag its end to make it longer, click an empty day to add
16
+ // a task there. On a phone the days show dots, and tapping one lists it
17
+ // under the grid.
18
+
19
+ const LANES = 3;
20
+ const LANE_PX = 24;
21
+
22
+ const dayName = (day, locale) => formatDate(day, { weekday: "long", month: "long", day: "numeric" }, { locale });
23
+
24
+ export function MonthView({ weeks, month, events, api, narrow, selected, onSelect }) {
25
+ const locale = api.locale;
26
+ const heads = weeks[0] ?? [];
27
+ if (narrow) return <NarrowMonth weeks={weeks} month={month} events={events} api={api} selected={selected} onSelect={onSelect} />;
28
+ return (
29
+ <div className="overflow-hidden rounded-lg border border-border bg-card">
30
+ <div className="grid grid-cols-7 border-b border-border">
31
+ {heads.map((d) => (
32
+ <div key={d} className="px-2 py-2 text-xs font-medium text-muted-foreground">
33
+ {formatDate(d, { weekday: "short" }, { locale })}
34
+ </div>
35
+ ))}
36
+ </div>
37
+ {weeks.map((week) => (
38
+ <WeekRow key={week[0]} week={week} month={month} events={events} api={api} />
39
+ ))}
40
+ </div>
41
+ );
42
+ }
43
+
44
+ function WeekRow({ week, month, events, api }) {
45
+ const rowRef = useRef(null);
46
+ const layout = useMemo(() => layoutLanes(events, week), [events, week]);
47
+ const overflow = layout.lanes > LANES;
48
+ const shownLanes = overflow ? LANES - 1 : layout.lanes;
49
+ const visible = layout.items.filter((it) => it.lane < shownLanes);
50
+ // What each day cannot show: its items in the lanes that did not fit.
51
+ const hidden = week.map((_, i) => layout.items.filter((it) => it.lane >= shownLanes && it.col <= i && i < it.col + it.span));
52
+ const cellWidth = () => (rowRef.current?.getBoundingClientRect().width ?? 700) / 7;
53
+ const reserve = Math.max(shownLanes + (overflow ? 1 : 0), 1) * LANE_PX;
54
+ return (
55
+ <div ref={rowRef} className="relative grid grid-cols-7 border-b border-border last:border-b-0">
56
+ {week.map((day, i) => (
57
+ <DayCell
58
+ key={day}
59
+ day={day}
60
+ inMonth={day.slice(0, 7) === month}
61
+ api={api}
62
+ reserve={reserve}
63
+ hidden={hidden[i]}
64
+ dayItems={layout.items.filter((it) => it.col <= i && i < it.col + it.span)}
65
+ overflow={overflow}
66
+ />
67
+ ))}
68
+ <div className="pointer-events-none absolute inset-x-0 top-10 grid grid-cols-7 gap-y-0.5" style={{ gridAutoRows: `${LANE_PX - 2}px` }}>
69
+ {visible.map((it) => (
70
+ <MonthItem key={`${it.event.id}:${week[0]}`} item={it} week={week} api={api} cellWidth={cellWidth} />
71
+ ))}
72
+ </div>
73
+ </div>
74
+ );
75
+ }
76
+
77
+ function DayCell({ day, inMonth, api, reserve, hidden, dayItems, overflow }) {
78
+ const { ctx, editable, locale } = api;
79
+ const today = day === ctx.today;
80
+ const label = dayName(day, locale);
81
+ const drop = useDropTarget(`cell:${day}`, { kind: "cell", day, label });
82
+ const drafting = api.draft && api.draft.allDay && api.draft.day === day;
83
+ const firstOfMonth = day.endsWith("-01");
84
+ const onBackground = (e) => {
85
+ // Only the cell's own empty space: not its buttons, not the "more"
86
+ // list (a popover inside the cell, whose clicks bubble here).
87
+ if (!editable || e.target.dataset?.calBg === undefined) return;
88
+ api.startDraft({ day, allDay: true });
89
+ };
90
+ return (
91
+ <div
92
+ ref={drop.setNodeRef}
93
+ data-cal-bg=""
94
+ onClick={onBackground}
95
+ className={cx(
96
+ "group/cell relative flex min-h-32 min-w-0 flex-col border-e border-border p-1 transition-colors duration-150 last:border-e-0",
97
+ !inMonth && "bg-muted/40",
98
+ inMonth && isWeekend(day, ctx.weekend) && "bg-muted/20",
99
+ editable && "cursor-default",
100
+ drop.isOver && "bg-accent",
101
+ )}
102
+ >
103
+ <div className="flex h-9 items-center justify-between gap-1">
104
+ <DayNumber day={day} today={today} muted={!inMonth} label={firstOfMonth ? formatDate(day, { month: "short", day: "numeric" }, { locale }) : null} api={api} count={dayItems.length} />
105
+ {editable ? (
106
+ <IconButton
107
+ size="sm"
108
+ icon="plus"
109
+ label={`${api.addLabel} on ${label}`}
110
+ onClick={(e) => {
111
+ e.stopPropagation();
112
+ api.startDraft({ day, allDay: true });
113
+ }}
114
+ className="opacity-0 transition-opacity duration-150 group-hover/cell:opacity-100 focus-visible:opacity-100 [@media(hover:none)]:hidden"
115
+ />
116
+ ) : null}
117
+ </div>
118
+ <div data-cal-bg="" aria-hidden="true" style={{ height: reserve - (overflow ? LANE_PX : 0) }} />
119
+ {overflow && hidden.length ? <MoreItems day={day} label={label} items={dayItems} count={hidden.length} api={api} /> : overflow ? <div aria-hidden="true" style={{ height: LANE_PX }} /> : null}
120
+ {drafting ? (
121
+ <div className="mt-0.5 flex h-6 items-center rounded-sm bg-primary/10 px-1.5 ring-1 ring-primary">
122
+ <DraftInput label={`New task on ${label}`} onSubmit={api.saveDraft} onCancel={api.cancelDraft} />
123
+ </div>
124
+ ) : null}
125
+ <div data-cal-bg="" className="min-h-2 flex-1" />
126
+ </div>
127
+ );
128
+ }
129
+
130
+ function DayNumber({ day, today, muted, label, api, count }) {
131
+ const n = Number(day.slice(8, 10));
132
+ const words = `${dayName(day, api.locale)}${count ? `, ${count} ${count === 1 ? "item" : "items"}` : ""}. Open the day`;
133
+ return (
134
+ // raw: the date is a small round target in the corner of the cell
135
+ // (the day view opens from it); a kit Button is a 36px padded action.
136
+ <button
137
+ type="button"
138
+ onClick={(e) => {
139
+ e.stopPropagation();
140
+ api.openDay(day);
141
+ }}
142
+ aria-label={words}
143
+ aria-current={today ? "date" : undefined}
144
+ className={cx(
145
+ "inline-flex h-7 min-w-7 items-center justify-center rounded-full px-1.5 text-xs tabular-nums outline-none transition-colors duration-150 focus-visible:ring-2 focus-visible:ring-ring",
146
+ today ? "bg-primary font-semibold text-primary-foreground" : "hover:bg-accent",
147
+ !today && (muted ? "text-muted-foreground" : "font-medium text-foreground"),
148
+ )}
149
+ >
150
+ {label ?? n}
151
+ </button>
152
+ );
153
+ }
154
+
155
+ function MoreItems({ day, label, items, count, api }) {
156
+ const [open, setOpen] = useState(false);
157
+ return (
158
+ <Popover
159
+ label={`Everything on ${label}`}
160
+ open={open}
161
+ onOpenChange={setOpen}
162
+ width="md"
163
+ align="start"
164
+ className="p-2"
165
+ trigger={(props) => (
166
+ // raw: a line of small text inside the day cell, sized to a lane;
167
+ // Popover hands its trigger props to a button of ours.
168
+ <button
169
+ type="button"
170
+ {...props}
171
+ onClick={(e) => e.stopPropagation()}
172
+ className="flex h-6 items-center rounded-sm px-1.5 text-left text-xs font-medium text-muted-foreground outline-none hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring"
173
+ >
174
+ {count} more
175
+ </button>
176
+ )}
177
+ >
178
+ <p className="px-1 pb-2 text-sm font-semibold">{label}</p>
179
+ <ul className="grid gap-1">
180
+ {items.map((it) => (
181
+ <li key={it.event.id}>
182
+ <TaskChip task={it.event.task} ctx={api.ctx} onOpen={api.open ? (t) => (setOpen(false), api.open(t)) : undefined} />
183
+ </li>
184
+ ))}
185
+ </ul>
186
+ </Popover>
187
+ );
188
+ }
189
+
190
+ function MonthItem({ item, week, api, cellWidth }) {
191
+ const { event, col, span, lane, clippedStart, clippedEnd } = item;
192
+ const { ctx, editable } = api;
193
+ const task = event.task;
194
+ const done = isDone(task, ctx);
195
+ const paint = paintOf(task, ctx, api.colorBy);
196
+ const title = task.title || "Untitled";
197
+ const bar = !event.timed;
198
+ const d = useDraggableTask(`bar:${event.id}:${week[0]}`, { kind: "span", task, event }, { disabled: !editable });
199
+ const canResize = editable && bar && !clippedEnd;
200
+ const r = useDraggableTask(`rx:${event.id}:${week[0]}`, { kind: "resize-x", task, event, cellWidth }, { disabled: !canResize });
201
+ let grow = 0;
202
+ if (r.isDragging && r.transform) grow = Math.round(r.transform.x / cellWidth());
203
+ const shownSpan = Math.max(1, Math.min(7 - col, span + Math.max(grow, 1 - span)));
204
+ const when = event.timed ? minutesLabel(event.from, { locale: api.locale }) : "";
205
+ const words = `${title}, ${event.timed ? (event.deadline ? `due ${when}` : when) : event.start === event.end ? "all day" : `${formatDate(event.start, { month: "short", day: "numeric" })} to ${formatDate(event.end, { month: "short", day: "numeric" })}`}${done ? ", done" : ""}`;
206
+ const keys = withKeys(d.handle, (e) => {
207
+ if (e.key === "Enter") return true;
208
+ if ((e.key === "Delete" || e.key === "Backspace") && editable) {
209
+ e.preventDefault();
210
+ api.remove(task);
211
+ return true;
212
+ }
213
+ if (bar && editable && e.shiftKey && (e.key === "ArrowRight" || e.key === "ArrowLeft")) {
214
+ e.preventDefault();
215
+ api.extend(event, e.key === "ArrowRight" ? 1 : -1);
216
+ return true;
217
+ }
218
+ return false;
219
+ });
220
+ return (
221
+ // raw: an item on the month is a drag source that also opens; a kit
222
+ // Button would centre and pad it as an action.
223
+ <button
224
+ type="button"
225
+ ref={d.setNodeRef}
226
+ data-cal-id={event.id}
227
+ {...(editable ? keys : {})}
228
+ onPointerDown={(e) => {
229
+ if (editable) {
230
+ // Which of its days was grabbed: a span moves by the days
231
+ // between that one and the one it is dropped on.
232
+ const rect = e.currentTarget.getBoundingClientRect();
233
+ const w = rect.width / shownSpan;
234
+ api.setGrab(week[col + Math.max(0, Math.min(shownSpan - 1, Math.floor((e.clientX - rect.left) / w)))]);
235
+ keys.onPointerDown?.(e);
236
+ }
237
+ }}
238
+ onClick={api.open ? () => api.open(task) : undefined}
239
+ aria-label={words}
240
+ title={title}
241
+ style={{ gridColumn: `${col + 1} / span ${shownSpan}`, gridRow: lane + 1 }}
242
+ className={cx(
243
+ "pointer-events-auto relative flex min-w-0 items-center gap-1.5 text-left text-xs outline-none transition-[opacity,background-color] duration-150 focus-visible:ring-2 focus-visible:ring-ring",
244
+ clippedStart ? "ms-0 rounded-s-none" : "ms-1",
245
+ clippedEnd ? "me-0 rounded-e-none" : "me-1",
246
+ bar ? cx("rounded-sm border-s-[3px] px-1.5 font-medium text-foreground", paint.tint, clippedStart && "border-s-0 ps-2") : "rounded-sm px-1.5 hover:bg-accent",
247
+ editable ? "cursor-grab active:cursor-grabbing" : api.open ? "cursor-pointer" : "cursor-default",
248
+ d.isDragging && "opacity-40",
249
+ r.isDragging && "ring-2 ring-primary",
250
+ done && "text-muted-foreground",
251
+ )}
252
+ >
253
+ {bar ? null : <span aria-hidden="true" className={cx("size-2 shrink-0 rounded-full", paint.dot, done && "opacity-50")} />}
254
+ {when ? (
255
+ <span data-nums className="shrink-0 text-muted-foreground">
256
+ {when}
257
+ </span>
258
+ ) : null}
259
+ <span className={cx("min-w-0 flex-1 truncate", done && "line-through")}>{title}</span>
260
+ {canResize ? (
261
+ <span
262
+ ref={r.setNodeRef}
263
+ {...r.handle}
264
+ role="presentation"
265
+ tabIndex={-1}
266
+ aria-hidden="true"
267
+ onClick={(e) => e.stopPropagation()}
268
+ className="absolute inset-y-0 end-0 w-2 cursor-ew-resize rounded-e-sm hover:bg-primary/30"
269
+ />
270
+ ) : null}
271
+ </button>
272
+ );
273
+ }
274
+
275
+ // ---- a phone's month: dots, and the tapped day listed under it ----------
276
+
277
+ function NarrowMonth({ weeks, month, events, api, selected, onSelect }) {
278
+ const { ctx, locale } = api;
279
+ const byDay = useMemo(() => {
280
+ const m = new Map();
281
+ for (const e of events) {
282
+ for (const week of weeks) {
283
+ for (const day of week) if (e.start <= day && day <= e.end) m.set(day, [...(m.get(day) ?? []), e]);
284
+ }
285
+ }
286
+ return m;
287
+ }, [events, weeks]);
288
+ const day = selected ?? ctx.today;
289
+ return (
290
+ <div className="grid gap-4">
291
+ <div className="overflow-hidden rounded-lg border border-border bg-card">
292
+ <div className="grid grid-cols-7 border-b border-border">
293
+ {weeks[0].map((d) => (
294
+ <div key={d} className="py-2 text-center text-2xs font-medium text-muted-foreground">
295
+ {formatDate(d, { weekday: "narrow" }, { locale })}
296
+ </div>
297
+ ))}
298
+ </div>
299
+ {weeks.map((week) => (
300
+ <div key={week[0]} className="grid grid-cols-7">
301
+ {week.map((d) => {
302
+ const items = byDay.get(d) ?? [];
303
+ const isSel = d === day;
304
+ const isToday = d === ctx.today;
305
+ return (
306
+ // raw: a day on a phone's month is one tap target — a
307
+ // number and its dots — that lists the day below.
308
+ <button
309
+ key={d}
310
+ type="button"
311
+ onClick={() => onSelect(d)}
312
+ aria-pressed={isSel}
313
+ aria-label={`${dayName(d, locale)}${items.length ? `, ${items.length} ${items.length === 1 ? "item" : "items"}` : ""}`}
314
+ className={cx(
315
+ "flex min-h-12 flex-col items-center justify-start gap-1 py-1.5 outline-none transition-colors duration-150 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
316
+ d.slice(0, 7) !== month && "text-muted-foreground",
317
+ )}
318
+ >
319
+ <span
320
+ className={cx(
321
+ "inline-flex size-7 items-center justify-center rounded-full text-sm tabular-nums",
322
+ isSel ? "bg-foreground font-semibold text-background" : isToday ? "font-semibold text-primary" : undefined,
323
+ )}
324
+ >
325
+ {Number(d.slice(8, 10))}
326
+ </span>
327
+ <span className="flex h-1.5 items-center gap-0.5" aria-hidden="true">
328
+ {items.slice(0, 3).map((e) => (
329
+ <span key={e.id} className={cx("size-1.5 rounded-full", paintOf(e.task, ctx, api.colorBy).dot)} />
330
+ ))}
331
+ </span>
332
+ </button>
333
+ );
334
+ })}
335
+ </div>
336
+ ))}
337
+ </div>
338
+ <AgendaDay day={day} events={byDay.get(day) ?? eventsOn(events, day)} api={api} standalone />
339
+ </div>
340
+ );
341
+ }
342
+
343
+ function eventsOn(events, day) {
344
+ return events.filter((e) => e.start <= day && day <= e.end);
345
+ }
346
+