makersclaw 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -1
  3. package/THIRD-PARTY-NOTICES.md +180 -0
  4. package/package.json +15 -8
  5. package/r/annotate.json +62 -0
  6. package/r/approval-request.json +52 -0
  7. package/r/audio-player.json +74 -0
  8. package/r/auth-form.json +55 -0
  9. package/r/board.json +55 -0
  10. package/r/calendar-view.json +105 -0
  11. package/r/cart.json +62 -0
  12. package/r/chart.json +83 -0
  13. package/r/chat.json +95 -0
  14. package/r/code-editor.json +94 -0
  15. package/r/comment-box.json +64 -0
  16. package/r/contact-section.json +53 -0
  17. package/r/core.json +341 -0
  18. package/r/csv-import.json +63 -0
  19. package/r/data-table.json +69 -0
  20. package/r/diagram.json +74 -0
  21. package/r/doc-editor.json +82 -0
  22. package/r/doc-page.json +61 -0
  23. package/r/email-render.json +73 -0
  24. package/r/faq.json +50 -0
  25. package/r/file-upload.json +54 -0
  26. package/r/flow-canvas.json +93 -0
  27. package/r/footer.json +52 -0
  28. package/r/gantt.json +70 -0
  29. package/r/job-panel.json +56 -0
  30. package/r/json-editor.json +66 -0
  31. package/r/map.json +89 -0
  32. package/r/menubar.json +52 -0
  33. package/r/mind-map.json +67 -0
  34. package/r/navigation-menu.json +52 -0
  35. package/r/order-detail.json +54 -0
  36. package/r/org-chart.json +66 -0
  37. package/r/page-builder.json +105 -0
  38. package/r/payment-methods.json +51 -0
  39. package/r/pdf-document.json +79 -0
  40. package/r/pdf-viewer.json +88 -0
  41. package/r/product-detail.json +76 -0
  42. package/r/product-grid.json +65 -0
  43. package/r/record-form.json +67 -0
  44. package/r/record-notes.json +55 -0
  45. package/r/registry.json +3612 -0
  46. package/r/search-dialog.json +51 -0
  47. package/r/settings-list.json +66 -0
  48. package/r/setup-checklist.json +51 -0
  49. package/r/share-dialog.json +52 -0
  50. package/r/sidebar.json +69 -0
  51. package/r/signature-pad.json +72 -0
  52. package/r/sketch-canvas.json +99 -0
  53. package/r/spreadsheet.json +90 -0
  54. package/r/stat-cards.json +66 -0
  55. package/r/task-list.json +63 -0
  56. package/r/task-model.json +98 -0
  57. package/r/testimonials.json +52 -0
  58. package/r/transaction-list.json +53 -0
  59. package/r/whiteboard.json +66 -0
  60. package/registry/blocks/annotate/README.md +179 -0
  61. package/registry/blocks/annotate/annotate-data.js +250 -0
  62. package/registry/blocks/annotate/annotate.jsx +646 -0
  63. package/registry/blocks/annotate/block.json +10 -0
  64. package/registry/blocks/annotate/demo.jsx +135 -0
  65. package/registry/blocks/annotate/index.js +15 -0
  66. package/registry/blocks/approval-request/README.md +116 -0
  67. package/registry/blocks/approval-request/approval-request.jsx +386 -0
  68. package/registry/blocks/approval-request/block.json +10 -0
  69. package/registry/blocks/approval-request/demo.jsx +127 -0
  70. package/registry/blocks/approval-request/index.js +4 -0
  71. package/registry/blocks/audio-player/README.md +167 -0
  72. package/registry/blocks/audio-player/audio-player.jsx +623 -0
  73. package/registry/blocks/audio-player/block.json +14 -0
  74. package/registry/blocks/audio-player/colors.js +109 -0
  75. package/registry/blocks/audio-player/demo.jsx +209 -0
  76. package/registry/blocks/audio-player/index.js +6 -0
  77. package/registry/blocks/audio-player/time.js +67 -0
  78. package/registry/blocks/audio-player/wavesurfer.js +9 -0
  79. package/registry/blocks/auth-form/README.md +126 -0
  80. package/registry/blocks/auth-form/auth-form.jsx +568 -0
  81. package/registry/blocks/auth-form/block.json +10 -0
  82. package/registry/blocks/auth-form/demo.jsx +131 -0
  83. package/registry/blocks/auth-form/index.js +3 -0
  84. package/registry/blocks/board/README.md +64 -13
  85. package/registry/blocks/board/block.json +2 -2
  86. package/registry/blocks/board/board.jsx +237 -94
  87. package/registry/blocks/board/demo.jsx +103 -24
  88. package/registry/blocks/calendar-view/README.md +180 -0
  89. package/registry/blocks/calendar-view/agenda.jsx +147 -0
  90. package/registry/blocks/calendar-view/block.json +76 -0
  91. package/registry/blocks/calendar-view/calendar-model.js +442 -0
  92. package/registry/blocks/calendar-view/calendar.jsx +627 -0
  93. package/registry/blocks/calendar-view/demo.jsx +195 -0
  94. package/registry/blocks/calendar-view/draft.jsx +49 -0
  95. package/registry/blocks/calendar-view/index.js +39 -0
  96. package/registry/blocks/calendar-view/month.jsx +346 -0
  97. package/registry/blocks/calendar-view/paint.js +69 -0
  98. package/registry/blocks/calendar-view/time-grid.jsx +527 -0
  99. package/registry/blocks/calendar-view/tray.jsx +87 -0
  100. package/registry/blocks/cart/README.md +146 -0
  101. package/registry/blocks/cart/block.json +10 -0
  102. package/registry/blocks/cart/cart.jsx +597 -0
  103. package/registry/blocks/cart/demo.jsx +98 -0
  104. package/registry/blocks/cart/index.js +4 -0
  105. package/registry/blocks/cart/money.js +28 -0
  106. package/registry/blocks/chart/README.md +316 -0
  107. package/registry/blocks/chart/block.json +10 -0
  108. package/registry/blocks/chart/cartesian.jsx +642 -0
  109. package/registry/blocks/chart/core.jsx +262 -0
  110. package/registry/blocks/chart/demo.jsx +357 -0
  111. package/registry/blocks/chart/heatmap.jsx +336 -0
  112. package/registry/blocks/chart/index.js +8 -0
  113. package/registry/blocks/chart/pie.jsx +245 -0
  114. package/registry/blocks/chart/sparkline.jsx +88 -0
  115. package/registry/blocks/chat/README.md +273 -0
  116. package/registry/blocks/chat/attachment.jsx +95 -0
  117. package/registry/blocks/chat/block.json +10 -0
  118. package/registry/blocks/chat/chat.jsx +132 -0
  119. package/registry/blocks/chat/composer.jsx +364 -0
  120. package/registry/blocks/chat/demo.jsx +578 -0
  121. package/registry/blocks/chat/header.jsx +34 -0
  122. package/registry/blocks/chat/index.js +9 -0
  123. package/registry/blocks/chat/message.jsx +450 -0
  124. package/registry/blocks/chat/scroller.jsx +247 -0
  125. package/registry/blocks/chat/text.jsx +104 -0
  126. package/registry/blocks/code-editor/README.md +210 -0
  127. package/registry/blocks/code-editor/block.json +22 -0
  128. package/registry/blocks/code-editor/code-editor.jsx +534 -0
  129. package/registry/blocks/code-editor/codemirror.js +38 -0
  130. package/registry/blocks/code-editor/demo.jsx +205 -0
  131. package/registry/blocks/code-editor/index.js +8 -0
  132. package/registry/blocks/code-editor/json.js +317 -0
  133. package/registry/blocks/code-editor/sql.js +136 -0
  134. package/registry/blocks/code-editor/text.js +101 -0
  135. package/registry/blocks/code-editor/theme.js +186 -0
  136. package/registry/blocks/comment-box/README.md +123 -0
  137. package/registry/blocks/comment-box/block.json +10 -0
  138. package/registry/blocks/comment-box/comment-body.jsx +217 -0
  139. package/registry/blocks/comment-box/comment-box.jsx +198 -0
  140. package/registry/blocks/comment-box/comment-time.jsx +77 -0
  141. package/registry/blocks/comment-box/demo.jsx +141 -0
  142. package/registry/blocks/comment-box/index.js +8 -0
  143. package/registry/blocks/contact-section/README.md +152 -0
  144. package/registry/blocks/contact-section/block.json +11 -0
  145. package/registry/blocks/contact-section/contact-section.jsx +509 -0
  146. package/registry/blocks/contact-section/demo.jsx +93 -0
  147. package/registry/blocks/contact-section/index.js +4 -0
  148. package/registry/blocks/csv-import/README.md +133 -0
  149. package/registry/blocks/csv-import/block.json +13 -0
  150. package/registry/blocks/csv-import/csv-import.jsx +479 -0
  151. package/registry/blocks/csv-import/demo.jsx +106 -0
  152. package/registry/blocks/csv-import/import.js +200 -0
  153. package/registry/blocks/csv-import/index.js +7 -0
  154. package/registry/blocks/data-table/README.md +386 -0
  155. package/registry/blocks/data-table/block.json +10 -0
  156. package/registry/blocks/data-table/data-table.jsx +1164 -0
  157. package/registry/blocks/data-table/demo.jsx +588 -0
  158. package/registry/blocks/data-table/index.js +5 -0
  159. package/registry/blocks/data-table/model.js +169 -0
  160. package/registry/blocks/diagram/README.md +108 -0
  161. package/registry/blocks/diagram/block.json +13 -0
  162. package/registry/blocks/diagram/demo.jsx +113 -0
  163. package/registry/blocks/diagram/diagram.jsx +481 -0
  164. package/registry/blocks/diagram/index.js +7 -0
  165. package/registry/blocks/diagram/mermaid.js +52 -0
  166. package/registry/blocks/diagram/palette.js +313 -0
  167. package/registry/blocks/diagram/source.js +98 -0
  168. package/registry/blocks/doc-editor/README.md +215 -0
  169. package/registry/blocks/doc-editor/block.json +15 -0
  170. package/registry/blocks/doc-editor/demo.jsx +225 -0
  171. package/registry/blocks/doc-editor/doc-editor.jsx +291 -0
  172. package/registry/blocks/doc-editor/doc.js +309 -0
  173. package/registry/blocks/doc-editor/index.js +7 -0
  174. package/registry/blocks/doc-editor/schema.jsx +56 -0
  175. package/registry/blocks/doc-editor/shadcn-classes.js +110 -0
  176. package/registry/blocks/doc-editor/theme.js +82 -0
  177. package/registry/blocks/doc-page/README.md +119 -0
  178. package/registry/blocks/doc-page/autosave.js +104 -0
  179. package/registry/blocks/doc-page/block.json +10 -0
  180. package/registry/blocks/doc-page/demo.jsx +137 -0
  181. package/registry/blocks/doc-page/doc-page.jsx +276 -0
  182. package/registry/blocks/doc-page/index.js +4 -0
  183. package/registry/blocks/email-render/README.md +151 -0
  184. package/registry/blocks/email-render/block.json +14 -0
  185. package/registry/blocks/email-render/demo.jsx +153 -0
  186. package/registry/blocks/email-render/doc-email.jsx +210 -0
  187. package/registry/blocks/email-render/email.jsx +221 -0
  188. package/registry/blocks/email-render/index.js +10 -0
  189. package/registry/blocks/email-render/render.js +50 -0
  190. package/registry/blocks/email-render/theme.js +215 -0
  191. package/registry/blocks/faq/README.md +101 -0
  192. package/registry/blocks/faq/block.json +11 -0
  193. package/registry/blocks/faq/demo.jsx +89 -0
  194. package/registry/blocks/faq/faq.jsx +220 -0
  195. package/registry/blocks/faq/index.js +4 -0
  196. package/registry/blocks/file-upload/README.md +138 -0
  197. package/registry/blocks/file-upload/block.json +10 -0
  198. package/registry/blocks/file-upload/demo.jsx +204 -0
  199. package/registry/blocks/file-upload/file-upload.jsx +635 -0
  200. package/registry/blocks/file-upload/index.js +4 -0
  201. package/registry/blocks/flow-canvas/README.md +420 -0
  202. package/registry/blocks/flow-canvas/block.json +13 -0
  203. package/registry/blocks/flow-canvas/board.js +819 -0
  204. package/registry/blocks/flow-canvas/chrome.jsx +649 -0
  205. package/registry/blocks/flow-canvas/context.jsx +35 -0
  206. package/registry/blocks/flow-canvas/demo.jsx +249 -0
  207. package/registry/blocks/flow-canvas/edges.jsx +107 -0
  208. package/registry/blocks/flow-canvas/flow-canvas.jsx +1329 -0
  209. package/registry/blocks/flow-canvas/index.js +41 -0
  210. package/registry/blocks/flow-canvas/nodes.jsx +392 -0
  211. package/registry/blocks/flow-canvas/theme.js +174 -0
  212. package/registry/blocks/footer/README.md +133 -0
  213. package/registry/blocks/footer/block.json +11 -0
  214. package/registry/blocks/footer/demo.jsx +119 -0
  215. package/registry/blocks/footer/footer.jsx +406 -0
  216. package/registry/blocks/footer/index.js +4 -0
  217. package/registry/blocks/gantt/README.md +220 -0
  218. package/registry/blocks/gantt/block.json +10 -0
  219. package/registry/blocks/gantt/demo.jsx +148 -0
  220. package/registry/blocks/gantt/gantt.jsx +923 -0
  221. package/registry/blocks/gantt/index.js +7 -0
  222. package/registry/blocks/gantt/rows.jsx +468 -0
  223. package/registry/blocks/gantt/schedule.js +278 -0
  224. package/registry/blocks/job-panel/README.md +86 -2
  225. package/registry/blocks/job-panel/block.json +3 -3
  226. package/registry/blocks/job-panel/demo.jsx +230 -3
  227. package/registry/blocks/job-panel/job-panel.jsx +169 -3
  228. package/registry/blocks/json-editor/README.md +133 -0
  229. package/registry/blocks/json-editor/block.json +10 -0
  230. package/registry/blocks/json-editor/demo.jsx +92 -0
  231. package/registry/blocks/json-editor/index.js +7 -0
  232. package/registry/blocks/json-editor/json-editor.jsx +305 -0
  233. package/registry/blocks/json-editor/json-tree.jsx +393 -0
  234. package/registry/blocks/json-editor/tree.js +225 -0
  235. package/registry/blocks/map/README.md +221 -0
  236. package/registry/blocks/map/block.json +14 -0
  237. package/registry/blocks/map/demo.jsx +201 -0
  238. package/registry/blocks/map/geo.js +198 -0
  239. package/registry/blocks/map/index.js +8 -0
  240. package/registry/blocks/map/list.jsx +128 -0
  241. package/registry/blocks/map/map-view.jsx +715 -0
  242. package/registry/blocks/map/maplibre.js +30 -0
  243. package/registry/blocks/map/marks.jsx +146 -0
  244. package/registry/blocks/map/theme.js +142 -0
  245. package/registry/blocks/menubar/README.md +109 -0
  246. package/registry/blocks/menubar/block.json +10 -0
  247. package/registry/blocks/menubar/demo.jsx +128 -0
  248. package/registry/blocks/menubar/index.js +4 -0
  249. package/registry/blocks/menubar/menubar.jsx +199 -0
  250. package/registry/blocks/mind-map/README.md +206 -0
  251. package/registry/blocks/mind-map/block.json +10 -0
  252. package/registry/blocks/mind-map/demo.jsx +103 -0
  253. package/registry/blocks/mind-map/index.js +31 -0
  254. package/registry/blocks/mind-map/mind-map.jsx +1125 -0
  255. package/registry/blocks/mind-map/topic.jsx +143 -0
  256. package/registry/blocks/mind-map/tree.js +645 -0
  257. package/registry/blocks/navigation-menu/README.md +124 -0
  258. package/registry/blocks/navigation-menu/block.json +10 -0
  259. package/registry/blocks/navigation-menu/demo.jsx +84 -0
  260. package/registry/blocks/navigation-menu/index.js +4 -0
  261. package/registry/blocks/navigation-menu/navigation-menu.jsx +448 -0
  262. package/registry/blocks/order-detail/README.md +109 -0
  263. package/registry/blocks/order-detail/block.json +10 -0
  264. package/registry/blocks/order-detail/demo.jsx +88 -0
  265. package/registry/blocks/order-detail/index.js +4 -0
  266. package/registry/blocks/order-detail/order-detail.jsx +354 -0
  267. package/registry/blocks/org-chart/README.md +145 -0
  268. package/registry/blocks/org-chart/block.json +10 -0
  269. package/registry/blocks/org-chart/demo.jsx +94 -0
  270. package/registry/blocks/org-chart/index.js +7 -0
  271. package/registry/blocks/org-chart/org-chart.jsx +631 -0
  272. package/registry/blocks/org-chart/org.js +245 -0
  273. package/registry/blocks/org-chart/person.jsx +96 -0
  274. package/registry/blocks/page-builder/README.md +257 -0
  275. package/registry/blocks/page-builder/block.json +14 -0
  276. package/registry/blocks/page-builder/demo.jsx +145 -0
  277. package/registry/blocks/page-builder/grapes.js +18 -0
  278. package/registry/blocks/page-builder/index.js +11 -0
  279. package/registry/blocks/page-builder/page-builder.jsx +704 -0
  280. package/registry/blocks/page-builder/page-view.jsx +33 -0
  281. package/registry/blocks/page-builder/page.js +118 -0
  282. package/registry/blocks/page-builder/panels.jsx +588 -0
  283. package/registry/blocks/page-builder/sections.js +209 -0
  284. package/registry/blocks/page-builder/theme.js +87 -0
  285. package/registry/blocks/page-builder/thumbs.jsx +189 -0
  286. package/registry/blocks/page-builder/tokens.js +329 -0
  287. package/registry/blocks/payment-methods/README.md +104 -0
  288. package/registry/blocks/payment-methods/block.json +10 -0
  289. package/registry/blocks/payment-methods/demo.jsx +71 -0
  290. package/registry/blocks/payment-methods/index.js +4 -0
  291. package/registry/blocks/payment-methods/payment-methods.jsx +302 -0
  292. package/registry/blocks/pdf-document/README.md +213 -0
  293. package/registry/blocks/pdf-document/block.json +13 -0
  294. package/registry/blocks/pdf-document/demo.jsx +136 -0
  295. package/registry/blocks/pdf-document/index.js +33 -0
  296. package/registry/blocks/pdf-document/money.js +83 -0
  297. package/registry/blocks/pdf-document/pdf-document.jsx +144 -0
  298. package/registry/blocks/pdf-document/primitives.jsx +271 -0
  299. package/registry/blocks/pdf-document/quote.jsx +179 -0
  300. package/registry/blocks/pdf-document/theme.js +193 -0
  301. package/registry/blocks/pdf-viewer/README.md +191 -0
  302. package/registry/blocks/pdf-viewer/block.json +14 -0
  303. package/registry/blocks/pdf-viewer/demo.jsx +252 -0
  304. package/registry/blocks/pdf-viewer/helpers.js +270 -0
  305. package/registry/blocks/pdf-viewer/index.js +8 -0
  306. package/registry/blocks/pdf-viewer/notes.jsx +195 -0
  307. package/registry/blocks/pdf-viewer/pdf-viewer.jsx +1368 -0
  308. package/registry/blocks/pdf-viewer/pdfjs.js +37 -0
  309. package/registry/blocks/pdf-viewer/ssr-shim-end.js +6 -0
  310. package/registry/blocks/pdf-viewer/ssr-shim.js +44 -0
  311. package/registry/blocks/product-detail/README.md +217 -0
  312. package/registry/blocks/product-detail/block.json +10 -0
  313. package/registry/blocks/product-detail/demo.jsx +233 -0
  314. package/registry/blocks/product-detail/index.js +7 -0
  315. package/registry/blocks/product-detail/price.jsx +115 -0
  316. package/registry/blocks/product-detail/product-detail.jsx +348 -0
  317. package/registry/blocks/product-detail/product-media.jsx +102 -0
  318. package/registry/blocks/product-detail/product-options.jsx +144 -0
  319. package/registry/blocks/product-grid/README.md +162 -0
  320. package/registry/blocks/product-grid/block.json +10 -0
  321. package/registry/blocks/product-grid/demo.jsx +255 -0
  322. package/registry/blocks/product-grid/index.js +5 -0
  323. package/registry/blocks/product-grid/product-card.jsx +232 -0
  324. package/registry/blocks/product-grid/product-grid.jsx +235 -0
  325. package/registry/blocks/record-form/README.md +196 -0
  326. package/registry/blocks/record-form/block.json +10 -0
  327. package/registry/blocks/record-form/demo.jsx +525 -0
  328. package/registry/blocks/record-form/index.js +4 -0
  329. package/registry/blocks/record-form/record-fields.jsx +457 -0
  330. package/registry/blocks/record-form/record-form.jsx +415 -0
  331. package/registry/blocks/record-form/rules.js +81 -0
  332. package/registry/blocks/record-notes/README.md +139 -0
  333. package/registry/blocks/record-notes/block.json +10 -0
  334. package/registry/blocks/record-notes/demo.jsx +179 -0
  335. package/registry/blocks/record-notes/index.js +4 -0
  336. package/registry/blocks/record-notes/record-notes.jsx +266 -0
  337. package/registry/blocks/search-dialog/README.md +108 -0
  338. package/registry/blocks/search-dialog/block.json +10 -0
  339. package/registry/blocks/search-dialog/demo.jsx +116 -0
  340. package/registry/blocks/search-dialog/index.js +3 -0
  341. package/registry/blocks/search-dialog/search-dialog.jsx +235 -0
  342. package/registry/blocks/settings-list/README.md +171 -0
  343. package/registry/blocks/settings-list/block.json +10 -0
  344. package/registry/blocks/settings-list/demo.jsx +333 -0
  345. package/registry/blocks/settings-list/index.js +4 -0
  346. package/registry/blocks/settings-list/row-state.jsx +93 -0
  347. package/registry/blocks/settings-list/settings-list.jsx +349 -0
  348. package/registry/blocks/settings-list/settings-matrix.jsx +118 -0
  349. package/registry/blocks/setup-checklist/README.md +142 -0
  350. package/registry/blocks/setup-checklist/block.json +10 -0
  351. package/registry/blocks/setup-checklist/demo.jsx +159 -0
  352. package/registry/blocks/setup-checklist/index.js +4 -0
  353. package/registry/blocks/setup-checklist/setup-checklist.jsx +446 -0
  354. package/registry/blocks/share-dialog/README.md +113 -0
  355. package/registry/blocks/share-dialog/block.json +10 -0
  356. package/registry/blocks/share-dialog/demo.jsx +140 -0
  357. package/registry/blocks/share-dialog/index.js +3 -0
  358. package/registry/blocks/share-dialog/share-dialog.jsx +384 -0
  359. package/registry/blocks/sidebar/README.md +190 -0
  360. package/registry/blocks/sidebar/block.json +43 -0
  361. package/registry/blocks/sidebar/demo.jsx +577 -0
  362. package/registry/blocks/sidebar/index.js +4 -0
  363. package/registry/blocks/sidebar/sidebar-panel.jsx +149 -0
  364. package/registry/blocks/sidebar/sidebar.jsx +864 -0
  365. package/registry/blocks/signature-pad/README.md +137 -0
  366. package/registry/blocks/signature-pad/block.json +13 -0
  367. package/registry/blocks/signature-pad/colors.js +115 -0
  368. package/registry/blocks/signature-pad/demo.jsx +94 -0
  369. package/registry/blocks/signature-pad/index.js +6 -0
  370. package/registry/blocks/signature-pad/pad.js +7 -0
  371. package/registry/blocks/signature-pad/signature-pad.jsx +434 -0
  372. package/registry/blocks/signature-pad/signature.js +68 -0
  373. package/registry/blocks/sketch-canvas/README.md +280 -0
  374. package/registry/blocks/sketch-canvas/block.json +13 -0
  375. package/registry/blocks/sketch-canvas/demo.jsx +159 -0
  376. package/registry/blocks/sketch-canvas/excalidraw.js +40 -0
  377. package/registry/blocks/sketch-canvas/index.js +9 -0
  378. package/registry/blocks/sketch-canvas/palette.js +226 -0
  379. package/registry/blocks/sketch-canvas/sketch-canvas.jsx +1188 -0
  380. package/registry/blocks/sketch-canvas/sketch.js +179 -0
  381. package/registry/blocks/sketch-canvas/ssr-shim-end.js +6 -0
  382. package/registry/blocks/sketch-canvas/ssr-shim.js +45 -0
  383. package/registry/blocks/sketch-canvas/stamps.js +104 -0
  384. package/registry/blocks/sketch-canvas/theme.js +131 -0
  385. package/registry/blocks/spreadsheet/README.md +307 -0
  386. package/registry/blocks/spreadsheet/block.json +13 -0
  387. package/registry/blocks/spreadsheet/cells.jsx +455 -0
  388. package/registry/blocks/spreadsheet/chrome.jsx +325 -0
  389. package/registry/blocks/spreadsheet/demo.jsx +177 -0
  390. package/registry/blocks/spreadsheet/grid.js +387 -0
  391. package/registry/blocks/spreadsheet/index.js +34 -0
  392. package/registry/blocks/spreadsheet/spreadsheet.jsx +1732 -0
  393. package/registry/blocks/spreadsheet/types.js +473 -0
  394. package/registry/blocks/stat-cards/README.md +173 -0
  395. package/registry/blocks/stat-cards/block.json +10 -0
  396. package/registry/blocks/stat-cards/demo.jsx +257 -0
  397. package/registry/blocks/stat-cards/index.js +4 -0
  398. package/registry/blocks/stat-cards/stat-cards.jsx +307 -0
  399. package/registry/blocks/stat-cards/usage.jsx +243 -0
  400. package/registry/blocks/task-list/README.md +176 -0
  401. package/registry/blocks/task-list/block.json +10 -0
  402. package/registry/blocks/task-list/demo.jsx +134 -0
  403. package/registry/blocks/task-list/index.js +5 -0
  404. package/registry/blocks/task-list/task-list.jsx +907 -0
  405. package/registry/blocks/task-model/README.md +455 -0
  406. package/registry/blocks/task-model/block.json +167 -0
  407. package/registry/blocks/task-model/changes.js +89 -0
  408. package/registry/blocks/task-model/dates.js +371 -0
  409. package/registry/blocks/task-model/demo.jsx +215 -0
  410. package/registry/blocks/task-model/dnd.jsx +240 -0
  411. package/registry/blocks/task-model/index.js +97 -0
  412. package/registry/blocks/task-model/model.js +919 -0
  413. package/registry/blocks/task-model/parts.jsx +449 -0
  414. package/registry/blocks/task-model/toolbar.jsx +271 -0
  415. package/registry/blocks/testimonials/README.md +139 -0
  416. package/registry/blocks/testimonials/block.json +11 -0
  417. package/registry/blocks/testimonials/demo.jsx +137 -0
  418. package/registry/blocks/testimonials/index.js +4 -0
  419. package/registry/blocks/testimonials/testimonials.jsx +430 -0
  420. package/registry/blocks/transaction-list/README.md +126 -0
  421. package/registry/blocks/transaction-list/block.json +10 -0
  422. package/registry/blocks/transaction-list/demo.jsx +79 -0
  423. package/registry/blocks/transaction-list/index.js +4 -0
  424. package/registry/blocks/transaction-list/transaction-list.jsx +383 -0
  425. package/registry/blocks/whiteboard/README.md +179 -0
  426. package/registry/blocks/whiteboard/block.json +10 -0
  427. package/registry/blocks/whiteboard/demo.jsx +169 -0
  428. package/registry/blocks/whiteboard/index.js +6 -0
  429. package/registry/blocks/whiteboard/templates.js +150 -0
  430. package/registry/blocks/whiteboard/whiteboard.jsx +721 -0
  431. package/src/install.mjs +18 -0
  432. package/src/shadcn.mjs +171 -0
  433. package/templates/next/files/README.md +145 -11
  434. package/templates/next/files/app/globals.css +55 -4
  435. package/templates/next/files/check/run.mjs +3 -3
  436. package/templates/next/files/components/parts/fixture.jsx +1 -1
  437. package/templates/next/files/components/parts/sample.js +15 -0
  438. package/templates/next/files/components/ui/avatar.jsx +141 -0
  439. package/templates/next/files/components/ui/breadcrumb.jsx +149 -0
  440. package/templates/next/files/components/ui/button-group.jsx +70 -0
  441. package/templates/next/files/components/ui/button.jsx +132 -12
  442. package/templates/next/files/components/ui/calendar.jsx +609 -0
  443. package/templates/next/files/components/ui/carousel.jsx +281 -0
  444. package/templates/next/files/components/ui/collapsible.jsx +208 -0
  445. package/templates/next/files/components/ui/combobox.jsx +608 -0
  446. package/templates/next/files/components/ui/command.jsx +577 -0
  447. package/templates/next/files/components/ui/context-menu.jsx +191 -0
  448. package/templates/next/files/components/ui/date-picker.jsx +360 -0
  449. package/templates/next/files/components/ui/distribution.jsx +117 -0
  450. package/templates/next/files/components/ui/feedback.jsx +143 -0
  451. package/templates/next/files/components/ui/field.jsx +115 -3
  452. package/templates/next/files/components/ui/file-input.jsx +234 -0
  453. package/templates/next/files/components/ui/icon.jsx +130 -8
  454. package/templates/next/files/components/ui/image.jsx +143 -0
  455. package/templates/next/files/components/ui/index.js +47 -2
  456. package/templates/next/files/components/ui/input-group.jsx +213 -0
  457. package/templates/next/files/components/ui/input-otp.jsx +170 -0
  458. package/templates/next/files/components/ui/item.jsx +206 -0
  459. package/templates/next/files/components/ui/menu.jsx +454 -82
  460. package/templates/next/files/components/ui/notice.jsx +126 -14
  461. package/templates/next/files/components/ui/pagination.jsx +156 -0
  462. package/templates/next/files/components/ui/popover.jsx +284 -0
  463. package/templates/next/files/components/ui/radio.jsx +193 -0
  464. package/templates/next/files/components/ui/rating.jsx +131 -0
  465. package/templates/next/files/components/ui/resizable.jsx +338 -0
  466. package/templates/next/files/components/ui/scroll-area.jsx +123 -0
  467. package/templates/next/files/components/ui/separator.jsx +119 -0
  468. package/templates/next/files/components/ui/sheet.jsx +96 -11
  469. package/templates/next/files/components/ui/slider.jsx +174 -0
  470. package/templates/next/files/components/ui/stat.jsx +574 -0
  471. package/templates/next/files/components/ui/steps.jsx +338 -0
  472. package/templates/next/files/components/ui/swatch.jsx +33 -0
  473. package/templates/next/files/components/ui/table.jsx +130 -0
  474. package/templates/next/files/components/ui/toast.jsx +440 -0
  475. package/templates/next/files/components/ui/toggle.jsx +195 -0
  476. package/templates/next/files/components/ui/tooltip.jsx +270 -0
  477. package/templates/next/files/lib/sample.js +4 -12
  478. package/templates/next/template.json +264 -8
