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,193 @@
1
+ "use client";
2
+
3
+ import { createContext, useContext, useEffect, useId, useState } from "react";
4
+ import { cx } from "./cx";
5
+ import { Icon } from "./icon";
6
+
7
+ // RadioGroup — one choice out of a few, all of them visible. Real
8
+ // <input type="radio"> sharing one name, so the browser supplies the
9
+ // behaviour: arrow keys move AND select, Tab enters at the checked one,
10
+ // forms submit the value. Options as data (`options`) or as <Radio>
11
+ // children. Controlled (`value` + `onChange(value)`) or not (`defaultValue`).
12
+ //
13
+ // options [{ value, label, description?, icon?, disabled? }]
14
+ // variant list (a dot beside each label; the default) · card (each
15
+ // option a selectable card — plans, templates, modes)
16
+ // orientation vertical (the default) · horizontal (wraps; cards stack
17
+ // on a narrow window and share the row from sm up)
18
+ // size md (44px rows) · sm (36px, dense rails); list only
19
+ // invalid marks every option; <Field error> sets the text
20
+ //
21
+ // In a <Field id="x" label hint error>, give the group the same `id`: a
22
+ // <label> cannot name a group, so the group borrows Field's label (and
23
+ // its hint or error) by aria-labelledby / aria-describedby. More than
24
+ // ~6 options, or options that are records: a <Select>.
25
+
26
+ const Group = createContext(null);
27
+
28
+ const ROW = {
29
+ md: "min-h-11 py-3",
30
+ sm: "min-h-9 py-2",
31
+ };
32
+
33
+ export function RadioGroup({
34
+ id,
35
+ name,
36
+ value,
37
+ defaultValue,
38
+ onChange,
39
+ options,
40
+ variant = "list",
41
+ orientation = "vertical",
42
+ size = "md",
43
+ invalid,
44
+ disabled,
45
+ required,
46
+ className,
47
+ children,
48
+ "aria-label": ariaLabel,
49
+ "aria-labelledby": ariaLabelledby,
50
+ }) {
51
+ const auto = useId();
52
+ const [own, setOwn] = useState(defaultValue);
53
+ const [named, setNamed] = useState({});
54
+ const current = value !== undefined ? value : own;
55
+
56
+ // Field's label and hint point at `id`; wire them to the group.
57
+ useEffect(() => {
58
+ if (!id || typeof document === "undefined") return;
59
+ const label = document.querySelector(`label[for="${CSS.escape(id)}"]`);
60
+ const note = document.getElementById(`${id}-error`) ?? document.getElementById(`${id}-hint`);
61
+ if (label && !label.id) label.id = `${id}-label`;
62
+ setNamed({ labelledby: label?.id, describedby: note?.id });
63
+ if (!label) return;
64
+ // Clicking the label lands on the group, as it would on an input.
65
+ const focus = () => {
66
+ const box = document.getElementById(id);
67
+ (box?.querySelector("input:checked:not(:disabled)") ?? box?.querySelector("input:not(:disabled)"))?.focus();
68
+ };
69
+ label.addEventListener("click", focus);
70
+ return () => label.removeEventListener("click", focus);
71
+ }, [id, invalid]);
72
+
73
+ const ctx = {
74
+ name: name ?? id ?? auto,
75
+ current,
76
+ variant,
77
+ size,
78
+ invalid,
79
+ disabled,
80
+ required,
81
+ select(next) {
82
+ if (value === undefined) setOwn(next);
83
+ onChange?.(next);
84
+ },
85
+ };
86
+
87
+ const card = variant === "card";
88
+ return (
89
+ <Group.Provider value={ctx}>
90
+ <div
91
+ id={id}
92
+ role="radiogroup"
93
+ aria-label={ariaLabel}
94
+ aria-labelledby={ariaLabel ? undefined : ariaLabelledby ?? named.labelledby}
95
+ aria-describedby={named.describedby}
96
+ aria-invalid={invalid ? true : undefined}
97
+ aria-required={required ? true : undefined}
98
+ aria-orientation={orientation}
99
+ className={cx(
100
+ card
101
+ ? orientation === "horizontal"
102
+ ? "grid gap-3 sm:auto-cols-fr sm:grid-flow-col"
103
+ : "grid gap-3"
104
+ : orientation === "horizontal"
105
+ ? "flex flex-wrap gap-x-6"
106
+ : "grid",
107
+ className,
108
+ )}
109
+ >
110
+ {options ? options.map((o) => <Radio key={o.value} {...o} />) : children}
111
+ </div>
112
+ </Group.Provider>
113
+ );
114
+ }
115
+
116
+ /** One option; only inside a <RadioGroup>. */
117
+ export function Radio({ value, label, description, icon, disabled, className }) {
118
+ const g = useContext(Group);
119
+ const auto = useId();
120
+ if (!g) return null;
121
+ const off = g.disabled || disabled;
122
+ const inputId = `${g.name}-${auto}`;
123
+ const card = g.variant === "card";
124
+
125
+ const dot = (
126
+ <span className="relative mt-0.5 flex h-4 w-4 shrink-0">
127
+ <input
128
+ id={inputId}
129
+ type="radio"
130
+ name={g.name}
131
+ value={value}
132
+ checked={g.current === value}
133
+ onChange={() => g.select(value)}
134
+ disabled={off}
135
+ required={g.required}
136
+ aria-describedby={description ? `${inputId}-d` : undefined}
137
+ className={cx(
138
+ "peer h-4 w-4 appearance-none rounded-full border bg-background outline-none transition-colors checked:border-primary disabled:cursor-not-allowed",
139
+ g.invalid ? "border-destructive" : "border-input",
140
+ !card && "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
141
+ )}
142
+ />
143
+ <span aria-hidden="true" className="pointer-events-none absolute inset-0 m-auto h-2 w-2 scale-0 rounded-full bg-primary transition-transform peer-checked:scale-100" />
144
+ </span>
145
+ );
146
+
147
+ const text = (
148
+ <span className="grid min-w-0 flex-1 gap-0.5">
149
+ <span className={cx("leading-5 text-foreground", card && "font-medium")}>{label ?? value}</span>
150
+ {description ? (
151
+ <span id={`${inputId}-d`} className="text-sm leading-5 text-muted-foreground">
152
+ {description}
153
+ </span>
154
+ ) : null}
155
+ </span>
156
+ );
157
+
158
+ if (card) {
159
+ return (
160
+ <label
161
+ htmlFor={inputId}
162
+ className={cx(
163
+ "flex min-h-11 cursor-pointer items-start gap-3 rounded-lg border bg-card p-4 text-sm text-card-foreground transition-colors",
164
+ "hover:bg-accent/50 has-[:checked]:bg-accent/50 has-[:checked]:ring-1",
165
+ g.invalid ? "border-destructive has-[:checked]:ring-destructive" : "border-border has-[:checked]:border-primary has-[:checked]:ring-primary",
166
+ "has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-ring",
167
+ off && "cursor-not-allowed opacity-50 hover:bg-card",
168
+ className,
169
+ )}
170
+ >
171
+ {icon ? <Icon name={icon} size={18} className="mt-px shrink-0 text-muted-foreground" /> : null}
172
+ {text}
173
+ {dot}
174
+ </label>
175
+ );
176
+ }
177
+
178
+ return (
179
+ <label
180
+ htmlFor={inputId}
181
+ className={cx(
182
+ "flex cursor-pointer items-start gap-3 text-sm",
183
+ ROW[g.size] ?? ROW.md,
184
+ off && "cursor-not-allowed opacity-50",
185
+ className,
186
+ )}
187
+ >
188
+ {dot}
189
+ {icon ? <Icon name={icon} className="mt-0.5 shrink-0 text-muted-foreground" /> : null}
190
+ {text}
191
+ </label>
192
+ );
193
+ }
@@ -0,0 +1,131 @@
1
+ "use client";
2
+
3
+ import { useId, useState } from "react";
4
+ import { cx } from "./cx";
5
+
6
+ // Rating — stars. Read-only it shows a score (4.5 of 5, halves drawn);
7
+ // with `onChange` it is an input: a native radio group underneath, one
8
+ // radio per star, so arrow keys, Tab, forms and screen readers are the
9
+ // browser's. The stars are drawn from tokens: filled in `text-primary`,
10
+ // empty in the border colour. Never a colour prop.
11
+ //
12
+ // value the score: a number from 0 to `max`. Read-only it may be
13
+ // fractional (shown to the nearest half, read to one decimal);
14
+ // as an input it is a whole number (0 = none chosen yet)
15
+ // max how many stars (5)
16
+ // onChange (n) → the chosen whole number; not an event. Present = input
17
+ // readOnly true: show it, even when onChange is passed
18
+ // size sm (16px stars) · md (20px stars; as an input each star is a
19
+ // 44px target)
20
+ // label what is rated ("Support quality"); a reader hears
21
+ // "Support quality, 4.5 out of 5". Without it: "4.5 out of 5"
22
+ // name the form field the input submits under
23
+ // disabled the input, greyed and still
24
+ //
25
+ // A reader hears the number, never "star star star": the read-only row is
26
+ // one image named "4.5 out of 5", and each radio is named "3 out of 5".
27
+
28
+ const STAR = "m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3 6.4 20.2l1.1-6.2L3 9.6l6.2-.9L12 3Z";
29
+
30
+ const PX = { sm: 16, md: 20 };
31
+ // Each star's box as an input: 44px at md, the thumb's target.
32
+ const TARGET = { sm: "size-8", md: "size-11" };
33
+
34
+ function Star({ size, className }) {
35
+ return (
36
+ <svg
37
+ width={size}
38
+ height={size}
39
+ viewBox="0 0 24 24"
40
+ fill="currentColor"
41
+ stroke="currentColor"
42
+ strokeWidth="1.8"
43
+ strokeLinejoin="round"
44
+ aria-hidden="true"
45
+ className={cx("block shrink-0", className)}
46
+ >
47
+ <path d={STAR} />
48
+ </svg>
49
+ );
50
+ }
51
+
52
+ // One star filled by `part` (0, 0.5 or 1): an empty star with the filled
53
+ // one laid over it, cut to that width from the start edge.
54
+ function PartStar({ part, size }) {
55
+ return (
56
+ <span className="relative block shrink-0" style={{ width: size, height: size }}>
57
+ <Star size={size} className="text-border" />
58
+ {part > 0 ? (
59
+ <span className="absolute inset-y-0 start-0 overflow-hidden" style={{ width: `${part * 100}%` }}>
60
+ <Star size={size} className="text-primary" />
61
+ </span>
62
+ ) : null}
63
+ </span>
64
+ );
65
+ }
66
+
67
+ const spoken = (n) => String(Math.round(n * 10) / 10);
68
+
69
+ export function Rating({ value = 0, max = 5, onChange, readOnly = false, size = "md", label, name, disabled, id, className }) {
70
+ const px = PX[size] ?? PX.md;
71
+ const group = useId();
72
+ const [hover, setHover] = useState(null);
73
+ const count = Math.max(1, Math.round(max));
74
+ const score = Math.min(Math.max(Number(value) || 0, 0), count);
75
+ const stars = Array.from({ length: count }, (_, i) => i + 1);
76
+
77
+ if (!onChange || readOnly) {
78
+ const halves = Math.round(score * 2) / 2;
79
+ const said = `${spoken(score)} out of ${count}`;
80
+ return (
81
+ <span
82
+ id={id}
83
+ role="img"
84
+ aria-label={label ? `${label}, ${said}` : said}
85
+ className={cx("inline-flex items-center gap-0.5 align-middle", className)}
86
+ >
87
+ {stars.map((n) => (
88
+ <PartStar key={n} size={px} part={Math.min(Math.max(halves - (n - 1), 0), 1)} />
89
+ ))}
90
+ </span>
91
+ );
92
+ }
93
+
94
+ const chosen = Math.round(score);
95
+ const shown = hover ?? chosen;
96
+ return (
97
+ <div
98
+ id={id}
99
+ role="radiogroup"
100
+ aria-label={label ?? "Rating"}
101
+ aria-disabled={disabled || undefined}
102
+ className={cx("inline-flex items-center", size === "sm" ? "-mx-2" : "-mx-3", disabled && "opacity-50", className)}
103
+ onMouseLeave={() => setHover(null)}
104
+ >
105
+ {stars.map((n) => (
106
+ <label
107
+ key={n}
108
+ className={cx(
109
+ "grid shrink-0 place-items-center rounded-md",
110
+ "has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring",
111
+ disabled ? "cursor-not-allowed" : "cursor-pointer",
112
+ TARGET[size] ?? TARGET.md,
113
+ )}
114
+ onMouseEnter={() => !disabled && setHover(n)}
115
+ >
116
+ <input
117
+ type="radio"
118
+ name={name ?? group}
119
+ value={n}
120
+ checked={chosen === n}
121
+ onChange={() => onChange(n)}
122
+ disabled={disabled}
123
+ aria-label={`${n} out of ${count}`}
124
+ className="sr-only"
125
+ />
126
+ <Star size={px} className={cx("transition-colors", n <= shown ? "text-primary" : "text-border")} />
127
+ </label>
128
+ ))}
129
+ </div>
130
+ );
131
+ }
@@ -0,0 +1,338 @@
1
+ "use client";
2
+
3
+ import { Children, createContext, isValidElement, useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
4
+ import { cx } from "./cx";
5
+ import { Icon } from "./icon";
6
+
7
+ // Resizable — panes the user sizes by dragging the line between them: a
8
+ // list beside its record, an editor above its preview. Sizes are
9
+ // percentages of the group; a handle moves only the two panes either
10
+ // side of it. Mobile first: below md (768px) a horizontal group stacks
11
+ // its panes top to bottom at their natural height and hides the handles
12
+ // (there is no room to share, and a thumb cannot hit a 1px line).
13
+ //
14
+ // <ResizablePanelGroup direction="horizontal" storageKey="inbox" className="h-[32rem]">
15
+ // <ResizablePanel defaultSize={35} minSize={20}>…list…</ResizablePanel>
16
+ // <ResizableHandle grip />
17
+ // <ResizablePanel>…record…</ResizablePanel>
18
+ // </ResizablePanelGroup>
19
+ //
20
+ // ResizablePanelGroup
21
+ // direction horizontal (side by side; the default) · vertical
22
+ // storageKey remember the sizes in this browser (localStorage)
23
+ // onResize (sizes) → percentages, one per panel
24
+ // className its height (h-[32rem]); without one it fills its parent
25
+ // (h-full), so the parent needs a height. A vertical
26
+ // group has no height of its own to fall back on
27
+ // ResizablePanel
28
+ // defaultSize %, of the group; panels without one share what is left
29
+ // minSize % it never shrinks below (10) · maxSize % (100)
30
+ // ResizableHandle
31
+ // grip draw a visible grip on the line
32
+ // label what a screen reader calls it ("Resize")
33
+ //
34
+ // Panels and handles are the group's DIRECT children, in order. A handle
35
+ // is a separator a keyboard can move: arrows by 2% (Shift: 10%), Home and
36
+ // End to the limits, Enter to fold the pane before it to its minimum and
37
+ // back; double-click resets the pair.
38
+ //
39
+ // The group never asks what TYPE a child is: from a server surface a
40
+ // child's type is a client reference, not the ResizablePanel function,
41
+ // so a type test finds no panels. Each child gets its slot through
42
+ // context and the panels register themselves (kind, sizes) there.
43
+
44
+ const STEP = 2;
45
+ const BIG = 10;
46
+
47
+ const GroupContext = createContext(null);
48
+ const SlotContext = createContext(-1);
49
+
50
+ // Register this child in its group under its slot; returns the group's
51
+ // wiring for it (undefined until the group has seen the registration).
52
+ function useSlot(entry) {
53
+ const group = useContext(GroupContext);
54
+ const slot = useContext(SlotContext);
55
+ const register = group?.register;
56
+ const key = JSON.stringify(entry);
57
+ useLayoutEffect(() => {
58
+ if (!register || slot < 0) return;
59
+ return register(slot, JSON.parse(key));
60
+ }, [register, slot, key]);
61
+ return group && slot >= 0 ? group.bySlot[slot] : undefined;
62
+ }
63
+
64
+ function initial(panels) {
65
+ const given = panels.reduce((s, p) => s + (p.defaultSize ?? 0), 0);
66
+ const open = panels.filter((p) => p.defaultSize == null).length;
67
+ const share = open ? Math.max(0, 100 - given) / open : 0;
68
+ const raw = panels.map((p) => p.defaultSize ?? share);
69
+ const total = raw.reduce((s, n) => s + n, 0) || 1;
70
+ return raw.map((n) => (n / total) * 100);
71
+ }
72
+
73
+ export function ResizablePanelGroup({ direction = "horizontal", storageKey, onResize, className, children }) {
74
+ const base = useId();
75
+ const group = useRef(null);
76
+ const items = Children.toArray(children).filter(isValidElement);
77
+ // slot → { kind: "panel" | "handle", defaultSize?, minSize?, maxSize? }
78
+ const [reg, setReg] = useState({});
79
+ const register = useCallback((slot, entry) => {
80
+ setReg((r) => (JSON.stringify(r[slot]) === JSON.stringify(entry) ? r : { ...r, [slot]: entry }));
81
+ return () =>
82
+ setReg((r) => {
83
+ if (!(slot in r)) return r;
84
+ const { [slot]: _, ...rest } = r;
85
+ return rest;
86
+ });
87
+ }, []);
88
+ const slots = Object.keys(reg).map(Number).sort((a, b) => a - b);
89
+ const panelSlots = slots.filter((k) => reg[k].kind === "panel");
90
+ const panels = panelSlots.map((k) => ({ minSize: 10, maxSize: 100, ...reg[k] }));
91
+ const defaults = useRef(null);
92
+ if (!defaults.current || defaults.current.length !== panels.length) defaults.current = initial(panels);
93
+ const [own, setSizes] = useState(null);
94
+ const sizes = own && own.length === panels.length ? own : defaults.current;
95
+ const loaded = useRef(false);
96
+ const horizontal = direction !== "vertical";
97
+
98
+ // The remembered sizes, before first paint, when they still fit (once
99
+ // the panels have registered — their layout effects run before ours,
100
+ // the re-render they cause before paint).
101
+ useLayoutEffect(() => {
102
+ if (!panels.length) return;
103
+ if (storageKey) {
104
+ try {
105
+ const saved = JSON.parse(localStorage.getItem(`resizable:${storageKey}`) ?? "null");
106
+ if (Array.isArray(saved) && saved.length === panels.length && saved.every((n) => Number.isFinite(n) && n >= 0)) setSizes(saved);
107
+ } catch {}
108
+ }
109
+ loaded.current = true;
110
+ // eslint-disable-next-line react-hooks/exhaustive-deps
111
+ }, [storageKey, panels.length]);
112
+
113
+ useEffect(() => {
114
+ if (!loaded.current || !panels.length) return;
115
+ onResize?.(sizes);
116
+ if (!storageKey) return;
117
+ const h = setTimeout(() => {
118
+ try {
119
+ localStorage.setItem(`resizable:${storageKey}`, JSON.stringify(sizes.map((n) => Math.round(n * 100) / 100)));
120
+ } catch {}
121
+ }, 150);
122
+ return () => clearTimeout(h);
123
+ // eslint-disable-next-line react-hooks/exhaustive-deps
124
+ }, [sizes, storageKey]);
125
+
126
+ // Move the line between panel a and a + 1 so a is `want` %; the pair's
127
+ // total stays put and each side keeps its min and max.
128
+ function place(a, want) {
129
+ setSizes((mine) => {
130
+ const prev = mine && mine.length === panels.length ? mine : defaults.current;
131
+ const b = a + 1;
132
+ const pair = prev[a] + prev[b];
133
+ const pa = panels[a];
134
+ const pb = panels[b];
135
+ const lo = Math.max(pa.minSize, pair - pb.maxSize, 0);
136
+ const hi = Math.min(pa.maxSize, pair - pb.minSize, pair);
137
+ const next = Math.min(hi, Math.max(lo, want));
138
+ if (Math.abs(next - prev[a]) < 0.01) return prev;
139
+ const out = [...prev];
140
+ out[a] = next;
141
+ out[b] = pair - next;
142
+ return out;
143
+ });
144
+ }
145
+
146
+ function limits(a) {
147
+ const pair = sizes[a] + sizes[a + 1];
148
+ return {
149
+ lo: Math.max(panels[a].minSize, pair - panels[a + 1].maxSize, 0),
150
+ hi: Math.min(panels[a].maxSize, pair - panels[a + 1].minSize, pair),
151
+ };
152
+ }
153
+
154
+ // The panels' own length along the axis, handles excluded: what 100% is.
155
+ function span() {
156
+ const nodes = group.current?.querySelectorAll(":scope > [data-panel]") ?? [];
157
+ let px = 0;
158
+ for (const n of nodes) px += horizontal ? n.offsetWidth : n.offsetHeight;
159
+ return px || 1;
160
+ }
161
+
162
+ // What each registered slot is given: a panel its id and size, a
163
+ // handle the pair either side of it (none when it is not between two).
164
+ const bySlot = {};
165
+ let p = -1;
166
+ for (const k of slots) {
167
+ if (reg[k].kind === "panel") {
168
+ p += 1;
169
+ bySlot[k] = { _id: `${base}-${p}`, _size: sizes[p], _horizontal: horizontal };
170
+ } else if (reg[k].kind === "handle") {
171
+ const a = p;
172
+ if (a < 0 || a >= panels.length - 1) {
173
+ bySlot[k] = { _horizontal: horizontal, _orphan: true };
174
+ continue;
175
+ }
176
+ bySlot[k] = {
177
+ _horizontal: horizontal,
178
+ _controls: `${base}-${a}`,
179
+ _value: sizes[a],
180
+ _limits: () => limits(a),
181
+ _start: () => ({ from: sizes[a], span: span() }),
182
+ _place: (want) => place(a, want),
183
+ _reset: () => {
184
+ const d = defaults.current;
185
+ const pair = sizes[a] + sizes[a + 1];
186
+ place(a, (d[a] / (d[a] + d[a + 1])) * pair);
187
+ },
188
+ };
189
+ }
190
+ }
191
+
192
+ return (
193
+ <div
194
+ ref={group}
195
+ data-direction={horizontal ? "horizontal" : "vertical"}
196
+ className={cx(
197
+ "flex w-full min-h-0 min-w-0",
198
+ !/(?:^|\s)h-/.test(className ?? "") && "h-full",
199
+ horizontal ? "flex-row max-md:h-auto max-md:flex-col" : "flex-col",
200
+ className,
201
+ )}
202
+ >
203
+ <GroupContext.Provider value={{ register, bySlot, horizontal }}>
204
+ {items.map((child, i) => (
205
+ <SlotContext.Provider key={child.key ?? i} value={i}>
206
+ {child}
207
+ </SlotContext.Provider>
208
+ ))}
209
+ </GroupContext.Provider>
210
+ </div>
211
+ );
212
+ }
213
+
214
+ export function ResizablePanel({ defaultSize, minSize, maxSize, className, children }) {
215
+ const group = useContext(GroupContext);
216
+ const wired = useSlot({ kind: "panel", defaultSize, minSize, maxSize });
217
+ const _horizontal = wired?._horizontal ?? group?.horizontal ?? true;
218
+ // Before the group has counted its panels (the server render, the first
219
+ // client pass) a panel with a defaultSize takes that share, the rest
220
+ // split what is left: the layout the counted sizes will give.
221
+ const style = wired
222
+ ? { flexGrow: wired._size ?? 1, flexShrink: 1, flexBasis: 0 }
223
+ : defaultSize != null
224
+ ? { flexGrow: 0, flexShrink: 1, flexBasis: `${defaultSize}%` }
225
+ : { flexGrow: 1, flexShrink: 1, flexBasis: 0 };
226
+ return (
227
+ <div
228
+ id={wired?._id}
229
+ data-panel=""
230
+ style={style}
231
+ className={cx("min-h-0 min-w-0 overflow-auto", _horizontal && "max-md:flex-none! max-md:overflow-visible", className)}
232
+ >
233
+ {children}
234
+ </div>
235
+ );
236
+ }
237
+
238
+ export function ResizableHandle({ grip = false, label = "Resize", className }) {
239
+ const group = useContext(GroupContext);
240
+ const wired = useSlot({ kind: "handle" });
241
+ const [dragging, setDragging] = useState(false);
242
+ const drag = useRef(null);
243
+ const folded = useRef(null);
244
+ const _horizontal = wired?._horizontal ?? group?.horizontal ?? true;
245
+ if (!group || wired?._orphan) return null;
246
+ const { _controls, _value, _limits, _start, _place, _reset } = wired ?? {};
247
+ const live = Boolean(_place);
248
+ const { lo, hi } = live ? _limits() : { lo: 0, hi: 100 };
249
+
250
+ function onPointerDown(e) {
251
+ if (e.button !== 0 || !live) return;
252
+ e.preventDefault();
253
+ e.currentTarget.setPointerCapture(e.pointerId);
254
+ e.currentTarget.focus();
255
+ drag.current = { at: _horizontal ? e.clientX : e.clientY, ..._start() };
256
+ setDragging(true);
257
+ document.documentElement.style.cursor = _horizontal ? "col-resize" : "row-resize";
258
+ document.documentElement.style.userSelect = "none";
259
+ }
260
+ function onPointerMove(e) {
261
+ const d = drag.current;
262
+ if (!d) return;
263
+ const moved = (_horizontal ? e.clientX : e.clientY) - d.at;
264
+ _place(d.from + (moved / d.span) * 100);
265
+ }
266
+ function end() {
267
+ if (!drag.current) return;
268
+ drag.current = null;
269
+ setDragging(false);
270
+ document.documentElement.style.cursor = "";
271
+ document.documentElement.style.userSelect = "";
272
+ }
273
+
274
+ function onKeyDown(e) {
275
+ if (!live) return;
276
+ const step = e.shiftKey ? BIG : STEP;
277
+ const back = _horizontal ? "ArrowLeft" : "ArrowUp";
278
+ const fwd = _horizontal ? "ArrowRight" : "ArrowDown";
279
+ if (e.key === back) _place(_value - step);
280
+ else if (e.key === fwd) _place(_value + step);
281
+ else if (e.key === "Home") _place(lo);
282
+ else if (e.key === "End") _place(hi);
283
+ else if (e.key === "Enter") {
284
+ if (folded.current != null && _value <= lo + 0.01) {
285
+ _place(folded.current);
286
+ folded.current = null;
287
+ } else {
288
+ folded.current = _value;
289
+ _place(lo);
290
+ }
291
+ } else return;
292
+ e.preventDefault();
293
+ }
294
+
295
+ return (
296
+ <div
297
+ // Until the group wires it (the server render), a plain line.
298
+ role={live ? "separator" : undefined}
299
+ aria-hidden={live ? undefined : true}
300
+ tabIndex={live ? 0 : undefined}
301
+ aria-label={live ? label : undefined}
302
+ aria-orientation={live ? (_horizontal ? "vertical" : "horizontal") : undefined}
303
+ aria-controls={_controls}
304
+ aria-valuenow={live ? Math.round(_value) : undefined}
305
+ aria-valuemin={live ? Math.round(lo) : undefined}
306
+ aria-valuemax={live ? Math.round(hi) : undefined}
307
+ data-dragging={dragging || undefined}
308
+ onPointerDown={onPointerDown}
309
+ onPointerMove={onPointerMove}
310
+ onPointerUp={end}
311
+ onPointerCancel={end}
312
+ onLostPointerCapture={end}
313
+ onKeyDown={onKeyDown}
314
+ onDoubleClick={_reset}
315
+ className={cx(
316
+ "relative z-10 flex shrink-0 touch-none items-center justify-center bg-border outline-none transition-colors",
317
+ "hover:bg-ring/60 focus-visible:bg-ring data-[dragging]:bg-ring motion-reduce:transition-none",
318
+ "after:absolute after:content-['']",
319
+ _horizontal
320
+ ? "w-px cursor-col-resize after:inset-y-0 after:left-1/2 after:w-4 after:-translate-x-1/2 max-md:hidden"
321
+ : "h-px w-full cursor-row-resize after:inset-x-0 after:top-1/2 after:h-4 after:-translate-y-1/2",
322
+ className,
323
+ )}
324
+ >
325
+ {grip ? (
326
+ <span
327
+ aria-hidden="true"
328
+ className={cx(
329
+ "grid place-items-center rounded-sm border border-border bg-background text-muted-foreground shadow-sm",
330
+ _horizontal ? "h-6 w-3.5" : "h-3.5 w-6",
331
+ )}
332
+ >
333
+ <Icon name="grip" size={12} className={_horizontal ? undefined : "rotate-90"} />
334
+ </span>
335
+ ) : null}
336
+ </div>
337
+ );
338
+ }