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,609 @@
1
+ "use client";
2
+
3
+ import { useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
+ import { cx } from "./cx";
5
+ import { IconButton } from "./button";
6
+ import { Select } from "./field";
7
+
8
+ // Calendar — a month grid to pick a day, several days, or a span of days.
9
+ // It is the WAI-ARIA date grid: one Tab stop (the focused day), arrows
10
+ // move a day or a week, Page Up/Down a month (with Shift, a year), Home
11
+ // and End the week's edges, Enter or Space picks. Names, week start and
12
+ // digits come from Intl for the reader's locale. No date library.
13
+ //
14
+ // mode single (value "2026-03-12" | null) · multiple (value
15
+ // ["2026-03-12", …], kept sorted) · range (value { from, to }
16
+ // | null; `to` is null until the second click; a second click
17
+ // before `from` swaps them)
18
+ // value, onChange(value) — controlled; or `defaultValue`
19
+ // required single: clicking the chosen day again keeps it (default:
20
+ // it clears)
21
+ // month the month shown, "2026-03" (controlled, with onMonthChange);
22
+ // or `defaultMonth`; else the first chosen day's, else today's
23
+ // numberOfMonths side by side from 640px, stacked on a phone
24
+ // min, max "YYYY-MM-DD", inclusive; days past them are disabled and
25
+ // the arrows stop there
26
+ // disabled (date) → true for a day that cannot be picked (weekends,
27
+ // booked days); true disables every day
28
+ // captionLayout label (default) · dropdown (month and year Selects for
29
+ // far jumps; the arrows stay) · none (no caption and no
30
+ // arrows: the parent shows the month and moves it, passing a
31
+ // controlled `month`; a screen reader still hears the month)
32
+ // fromYear, toYear the dropdown's years (default: min/max, else today
33
+ // −100 … +10)
34
+ // showOutsideDays the neighbouring months' days, muted (true)
35
+ // showWeekNumbers ISO 8601 week numbers down the side
36
+ // marked days that hold something (posts, bookings): a list of
37
+ // "YYYY-MM-DD", or { "2026-03-04": { tone, label } } — a dot
38
+ // under the number in `tone` (primary, the default · neutral ·
39
+ // success · warning · danger · info); `label` joins the day's
40
+ // name for a screen reader ("Wednesday, March 4, 2026, 3
41
+ // posts"). Selection is unchanged: open the day's items from
42
+ // onChange
43
+ // emphasizeMarked marked days drawn bold, the rest muted — a calendar
44
+ // that exists to show where the posts are (false)
45
+ // onlyMarked unmarked days cannot be picked, with no strike-through: they
46
+ // are empty, not forbidden (that stays `disabled`'s look).
47
+ // Keys still walk them (false)
48
+ // weekStartsOn 0 (Sunday) … 6; default: the locale's
49
+ // locale a BCP 47 tag; default: the browser's
50
+ // today "YYYY-MM-DD", drawn ringed; default: the browser's today.
51
+ // Pass it where a screen must not change from day to day (a
52
+ // demo, a test)
53
+ // size md (44px days) · sm (36px days from 640px, 44px on a phone)
54
+ // autoFocus when it turns true, focus moves to the grid (a picker
55
+ // passes its open state)
56
+ // label what a screen reader calls the whole calendar ("Calendar")
57
+ //
58
+ // Dates are plain "YYYY-MM-DD" strings in and out, never Date objects. A
59
+ // date is a day on a wall calendar, not an instant: a Date is an instant,
60
+ // and "2026-03-12" parsed as one is midnight UTC — the 11th in New York.
61
+ // Strings compare in order ("2026-03-02" < "2026-03-12"), survive JSON
62
+ // and a database's `date` column unchanged, and mean the same day in
63
+ // every timezone. Inside, arithmetic runs on UTC midnights, where no
64
+ // daylight-saving shift can add or lose a day. The helpers below are
65
+ // exported for the same work in a surface.
66
+
67
+ // ── Dates as strings ────────────────────────────────────────────────────
68
+
69
+ const ISO = /^(\d{4})-(\d{2})-(\d{2})$/;
70
+ const DAY = 86400000;
71
+ const pad = (n, w = 2) => String(n).padStart(w, "0");
72
+
73
+ /** "YYYY-MM-DD" → a Date at that day's UTC midnight; null when it is not
74
+ * a real day ("2026-02-30", "", undefined). */
75
+ export function parseDate(s) {
76
+ const m = typeof s === "string" ? ISO.exec(s) : null;
77
+ if (!m) return null;
78
+ const d = new Date(0);
79
+ d.setUTCFullYear(+m[1], +m[2] - 1, +m[3]);
80
+ return d.getUTCMonth() === +m[2] - 1 && d.getUTCDate() === +m[3] ? d : null;
81
+ }
82
+
83
+ const iso = (d) => `${pad(d.getUTCFullYear(), 4)}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;
84
+
85
+ /** True for a real "YYYY-MM-DD" day. */
86
+ export const isDateString = (s) => parseDate(s) !== null;
87
+
88
+ /** A JS Date → the "YYYY-MM-DD" it is on the reader's own calendar
89
+ * (local time: new Date() at 23:30 in Tokyo is Tokyo's day). */
90
+ export function toDateString(date = new Date()) {
91
+ return `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
92
+ }
93
+
94
+ /** Today on the reader's calendar, "YYYY-MM-DD". */
95
+ export const todayString = () => toDateString(new Date());
96
+
97
+ /** The day `n` days on (negative: back). */
98
+ export function addDays(s, n) {
99
+ const d = parseDate(s);
100
+ return d ? iso(new Date(d.getTime() + n * DAY)) : null;
101
+ }
102
+
103
+ /** The same day `n` months on, clamped to the month's end (Jan 31 + 1 →
104
+ * Feb 28). */
105
+ export function addMonths(s, n) {
106
+ const d = parseDate(s);
107
+ if (!d) return null;
108
+ const y = d.getUTCFullYear();
109
+ const m = d.getUTCMonth() + n;
110
+ const last = new Date(Date.UTC(2000, 0, 1));
111
+ last.setUTCFullYear(y, m + 1, 0);
112
+ const out = new Date(0);
113
+ out.setUTCFullYear(y, m, Math.min(d.getUTCDate(), last.getUTCDate()));
114
+ return iso(out);
115
+ }
116
+
117
+ /** The first day of `s`'s month; "2026-03" works as well as a full date. */
118
+ export const startOfMonth = (s) => (typeof s === "string" && /^\d{4}-\d{2}/.test(s) ? `${s.slice(0, 7)}-01` : null);
119
+
120
+ /** The last day of `s`'s month. */
121
+ export const endOfMonth = (s) => {
122
+ const first = startOfMonth(s);
123
+ return first ? addDays(addMonths(first, 1), -1) : null;
124
+ };
125
+
126
+ /** The day of the week, 0 (Sunday) … 6. */
127
+ export const dayOfWeek = (s) => parseDate(s)?.getUTCDay() ?? null;
128
+
129
+ // Intl's spacing differs between ICU builds (Node's thin and no-break
130
+ // spaces around a range's dash, a browser's plain ones): the server's
131
+ // HTML and the browser's first render must be the same text, so every
132
+ // formatted string is written with plain spaces.
133
+ export const plainSpaces = (s) => s.replace(/[\u00a0\u2009\u202f]/g, " ");
134
+
135
+ /** A day in words for the locale: formatDate("2026-03-12") → "Mar 12,
136
+ * 2026"; `options` are Intl.DateTimeFormat's ({ dateStyle: "full" }). */
137
+ export function formatDate(s, options = { dateStyle: "medium" }, locale) {
138
+ const d = parseDate(s);
139
+ return d ? plainSpaces(new Intl.DateTimeFormat(locale, { ...options, timeZone: "UTC" }).format(d)) : "";
140
+ }
141
+
142
+ // The week's first day for a locale: Intl's own answer where the browser
143
+ // has it (getWeekInfo), else CLDR's regions that start on Sunday or
144
+ // Saturday; everyone else starts on Monday.
145
+ const SUNDAY = new Set("AG AS BD BR BS BT BW BZ CA CO DM DO ET GT GU HK HN ID IL IN JM JP KE KH KR LA MH MM MO MT MX MZ NI NP PA PE PH PK PR PT PY SA SG SV TH TT TW UM US VE VI WS YE ZA ZW".split(" "));
146
+ const SATURDAY = new Set("AE AF BH DJ DZ EG IQ IR JO KW LY OM QA SD SY".split(" "));
147
+
148
+ /** 0 (Sunday) … 6: the day a week starts on in `locale`. */
149
+ export function firstDayOfWeek(locale) {
150
+ try {
151
+ const loc = new Intl.Locale(locale ?? Intl.DateTimeFormat().resolvedOptions().locale);
152
+ const info = loc.getWeekInfo?.() ?? loc.weekInfo;
153
+ if (info?.firstDay) return info.firstDay % 7;
154
+ const region = loc.maximize().region;
155
+ return SUNDAY.has(region) ? 0 : SATURDAY.has(region) ? 6 : 1;
156
+ } catch {
157
+ return 1;
158
+ }
159
+ }
160
+
161
+ // ISO 8601 week number of the week holding `thursday` (a Thursday's
162
+ // week number is its day of the year, in sevens, rounded up).
163
+ function isoWeek(thursday) {
164
+ const d = parseDate(thursday);
165
+ const jan1 = Date.UTC(d.getUTCFullYear(), 0, 1);
166
+ return Math.floor((d.getTime() - jan1) / DAY / 7) + 1;
167
+ }
168
+
169
+ // ── The reader's locale and today, without a hydration mismatch ────────
170
+ // The server does not know either. useSyncExternalStore renders the
171
+ // server's answer (null) while hydrating, then the browser's — so the
172
+ // first paint matches the HTML and nothing warns.
173
+
174
+ const never = () => () => {};
175
+ function useBrowser(get) {
176
+ return useSyncExternalStore(never, get, () => null);
177
+ }
178
+
179
+ /** The locale to format in: `locale`, else the browser's (after
180
+ * hydration; "en-US" in the server's HTML). */
181
+ export function useLocale(locale) {
182
+ const browser = useBrowser(() => navigator.language);
183
+ return locale ?? browser ?? "en-US";
184
+ }
185
+
186
+ /** `today`, else the browser's today once hydrated (null before). */
187
+ export function useToday(today) {
188
+ const browser = useBrowser(todayString);
189
+ return today ?? browser;
190
+ }
191
+
192
+ // ── The grid ────────────────────────────────────────────────────────────
193
+
194
+ // A marked day's dot. On a picked day (the primary fill) the primary and
195
+ // neutral dots turn to the fill's own foreground so they still show.
196
+ const DOT = {
197
+ primary: "bg-primary",
198
+ neutral: "bg-muted-foreground",
199
+ success: "bg-success",
200
+ warning: "bg-warning",
201
+ danger: "bg-destructive",
202
+ info: "bg-info",
203
+ };
204
+
205
+ const SIZES = {
206
+ md: { cell: "size-11", caption: "h-11", nav: "md" },
207
+ sm: { cell: "size-11 sm:size-9", caption: "h-11 sm:h-9", nav: "sm" },
208
+ };
209
+
210
+ function useControlled(value, fallback) {
211
+ const [own, setOwn] = useState(fallback);
212
+ return value !== undefined ? [value, false] : [own, setOwn];
213
+ }
214
+
215
+ function listOf(mode, value) {
216
+ if (!value) return [];
217
+ if (mode === "multiple") return Array.isArray(value) ? value : [];
218
+ if (mode === "range") return [value.from, value.to].filter(Boolean);
219
+ return [value];
220
+ }
221
+
222
+ export function Calendar({
223
+ mode = "single",
224
+ value: valueProp,
225
+ defaultValue,
226
+ onChange,
227
+ required = false,
228
+ month: monthProp,
229
+ defaultMonth,
230
+ onMonthChange,
231
+ numberOfMonths = 1,
232
+ min,
233
+ max,
234
+ disabled,
235
+ captionLayout = "label",
236
+ fromYear,
237
+ toYear,
238
+ showOutsideDays = true,
239
+ showWeekNumbers = false,
240
+ marked,
241
+ emphasizeMarked = false,
242
+ onlyMarked = false,
243
+ weekStartsOn,
244
+ locale: localeProp,
245
+ today: todayProp,
246
+ size = "md",
247
+ autoFocus = false,
248
+ label = "Calendar",
249
+ className,
250
+ }) {
251
+ const uid = useId();
252
+ const root = useRef(null);
253
+ const pending = useRef(false);
254
+ const locale = useLocale(localeProp);
255
+ const today = useToday(todayProp);
256
+ const s = SIZES[size] ?? SIZES.md;
257
+ const n = Math.max(1, numberOfMonths | 0);
258
+
259
+ const [own, setOwnValue] = useControlled(valueProp, defaultValue ?? (mode === "multiple" ? [] : null));
260
+ const value = valueProp !== undefined ? valueProp : own;
261
+ const chosen = listOf(mode, value);
262
+
263
+ const [ownMonth, setOwnMonth] = useState(() => startOfMonth(defaultMonth) ?? startOfMonth(chosen[0]));
264
+ const first = startOfMonth(monthProp) ?? ownMonth ?? startOfMonth(today);
265
+ const last = first ? addMonths(first, n - 1) : null;
266
+ const [focus, setFocus] = useState(null);
267
+ const [hover, setHover] = useState(null);
268
+
269
+ const marks = useMemo(() => {
270
+ if (Array.isArray(marked)) return Object.fromEntries(marked.map((d) => [d, {}]));
271
+ return marked && typeof marked === "object" ? marked : {};
272
+ }, [marked]);
273
+
274
+ const ws = weekStartsOn ?? firstDayOfWeek(locale);
275
+ const fmt = useMemo(() => {
276
+ const f = (o) => {
277
+ const intl = new Intl.DateTimeFormat(locale, { ...o, timeZone: "UTC" });
278
+ return { format: (d) => plainSpaces(intl.format(d)) };
279
+ };
280
+ return {
281
+ caption: f({ month: "long", year: "numeric" }),
282
+ day: f({ day: "numeric" }),
283
+ full: f({ dateStyle: "full" }),
284
+ monthShort: f({ month: "short" }),
285
+ year: f({ year: "numeric" }),
286
+ weekShort: f({ weekday: "short" }),
287
+ weekLong: f({ weekday: "long" }),
288
+ };
289
+ }, [locale]);
290
+ // 2023-01-01 was a Sunday: the seven names from the week's first day.
291
+ const weekdays = useMemo(
292
+ () =>
293
+ Array.from({ length: 7 }, (_, i) => {
294
+ const d = parseDate(addDays("2023-01-01", (ws + i) % 7));
295
+ return { short: fmt.weekShort.format(d), long: fmt.weekLong.format(d) };
296
+ }),
297
+ [fmt, ws],
298
+ );
299
+
300
+ // Focus follows the roving day after the render that shows it.
301
+ useEffect(() => {
302
+ if (!pending.current) return;
303
+ pending.current = false;
304
+ root.current?.querySelector('button[data-day][tabindex="0"]')?.focus();
305
+ });
306
+ useEffect(() => {
307
+ if (!autoFocus) return;
308
+ const go = () => root.current?.querySelector('button[data-day][tabindex="0"]')?.focus({ preventScroll: true });
309
+ // Inside a popover not shown yet (one open on load), wait for it: the
310
+ // Popover focuses its first control on toggle, and the day wins after.
311
+ const pop = root.current?.closest("[popover]");
312
+ if (pop && !pop.matches(":popover-open")) {
313
+ let t;
314
+ const on = () => (t = setTimeout(go));
315
+ pop.addEventListener("toggle", on, { once: true });
316
+ return () => {
317
+ pop.removeEventListener("toggle", on);
318
+ clearTimeout(t);
319
+ };
320
+ }
321
+ go();
322
+ }, [autoFocus]);
323
+
324
+ function setMonth(m) {
325
+ if (monthProp === undefined) setOwnMonth(m);
326
+ onMonthChange?.(m.slice(0, 7));
327
+ }
328
+
329
+ function setValue(v) {
330
+ if (setOwnValue) setOwnValue(v);
331
+ onChange?.(v);
332
+ }
333
+
334
+ const isDisabled = (d) =>
335
+ disabled === true || (min && d < min) || (max && d > max) || (typeof disabled === "function" && !!disabled(d));
336
+ const inView = (d) => !!(d && first && startOfMonth(d) >= first && startOfMonth(d) <= last);
337
+
338
+ const isEmpty = (d) => onlyMarked && !marks[d];
339
+
340
+ function pick(d) {
341
+ if (isDisabled(d) || isEmpty(d)) return;
342
+ if (mode === "multiple") {
343
+ setValue(chosen.includes(d) ? chosen.filter((x) => x !== d) : [...chosen, d].sort());
344
+ } else if (mode === "range") {
345
+ const { from, to } = value ?? {};
346
+ if (!from || to) setValue({ from: d, to: null });
347
+ else if (d < from) setValue({ from: d, to: from });
348
+ else setValue({ from, to: d });
349
+ } else {
350
+ setValue(value === d && !required ? null : d);
351
+ }
352
+ }
353
+
354
+ function moveTo(d) {
355
+ if (min && d < min) d = min;
356
+ if (max && d > max) d = max;
357
+ const m = startOfMonth(d);
358
+ if (m < first) setMonth(m);
359
+ else if (m > last) setMonth(addMonths(m, -(n - 1)));
360
+ setFocus(d);
361
+ pending.current = true;
362
+ }
363
+
364
+ function onKeyDown(e) {
365
+ const day = e.target.dataset?.day;
366
+ if (!day || e.altKey || e.ctrlKey || e.metaKey) return;
367
+ const rtl = getComputedStyle(e.currentTarget).direction === "rtl";
368
+ const back = (dayOfWeek(day) - ws + 7) % 7;
369
+ const step = {
370
+ ArrowLeft: () => addDays(day, rtl ? 1 : -1),
371
+ ArrowRight: () => addDays(day, rtl ? -1 : 1),
372
+ ArrowUp: () => addDays(day, -7),
373
+ ArrowDown: () => addDays(day, 7),
374
+ PageUp: () => addMonths(day, e.shiftKey ? -12 : -1),
375
+ PageDown: () => addMonths(day, e.shiftKey ? 12 : 1),
376
+ Home: () => addDays(day, -back),
377
+ End: () => addDays(day, 6 - back),
378
+ }[e.key];
379
+ if (!step) return;
380
+ e.preventDefault();
381
+ moveTo(step());
382
+ }
383
+
384
+ // Range display: the committed span, or — between the two clicks —
385
+ // a preview from `from` to the day under the pointer or focus.
386
+ const range = mode === "range" ? value ?? {} : {};
387
+ const previewing = !!(range.from && !range.to && hover);
388
+ const ends = range.from ? [range.from, range.to ?? (previewing ? hover : range.from)].sort() : null;
389
+
390
+ const tabbable = [focus, ...chosen, today].find((d) => inView(d) && !(min && d < min) && !(max && d > max)) ?? (inView(min) ? min : first);
391
+
392
+ if (!first) {
393
+ // Hydrating with no month to show yet: hold the space.
394
+ return <div ref={root} role="group" aria-label={label} aria-busy="true" className={cx("min-h-80 min-w-72", className)} />;
395
+ }
396
+
397
+ const months = Array.from({ length: n }, (_, i) => addMonths(first, i));
398
+ const prevOff = !!(min && startOfMonth(min) >= first);
399
+ const nextOff = !!(max && startOfMonth(max) <= last);
400
+
401
+ function Caption({ m, i }) {
402
+ const id = `${uid}-cap-${i}`;
403
+ if (captionLayout === "none") {
404
+ return (
405
+ <span id={id} className="sr-only" aria-live={i === 0 ? "polite" : undefined}>
406
+ {fmt.caption.format(parseDate(m))}
407
+ </span>
408
+ );
409
+ }
410
+ if (captionLayout === "dropdown" && i === 0) {
411
+ const y = +m.slice(0, 4);
412
+ const ty = +(today ?? m).slice(0, 4);
413
+ const lo = Math.min(fromYear ?? (min ? +min.slice(0, 4) : ty - 100), y);
414
+ const hi = Math.max(toYear ?? (max ? +max.slice(0, 4) : ty + 10), y);
415
+ const monthOff = (k) => {
416
+ const mm = `${pad(y, 4)}-${pad(k + 1)}-01`;
417
+ return (min && endOfMonth(mm) < min) || (max && mm > max);
418
+ };
419
+ return (
420
+ <div className={cx("flex items-center justify-center gap-1 px-12", s.caption)}>
421
+ <span id={id} className="sr-only" aria-live="polite">
422
+ {fmt.caption.format(parseDate(m))}
423
+ </span>
424
+ <span className="min-w-0 flex-[3]">
425
+ <Select aria-label="Month" value={String(+m.slice(5, 7))} onChange={(e) => setMonth(`${pad(y, 4)}-${pad(+e.target.value)}-01`)}>
426
+ {Array.from({ length: 12 }, (_, k) => (
427
+ <option key={k} value={k + 1} disabled={monthOff(k)}>
428
+ {fmt.monthShort.format(parseDate(`2023-${pad(k + 1)}-01`))}
429
+ </option>
430
+ ))}
431
+ </Select>
432
+ </span>
433
+ <span className="min-w-0 flex-[2]">
434
+ <Select aria-label="Year" value={String(y)} onChange={(e) => setMonth(`${pad(+e.target.value, 4)}${m.slice(4)}`)}>
435
+ {Array.from({ length: hi - lo + 1 }, (_, k) => (
436
+ <option key={k} value={lo + k}>
437
+ {fmt.year.format(parseDate(`${pad(lo + k, 4)}-06-15`))}
438
+ </option>
439
+ ))}
440
+ </Select>
441
+ </span>
442
+ </div>
443
+ );
444
+ }
445
+ return (
446
+ <div id={id} aria-live={i === 0 ? "polite" : undefined} className={cx("flex items-center justify-center px-12 font-medium", s.caption)}>
447
+ {fmt.caption.format(parseDate(m))}
448
+ </div>
449
+ );
450
+ }
451
+
452
+ function Month({ m, i }) {
453
+ const lead = (dayOfWeek(m) - ws + 7) % 7;
454
+ const start = addDays(m, -lead);
455
+ const dim = +endOfMonth(m).slice(8);
456
+ const rows = Math.ceil((lead + dim) / 7);
457
+ return (
458
+ <div className="grid content-start gap-2">
459
+ {Caption({ m, i })}
460
+ <table role="grid" aria-labelledby={`${uid}-cap-${i}`} className="border-collapse" onKeyDown={onKeyDown}>
461
+ <thead>
462
+ <tr>
463
+ {showWeekNumbers ? (
464
+ <th scope="col" className="w-8 text-xs font-normal text-muted-foreground">
465
+ <span className="sr-only">Week</span>
466
+ </th>
467
+ ) : null}
468
+ {weekdays.map((w) => (
469
+ <th key={w.long} scope="col" abbr={w.long} className="h-8 p-0 text-xs font-normal text-muted-foreground">
470
+ <span aria-hidden="true">{w.short}</span>
471
+ <span className="sr-only">{w.long}</span>
472
+ </th>
473
+ ))}
474
+ </tr>
475
+ </thead>
476
+ <tbody>
477
+ {Array.from({ length: rows }, (_, r) => {
478
+ const rowStart = addDays(start, r * 7);
479
+ return (
480
+ <tr key={rowStart}>
481
+ {showWeekNumbers ? (
482
+ <th scope="row" className="w-8 p-0 text-center text-xs font-normal tabular-nums text-muted-foreground">
483
+ {isoWeek(addDays(rowStart, (4 - dayOfWeek(rowStart) + 7) % 7))}
484
+ </th>
485
+ ) : null}
486
+ {Array.from({ length: 7 }, (_, c) => Day({ d: addDays(rowStart, c), m }))}
487
+ </tr>
488
+ );
489
+ })}
490
+ </tbody>
491
+ </table>
492
+ </div>
493
+ );
494
+ }
495
+
496
+ function Day({ d, m }) {
497
+ const outside = startOfMonth(d) !== m;
498
+ if (outside && !showOutsideDays) return <td key={d} className="p-0" />;
499
+ const off = isDisabled(d);
500
+ const empty = !off && isEmpty(d);
501
+ const picked = mode === "range" ? d === range.from || d === range.to : chosen.includes(d);
502
+ // Beside another month, an outside day repeats a day shown there: only
503
+ // the real one carries the band.
504
+ const band = ends && ends[0] < ends[1] && d >= ends[0] && d <= ends[1] && !(outside && n > 1);
505
+ const isToday = d === today;
506
+ const mark = marks[d];
507
+ const tone = mark ? (DOT[mark.tone] ? mark.tone : "primary") : null;
508
+ // cx does not merge: one text colour and one weight per day.
509
+ const quiet = !picked && !band && !outside && ((emphasizeMarked && !mark) || empty);
510
+ return (
511
+ <td
512
+ key={d}
513
+ aria-selected={picked || (band && !previewing) || undefined}
514
+ className={cx(
515
+ "p-0 text-center",
516
+ band && (previewing ? "bg-accent/50" : "bg-accent"),
517
+ band && d === ends[0] && "rounded-l-md",
518
+ band && d === ends[1] && "rounded-r-md",
519
+ )}
520
+ >
521
+ <button
522
+ type="button"
523
+ data-day={d}
524
+ data-outside={outside || undefined}
525
+ tabIndex={!outside && d === tabbable ? 0 : -1}
526
+ aria-label={[fmt.full.format(parseDate(d)), isToday && "today", mark?.label].filter(Boolean).join(", ")}
527
+ aria-current={isToday ? "date" : undefined}
528
+ aria-disabled={off || empty || undefined}
529
+ onClick={() => {
530
+ if (off || empty) return;
531
+ pick(d);
532
+ setFocus(d);
533
+ if (!inView(d)) setMonth(startOfMonth(d) < first ? startOfMonth(d) : addMonths(startOfMonth(d), -(n - 1)));
534
+ }}
535
+ onMouseEnter={() => mode === "range" && setHover(d)}
536
+ onFocus={() => mode === "range" && setHover(d)}
537
+ className={cx(
538
+ "relative inline-flex items-center justify-center rounded-md text-sm tabular-nums outline-none",
539
+ "focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-ring",
540
+ s.cell,
541
+ picked
542
+ ? "bg-primary font-medium text-primary-foreground"
543
+ : band
544
+ ? "text-accent-foreground hover:bg-accent"
545
+ : quiet
546
+ ? "text-muted-foreground"
547
+ : "text-foreground",
548
+ !picked && !band && !empty && "hover:bg-accent",
549
+ emphasizeMarked && mark && !picked && !isToday && "font-semibold",
550
+ outside && !picked && "text-muted-foreground opacity-60",
551
+ outside && picked && "opacity-70",
552
+ off && "cursor-not-allowed line-through opacity-40 hover:bg-transparent",
553
+ empty && "cursor-default",
554
+ // Today: a ring and a heavier number — never colour alone.
555
+ isToday && "font-semibold ring-1 ring-inset ring-muted-foreground/60",
556
+ )}
557
+ >
558
+ {fmt.day.format(parseDate(d))}
559
+ {tone ? (
560
+ <span
561
+ aria-hidden="true"
562
+ className={cx(
563
+ "absolute bottom-1 left-1/2 size-1.5 -translate-x-1/2 rounded-full",
564
+ picked && (tone === "primary" || tone === "neutral") ? "bg-primary-foreground" : DOT[tone],
565
+ )}
566
+ />
567
+ ) : null}
568
+ </button>
569
+ </td>
570
+ );
571
+ }
572
+
573
+ return (
574
+ <div
575
+ ref={root}
576
+ role="group"
577
+ aria-label={label}
578
+ onMouseLeave={() => setHover(null)}
579
+ onBlur={(e) => !root.current?.contains(e.relatedTarget) && setHover(null)}
580
+ className={cx("relative inline-block max-w-full text-sm", className)}
581
+ >
582
+ {captionLayout === "none" ? null : (
583
+ <>
584
+ <IconButton
585
+ icon="chevron-left"
586
+ label="Previous month"
587
+ size={s.nav}
588
+ disabled={prevOff}
589
+ onClick={() => setMonth(addMonths(first, -1))}
590
+ className="absolute left-0 top-0 z-10"
591
+ />
592
+ <IconButton
593
+ icon="chevron-right"
594
+ label="Next month"
595
+ size={s.nav}
596
+ disabled={nextOff}
597
+ onClick={() => setMonth(addMonths(first, 1))}
598
+ className="absolute right-0 top-0 z-10"
599
+ />
600
+ </>
601
+ )}
602
+ <div className="flex flex-col gap-4 sm:flex-row sm:gap-6">
603
+ {months.map((m, i) => (
604
+ <div key={m}>{Month({ m, i })}</div>
605
+ ))}
606
+ </div>
607
+ </div>
608
+ );
609
+ }