@@ -0,0 +1,442 @@
1
+ // The calendar's arithmetic — pure, no React. Where a task sits on a
2
+ // calendar (a timed block on one day, or an all-day span), how
3
+ // overlapping blocks share a column, how spans stack into lanes, the
4
+ // patches a move or a resize saves, the window each mode shows, and the
5
+ // available-time layer (working hours, open slots) booking-page builds
6
+ // on. Dates are task-model's wall-calendar strings; minutes are minutes
7
+ // after midnight.
8
+
9
+ import {
10
+ addDays,
11
+ addMonths,
12
+ dayNumber,
13
+ dayOf,
14
+ diffDays,
15
+ formatDate,
16
+ formatTime,
17
+ minutesOf,
18
+ monthGrid,
19
+ shiftDates,
20
+ spanOf,
21
+ startOfWeek,
22
+ weekdayOf,
23
+ withTime,
24
+ } from "../task-model";
25
+
26
+ export const DAY_MINUTES = 1440;
27
+ export const CALENDAR_MODES = ["month", "week", "day", "agenda"];
28
+ export const MODE_LABELS = { month: "Month", week: "Week", day: "Day", agenda: "Agenda" };
29
+
30
+ const clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
31
+
32
+ /** Rounds minutes to the nearest `step` (default 15). */
33
+ export function snapMinutes(minutes, step = 15) {
34
+ return Math.round(minutes / step) * step;
35
+ }
36
+
37
+ /** How long a timed block runs when the task says only when it starts:
38
+ * its estimate (hours), else `fallback` minutes. */
39
+ export function durationOf(task, fallback = 60) {
40
+ const est = Number(task?.estimate);
41
+ return est > 0 ? clamp(Math.round(est * 60), 15, 8 * 60) : fallback;
42
+ }
43
+
44
+ /**
45
+ * Where a task sits on a calendar, or null when it has no date.
46
+ * { id, task, timed, start, end, from, to, deadline, startOnly }
47
+ * `start` / `end` are days (inclusive). A timed item lives on one day
48
+ * (`start === end`) from `from` to `to` minutes: a start and a due time
49
+ * on the same day; a start time alone (runs its estimate, else an hour);
50
+ * or a due time alone (a `deadline`: a half-hour block at the due time).
51
+ * Anything else — plain days, or a span over several days — is all-day.
52
+ */
53
+ export function eventOf(task, { defaultMinutes = 60 } = {}) {
54
+ const span = spanOf(task);
55
+ if (!span) return null;
56
+ const base = { id: String(task.id), task, start: span.start, end: span.end, timed: false, from: null, to: null, deadline: false, startOnly: false };
57
+ if (span.start !== span.end) return base;
58
+ const sDay = dayOf(task.start);
59
+ const dDay = dayOf(task.due);
60
+ const sm = sDay ? minutesOf(task.start) : null;
61
+ const dm = dDay ? minutesOf(task.due) : null;
62
+ if (sm === null && dm === null) return base;
63
+ let from;
64
+ let to;
65
+ let deadline = false;
66
+ let startOnly = false;
67
+ if (sm !== null && dm !== null && dm > sm) [from, to] = [sm, dm];
68
+ else if (sm !== null) {
69
+ from = sm;
70
+ to = sm + durationOf(task, defaultMinutes);
71
+ startOnly = !dDay;
72
+ } else {
73
+ from = dm;
74
+ to = dm + 30;
75
+ deadline = true;
76
+ }
77
+ from = clamp(from, 0, DAY_MINUTES - 15);
78
+ to = clamp(to, from + 15, DAY_MINUTES);
79
+ return { ...base, timed: true, from, to, deadline, startOnly };
80
+ }
81
+
82
+ /** Every dated task as an event (in the order given). */
83
+ export function eventsOf(tasks, options) {
84
+ const out = [];
85
+ for (const t of tasks ?? []) {
86
+ const e = eventOf(t, options);
87
+ if (e) out.push(e);
88
+ }
89
+ return out;
90
+ }
91
+
92
+ /** Tasks with neither a start nor a due date: the unscheduled tray. */
93
+ export function unscheduledOf(tasks) {
94
+ return (tasks ?? []).filter((t) => !spanOf(t));
95
+ }
96
+
97
+ /**
98
+ * Side-by-side columns for the timed events of one day, the way Google
99
+ * Calendar lays a busy morning: events that overlap (directly or through
100
+ * a chain) share a cluster; each takes the first column free at its
101
+ * start; a block widens over the columns to its right that stay free for
102
+ * its whole run. Returns Map id → { col, cols, span }. `minMinutes` is
103
+ * the shortest block drawn (short ones still need room for a title).
104
+ */
105
+ export function layoutTimed(events, { minMinutes = 20 } = {}) {
106
+ const list = [...events]
107
+ .filter((e) => e.timed)
108
+ .map((e) => ({ e, a: e.from, b: Math.max(e.to, e.from + minMinutes) }))
109
+ .sort((x, y) => x.a - y.a || y.b - x.b || String(x.e.task.title).localeCompare(String(y.e.task.title)));
110
+ const out = new Map();
111
+ let cluster = [];
112
+ let clusterEnd = -1;
113
+ const flush = () => {
114
+ if (!cluster.length) return;
115
+ const cols = Math.max(...cluster.map((c) => c.col)) + 1;
116
+ for (const c of cluster) {
117
+ let span = 1;
118
+ for (let k = c.col + 1; k < cols; k++) {
119
+ if (cluster.some((o) => o.col === k && o.a < c.b && c.a < o.b)) break;
120
+ span++;
121
+ }
122
+ out.set(c.e.id, { col: c.col, cols, span });
123
+ }
124
+ cluster = [];
125
+ clusterEnd = -1;
126
+ };
127
+ let ends = [];
128
+ for (const item of list) {
129
+ if (item.a >= clusterEnd) {
130
+ flush();
131
+ ends = [];
132
+ }
133
+ let col = ends.findIndex((end) => end <= item.a);
134
+ if (col < 0) col = ends.length;
135
+ ends[col] = item.b;
136
+ cluster.push({ ...item, col });
137
+ clusterEnd = Math.max(clusterEnd, item.b);
138
+ }
139
+ flush();
140
+ return out;
141
+ }
142
+
143
+ /**
144
+ * Spans stacked into lanes across a row of days (a month week, a week's
145
+ * all-day strip): longest first among those starting together, each in
146
+ * the first lane free for its days. Returns { items: [{ event, lane, col,
147
+ * span, clippedStart, clippedEnd }], lanes } — `col` / `span` in days
148
+ * from the row's first; `clipped*` when it runs past the row's ends.
149
+ */
150
+ export function layoutLanes(events, days) {
151
+ const n = days.length;
152
+ if (!n) return { items: [], lanes: 0 };
153
+ const first = days[0];
154
+ const last = days[n - 1];
155
+ const list = events
156
+ .filter((e) => e.start <= last && e.end >= first)
157
+ .map((e) => {
158
+ const a = Math.max(0, diffDays(first, e.start));
159
+ const b = Math.min(n - 1, diffDays(first, e.end));
160
+ return { event: e, col: a, span: b - a + 1, clippedStart: e.start < first, clippedEnd: e.end > last };
161
+ })
162
+ .sort(
163
+ (x, y) =>
164
+ x.col - y.col ||
165
+ y.span - x.span ||
166
+ Number(x.event.timed) - Number(y.event.timed) ||
167
+ (x.event.from ?? -1) - (y.event.from ?? -1) ||
168
+ String(x.event.task.title).localeCompare(String(y.event.task.title)),
169
+ );
170
+ const lanes = [];
171
+ const items = [];
172
+ for (const it of list) {
173
+ let lane = lanes.findIndex((cells) => !cells.some((c) => c >= it.col && c < it.col + it.span));
174
+ if (lane < 0) {
175
+ lane = lanes.length;
176
+ lanes.push([]);
177
+ }
178
+ for (let k = it.col; k < it.col + it.span; k++) lanes[lane].push(k);
179
+ items.push({ ...it, lane });
180
+ }
181
+ return { items, lanes: lanes.length };
182
+ }
183
+
184
+ // ---- the patches a gesture saves -----------------------------------------
185
+
186
+ /** A timed event moved to `day` at `from` minutes, keeping its length. */
187
+ export function moveEventPatch(event, day, from) {
188
+ const len = event.to - event.from;
189
+ const a = clamp(snapMinutes(from, 1), 0, DAY_MINUTES - len);
190
+ if (event.deadline) return { due: withTime(day, a) };
191
+ if (event.startOnly) return { start: withTime(day, a) };
192
+ return { start: withTime(day, a), due: withTime(day, a + len) };
193
+ }
194
+
195
+ /** A timed event's end dragged to `to` minutes (at least 15 after it
196
+ * starts). A deadline or a start-only task becomes a start–due block. */
197
+ export function resizeEventPatch(event, to) {
198
+ const b = clamp(to, event.from + 15, DAY_MINUTES);
199
+ if (event.deadline || event.startOnly) return { start: withTime(event.start, event.from), due: withTime(event.start, b) };
200
+ return { due: withTime(event.start, b) };
201
+ }
202
+
203
+ /** A timed event given a new day and a new [from, to] (a keyboard nudge
204
+ * that may move and resize at once). */
205
+ export function placeEventPatch(event, day, from, to) {
206
+ if (to - from === event.to - event.from) return moveEventPatch(event, day, from);
207
+ const a = clamp(from, 0, DAY_MINUTES - 15);
208
+ const b = clamp(to, a + 15, DAY_MINUTES);
209
+ return { start: withTime(day, a), due: withTime(day, b) };
210
+ }
211
+
212
+ /** A task put on the time grid (from all-day, from the tray): a block
213
+ * of `minutes` from `from`. */
214
+ export function timedPatch(day, from, minutes = 60) {
215
+ const a = clamp(from, 0, DAY_MINUTES - 15);
216
+ return { start: withTime(day, a), due: withTime(day, Math.min(DAY_MINUTES, a + minutes)) };
217
+ }
218
+
219
+ /** A task dropped on a day (a month cell, the all-day strip). An all-day
220
+ * span moves whole (by the days between where it was grabbed and where
221
+ * it landed); a timed one keeps its times on the new day; an
222
+ * unscheduled one gets that day as its due date. */
223
+ export function dayPatch(task, day, { grabbed } = {}) {
224
+ const e = eventOf(task);
225
+ if (!e) return { due: day };
226
+ const shift = diffDays(grabbed ?? e.start, day);
227
+ return shift ? shiftDates(task, shift) : null;
228
+ }
229
+
230
+ /** A timed task made all-day on `day` (dropped on the all-day strip). */
231
+ export function allDayPatch(day) {
232
+ return { start: null, due: day };
233
+ }
234
+
235
+ /** An all-day span's last day dragged to `end` (never before it starts). */
236
+ export function extendPatch(event, end) {
237
+ const e = end < event.start ? event.start : end;
238
+ const task = event.task;
239
+ if (e === event.start && !dayOf(task.start)) return { due: withTime(e, minutesOf(task.due)) };
240
+ return { start: withTime(event.start, minutesOf(task.start)), due: withTime(e, minutesOf(task.due)) };
241
+ }
242
+
243
+ /** Takes a task off the calendar (dropped on the unscheduled tray). */
244
+ export const UNSCHEDULE = Object.freeze({ start: null, due: null });
245
+
246
+ // ---- what each mode shows ------------------------------------------------
247
+
248
+ /**
249
+ * The days a mode shows around `anchor`: { from, to, days, weeks? }.
250
+ * month the weeks that hold the anchor's month (4–6 rows)
251
+ * week the anchor's week, or `count` days from the anchor (a phone's
252
+ * three-day week)
253
+ * day the anchor
254
+ * agenda `agendaDays` days from the anchor
255
+ */
256
+ export function rangeFor(mode, anchor, { weekStartsOn = 1, count = 7, agendaDays = 14 } = {}) {
257
+ const a = dayOf(anchor);
258
+ if (mode === "month") {
259
+ const weeks = monthGrid(a, { weekStartsOn });
260
+ return { from: weeks[0][0], to: weeks[weeks.length - 1][6], days: weeks.flat(), weeks };
261
+ }
262
+ if (mode === "week") {
263
+ const from = count >= 7 ? startOfWeek(a, weekStartsOn) : a;
264
+ const days = Array.from({ length: count >= 7 ? 7 : count }, (_, i) => addDays(from, i));
265
+ return { from: days[0], to: days[days.length - 1], days };
266
+ }
267
+ if (mode === "agenda") {
268
+ const days = Array.from({ length: agendaDays }, (_, i) => addDays(a, i));
269
+ return { from: days[0], to: days[days.length - 1], days };
270
+ }
271
+ return { from: a, to: a, days: [a] };
272
+ }
273
+
274
+ /** The anchor one step back (dir −1) or on (+1) in a mode. */
275
+ export function stepAnchor(mode, anchor, dir, { count = 7, agendaDays = 14 } = {}) {
276
+ if (mode === "month") return addMonths(anchor, dir);
277
+ if (mode === "week") return addDays(anchor, dir * (count >= 7 ? 7 : count));
278
+ if (mode === "agenda") return addDays(anchor, dir * agendaDays);
279
+ return addDays(anchor, dir);
280
+ }
281
+
282
+ /** A range in words: "Sep 21 – 27, 2026", "Sep 28 – Oct 4, 2026",
283
+ * "Dec 29, 2026 – Jan 4, 2027". */
284
+ export function rangeLabel(from, to, { locale } = {}) {
285
+ if (from === to) return formatDate(from, { month: "short", day: "numeric", year: "numeric" }, { locale });
286
+ const sameYear = from.slice(0, 4) === to.slice(0, 4);
287
+ const sameMonth = sameYear && from.slice(5, 7) === to.slice(5, 7);
288
+ const a = formatDate(from, sameYear ? { month: "short", day: "numeric" } : { month: "short", day: "numeric", year: "numeric" }, { locale });
289
+ const b = formatDate(to, sameMonth ? { day: "numeric" } : { month: "short", day: "numeric" }, { locale });
290
+ return `${a} – ${b}, ${to.slice(0, 4)}`;
291
+ }
292
+
293
+ /** The heading a mode shows: "September 2026", a week's range, "Wednesday,
294
+ * September 23" (with the year when it is not `today`'s). */
295
+ export function titleFor(mode, range, anchor, { today, locale } = {}) {
296
+ if (mode === "month") return formatDate(anchor, { month: "long", year: "numeric" }, { locale });
297
+ if (mode === "day") {
298
+ const sameYear = !today || anchor.slice(0, 4) === today.slice(0, 4);
299
+ return formatDate(anchor, sameYear ? { weekday: "long", month: "long", day: "numeric" } : { weekday: "long", month: "long", day: "numeric", year: "numeric" }, { locale });
300
+ }
301
+ return rangeLabel(range.from, range.to, { locale });
302
+ }
303
+
304
+ /** "9 AM" / "21" — an hour on the grid's gutter. */
305
+ export function hourLabel(hour, { locale } = {}) {
306
+ return new Intl.DateTimeFormat(locale, { hour: "numeric", timeZone: "UTC" }).format(new Date(hour * 3600000));
307
+ }
308
+
309
+ /** "9:30 AM" for minutes after midnight. */
310
+ export function minutesLabel(minutes, { locale } = {}) {
311
+ return formatTime(withTime("2000-01-01", Math.min(minutes, DAY_MINUTES - 1)), { locale });
312
+ }
313
+
314
+ /** "9:30 – 11:00 AM"-ish words for a timed event, "All day", or "Due
315
+ * 5:00 PM" for a deadline. */
316
+ export function eventTimeLabel(event, { locale } = {}) {
317
+ if (!event?.timed) return "All day";
318
+ if (event.deadline) return `Due ${minutesLabel(event.from, { locale })}`;
319
+ return `${minutesLabel(event.from, { locale })} – ${minutesLabel(event.to, { locale })}`;
320
+ }
321
+
322
+ // ---- the available-time layer --------------------------------------------
323
+
324
+ const HHMM = /^(\d{1,2}):(\d{2})$/;
325
+ const toMin = (v) => {
326
+ if (typeof v === "number") return v;
327
+ const m = HHMM.exec(String(v ?? ""));
328
+ return m ? +m[1] * 60 + +m[2] : null;
329
+ };
330
+
331
+ function intervals(list) {
332
+ return (list ?? [])
333
+ .map((r) => (Array.isArray(r) ? [toMin(r[0]), toMin(r[1])] : [toMin(r?.from), toMin(r?.to)]))
334
+ .filter(([a, b]) => a !== null && b !== null && b > a)
335
+ .map(([a, b]) => [clamp(a, 0, DAY_MINUTES), clamp(b, 0, DAY_MINUTES)])
336
+ .sort((x, y) => x[0] - y[0]);
337
+ }
338
+
339
+ /**
340
+ * The open hours on a day, as [[from, to], …] minutes. `availability` is
341
+ * { days: [1,2,3,4,5], from: "09:00", to: "17:00" } the simple week
342
+ * { weekly: { 1: [["09:00","12:00"], ["13:00","17:00"]], … } } per weekday (0 Sunday)
343
+ * …either, plus dates: { "2026-12-24": [["09:00","12:00"]], "2026-12-25": [] }
344
+ * or a function (day) → [[from, to], …]
345
+ * Nothing given → the whole day is open.
346
+ */
347
+ export function availabilityOn(day, availability) {
348
+ if (!availability) return [[0, DAY_MINUTES]];
349
+ if (typeof availability === "function") return intervals(availability(day));
350
+ const d = dayOf(day);
351
+ if (availability.dates && Object.hasOwn(availability.dates, d)) return intervals(availability.dates[d]);
352
+ const wd = weekdayOf(d);
353
+ if (availability.weekly) return intervals(availability.weekly[wd] ?? availability.weekly[String(wd)]);
354
+ const days = availability.days ?? [1, 2, 3, 4, 5];
355
+ if (!days.includes(wd)) return [];
356
+ return intervals([[availability.from ?? "09:00", availability.to ?? "17:00"]]);
357
+ }
358
+
359
+ /** The closed stretches of a day: the complement of availabilityOn. */
360
+ export function closedOn(day, availability) {
361
+ const open = availabilityOn(day, availability);
362
+ const out = [];
363
+ let cursor = 0;
364
+ for (const [a, b] of open) {
365
+ if (a > cursor) out.push([cursor, a]);
366
+ cursor = Math.max(cursor, b);
367
+ }
368
+ if (cursor < DAY_MINUTES) out.push([cursor, DAY_MINUTES]);
369
+ return out;
370
+ }
371
+
372
+ function busyIntervals(busy, day, buffer) {
373
+ const out = [];
374
+ for (const b of busy ?? []) {
375
+ let a;
376
+ let z;
377
+ if (b && Object.hasOwn(b, "end")) {
378
+ // an interval { start, end } (a booking, a meeting)
379
+ const sd = dayOf(b.start);
380
+ const ed = dayOf(b.end);
381
+ if (!sd || !ed || sd > day || ed < day) continue;
382
+ a = sd < day ? 0 : minutesOf(b.start) ?? 0;
383
+ z = ed > day ? DAY_MINUTES : minutesOf(b.end) ?? DAY_MINUTES;
384
+ } else {
385
+ // a task: only a timed block takes time; an all-day date does not
386
+ const e = eventOf(b);
387
+ if (!e?.timed || e.start !== day) continue;
388
+ a = e.from;
389
+ z = e.to;
390
+ }
391
+ out.push([a - buffer, z + buffer]);
392
+ }
393
+ return out;
394
+ }
395
+
396
+ /**
397
+ * Open slots between two days — what a booking page offers, and what a
398
+ * calendar's `getSlots` can return as is:
399
+ * freeSlots({ from, to, availability, busy, minutes: 30, step, buffer, notice, now })
400
+ * → [{ id, day, start: "2026-09-24T09:00", end: "2026-09-24T09:30", from: 540, to: 570 }]
401
+ * `busy` mixes tasks (their timed blocks) and { start, end } intervals;
402
+ * `buffer` minutes are kept free around each; `step` is how far apart
403
+ * slots start (default `minutes`); nothing starts before `now` plus
404
+ * `notice` minutes (`now` a "YYYY-MM-DDTHH:mm" string).
405
+ */
406
+ export function freeSlots({ from, to, availability, busy = [], minutes = 30, step, buffer = 0, notice = 0, now } = {}) {
407
+ const a = dayNumber(from);
408
+ const z = dayNumber(to ?? from);
409
+ if (a === null || z === null) return [];
410
+ const inc = step > 0 ? step : minutes;
411
+ const nowDay = dayOf(now);
412
+ const earliest = nowDay ? (minutesOf(now) ?? 0) + notice : null;
413
+ const out = [];
414
+ for (let n = a; n <= z && out.length < 5000; n++) {
415
+ const day = addDays(from, n - a);
416
+ if (nowDay && day < nowDay) continue;
417
+ const taken = busyIntervals(busy, day, buffer);
418
+ for (const [open, close] of availabilityOn(day, availability)) {
419
+ for (let s = open; s + minutes <= close; s += inc) {
420
+ const e = s + minutes;
421
+ if (nowDay && day === nowDay && s < earliest) continue;
422
+ if (taken.some(([x, y]) => s < y && x < e)) continue;
423
+ out.push({ id: `${day}T${s}`, day, start: withTime(day, s), end: withTime(day, Math.min(e, DAY_MINUTES - 1)), from: s, to: e });
424
+ }
425
+ }
426
+ }
427
+ return out;
428
+ }
429
+
430
+ /** A slot list (from `slots` or `getSlots`) normalised to the shape the
431
+ * grid draws: { id, day, from, to, start, end, …yours }. */
432
+ export function normalizeSlots(slots) {
433
+ const out = [];
434
+ for (const s of slots ?? []) {
435
+ const day = s.day ?? dayOf(s.start);
436
+ const from = s.from ?? minutesOf(s.start);
437
+ const to = s.to ?? minutesOf(s.end) ?? (from !== null ? from + 30 : null);
438
+ if (!day || from === null || to === null) continue;
439
+ out.push({ ...s, id: String(s.id ?? `${day}T${from}`), day, from, to, start: s.start ?? withTime(day, from), end: s.end ?? withTime(day, to) });
440
+ }
441
+ return out;
442
+ }