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,393 @@
1
+ "use client";
2
+
3
+ // The tree view: a JSON value as folding rows, edited in place.
4
+ //
5
+ // One row per key (or list item). Containers fold; text, numbers,
6
+ // true/false and null edit inline (double-click, or Enter on the row);
7
+ // keys rename (double-click the key, or F2). Each row's ⋯ menu adds, copies
8
+ // its path or value, changes its type, or deletes it (with Undo). The rows
9
+ // are a WAI-ARIA tree: one Tab stop, arrows move and fold, Home/End jump.
10
+ import { useEffect, useRef, useState } from "react";
11
+ import { Icon, IconButton, Menu, cx } from "../../ui";
12
+ import { convertType, editText, flattenTree, insertAt, isContainer, parseEdit, pathId, pathLabel, preview, removeAt, renameKey, setAt, summary, uniqueKey } from "./tree";
13
+
14
+ // Types are categories: the chart hues, as the code view paints them.
15
+ const TONE = {
16
+ string: "text-chart-2",
17
+ number: "text-chart-3 tabular-nums",
18
+ boolean: "text-chart-3",
19
+ null: "text-chart-3 italic",
20
+ };
21
+
22
+ const TYPES = [
23
+ { value: "string", label: "Text" },
24
+ { value: "number", label: "Number" },
25
+ { value: "boolean", label: "True / false" },
26
+ { value: "null", label: "Empty (null)" },
27
+ { value: "object", label: "Object" },
28
+ { value: "array", label: "List" },
29
+ ];
30
+
31
+ const INDENT = 18;
32
+
33
+ async function copy(text) {
34
+ try {
35
+ await navigator.clipboard.writeText(text);
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ export function JsonTree({ value, onEdit, open, setOpen, readOnly = false, onNotice, className, style, label = "JSON" }) {
43
+ const rows = flattenTree(value, open);
44
+ const [focusId, setFocusId] = useState(rows[0]?.id ?? null);
45
+ const [editing, setEditing] = useState(null); // { id, field: "key" | "value", draft, error }
46
+ const [hoverId, setHoverId] = useState(null);
47
+ const rowRefs = useRef(new Map());
48
+ const wantFocus = useRef(null);
49
+
50
+ // Keep a focused row that still exists.
51
+ const current = rows.find((r) => r.id === focusId) ? focusId : rows[0]?.id ?? null;
52
+
53
+ useEffect(() => {
54
+ if (!wantFocus.current) return;
55
+ const el = rowRefs.current.get(wantFocus.current);
56
+ wantFocus.current = null;
57
+ el?.focus();
58
+ });
59
+
60
+ const focusRow = (id) => {
61
+ setFocusId(id);
62
+ wantFocus.current = id;
63
+ };
64
+
65
+ const toggle = (row, to) => {
66
+ if (!isContainer(row.value)) return;
67
+ const next = new Set(open);
68
+ const want = to ?? !open.has(row.id);
69
+ if (want) next.add(row.id);
70
+ else next.delete(row.id);
71
+ setOpen(next);
72
+ };
73
+
74
+ // ---- edits: each hands the new root out, with words for an Undo toast.
75
+ function commitValue(row, draft) {
76
+ const next = parseEdit(draft, row.type);
77
+ setEditing(null);
78
+ focusRow(row.id);
79
+ if (Object.is(next, row.value) || JSON.stringify(next) === JSON.stringify(row.value)) return;
80
+ onEdit(setAt(value, row.path, next));
81
+ }
82
+
83
+ function commitKey(row, draft) {
84
+ const r = renameKey(value, row.path, draft.trim());
85
+ if (r.error) {
86
+ setEditing((e) => e && { ...e, error: r.error });
87
+ return;
88
+ }
89
+ setEditing(null);
90
+ const newPath = [...row.path.slice(0, -1), draft.trim()];
91
+ focusRow(pathId(newPath));
92
+ if (r.root !== value) onEdit(r.root);
93
+ }
94
+
95
+ function add(row) {
96
+ const parentPath = row ? row.path : [];
97
+ const parent = row ? row.value : value;
98
+ const openNext = new Set(open);
99
+ if (row) openNext.add(row.id);
100
+ setOpen(openNext);
101
+ if (Array.isArray(parent)) {
102
+ const path = [...parentPath, parent.length];
103
+ onEdit(insertAt(value, parentPath, { value: "" }));
104
+ setFocusId(pathId(path)); // the field takes focus, not the row
105
+ setEditing({ id: pathId(path), field: "value", draft: "" });
106
+ } else {
107
+ const key = uniqueKey(parent);
108
+ const path = [...parentPath, key];
109
+ onEdit(insertAt(value, parentPath, { key, value: "" }));
110
+ setFocusId(pathId(path));
111
+ setEditing({ id: pathId(path), field: "key", draft: key, select: true });
112
+ }
113
+ }
114
+
115
+ function remove(row) {
116
+ const before = value;
117
+ const { root } = removeAt(value, row.path);
118
+ // Focus stays in place: the next sibling (in a list, the next item
119
+ // takes this one's index), else the one before, else the parent.
120
+ const siblings = rows.filter((r) => r.parentId === row.parentId);
121
+ const pos = siblings.findIndex((r) => r.id === row.id);
122
+ const inList = typeof row.key === "number";
123
+ const target = pos < siblings.length - 1 ? (inList ? row.id : siblings[pos + 1].id) : (siblings[pos - 1]?.id ?? row.parentId);
124
+ onEdit(root, { undo: () => onEdit(before), message: `Deleted ${inList ? `item ${row.key}` : `"${row.key}"`}` });
125
+ focusRow(target);
126
+ }
127
+
128
+ function retype(row, type) {
129
+ if (row.type === type) return;
130
+ onEdit(setAt(value, row.path, convertType(row.value, type)));
131
+ if (type === "object" || type === "array") setOpen(new Set(open).add(row.id));
132
+ }
133
+
134
+ // ---- keys: the tree pattern.
135
+ function onKeyDown(e, row, i) {
136
+ if (editing) return;
137
+ const go = (j) => {
138
+ if (rows[j]) {
139
+ e.preventDefault();
140
+ focusRow(rows[j].id);
141
+ }
142
+ };
143
+ switch (e.key) {
144
+ case "ArrowDown":
145
+ return go(i + 1);
146
+ case "ArrowUp":
147
+ return go(i - 1);
148
+ case "Home":
149
+ return go(0);
150
+ case "End":
151
+ return go(rows.length - 1);
152
+ case "ArrowRight":
153
+ e.preventDefault();
154
+ if (isContainer(row.value) && !row.open) toggle(row, true);
155
+ else if (row.open && rows[i + 1]?.parentId === row.id) focusRow(rows[i + 1].id);
156
+ return;
157
+ case "ArrowLeft": {
158
+ e.preventDefault();
159
+ if (row.open) return toggle(row, false);
160
+ const parent = rows.find((r) => r.id === row.parentId);
161
+ if (parent) focusRow(parent.id);
162
+ return;
163
+ }
164
+ case "Enter":
165
+ case " ":
166
+ e.preventDefault();
167
+ if (isContainer(row.value)) toggle(row);
168
+ else if (!readOnly) setEditing({ id: row.id, field: "value", draft: editText(row.value), select: true });
169
+ return;
170
+ case "F2":
171
+ if (!readOnly && typeof row.key === "string") {
172
+ e.preventDefault();
173
+ setEditing({ id: row.id, field: "key", draft: row.key, select: true });
174
+ }
175
+ return;
176
+ case "Delete":
177
+ case "Backspace":
178
+ if (!readOnly && row.path.length) {
179
+ e.preventDefault();
180
+ remove(row);
181
+ }
182
+ return;
183
+ default:
184
+ }
185
+ }
186
+
187
+ const rootIsContainer = isContainer(value);
188
+
189
+ return (
190
+ <div className={cx("overflow-auto py-1.5", className)} style={style}>
191
+ <div role="tree" aria-label={label} className="px-1.5" onMouseLeave={() => setHoverId(null)}>
192
+ {rows.map((row, i) => {
193
+ const container = isContainer(row.value);
194
+ const isEditing = editing?.id === row.id;
195
+ const menu = row.id !== current && row.id !== hoverId ? [] : readOnly
196
+ ? [
197
+ { label: "Copy path", icon: "link", onSelect: () => copy(pathLabel(row.path)).then((ok) => onNotice?.(ok ? `Copied ${pathLabel(row.path)}` : "Could not reach the clipboard")) },
198
+ { label: "Copy value", icon: "copy", onSelect: () => copy(container ? JSON.stringify(row.value, null, 2) : editText(row.value)).then((ok) => onNotice?.(ok ? "Copied the value" : "Could not reach the clipboard")) },
199
+ ]
200
+ : [
201
+ !container && { label: "Edit value", icon: "pencil", shortcut: "↵", onSelect: () => setEditing({ id: row.id, field: "value", draft: editText(row.value), select: true }) },
202
+ typeof row.key === "string" && { label: "Rename key", icon: "type", shortcut: "F2", onSelect: () => setEditing({ id: row.id, field: "key", draft: row.key, select: true }) },
203
+ container && { label: Array.isArray(row.value) ? "Add item" : "Add key", icon: "plus", onSelect: () => add(row) },
204
+ { type: "separator" },
205
+ { label: "Copy path", icon: "link", onSelect: () => copy(pathLabel(row.path)).then((ok) => onNotice?.(ok ? `Copied ${pathLabel(row.path)}` : "Could not reach the clipboard")) },
206
+ { label: "Copy value", icon: "copy", onSelect: () => copy(container ? JSON.stringify(row.value, null, 2) : editText(row.value)).then((ok) => onNotice?.(ok ? "Copied the value" : "Could not reach the clipboard")) },
207
+ { label: "Change type", icon: "layers", items: [{ type: "radio", value: row.type, onValueChange: (t) => retype(row, t), options: TYPES }] },
208
+ row.path.length > 0 && { type: "separator" },
209
+ row.path.length > 0 && { label: "Delete", icon: "trash", tone: "danger", shortcut: "⌫", onSelect: () => remove(row) },
210
+ ];
211
+ return (
212
+ // raw: a treeitem row — the WAI-ARIA tree needs the row itself
213
+ // focusable with its own keys; no kit part is a tree row.
214
+ <div
215
+ key={row.id}
216
+ ref={(el) => {
217
+ if (el) rowRefs.current.set(row.id, el);
218
+ else rowRefs.current.delete(row.id);
219
+ }}
220
+ role="treeitem"
221
+ aria-level={row.depth + 1}
222
+ aria-expanded={container ? row.open : undefined}
223
+ aria-selected={row.id === current}
224
+ aria-label={`${row.key ?? "value"}: ${container ? summary(row.value) : editText(row.value)}`}
225
+ tabIndex={row.id === current ? 0 : -1}
226
+ onFocus={() => setFocusId(row.id)}
227
+ onMouseEnter={() => setHoverId(row.id)}
228
+ onKeyDown={(e) => onKeyDown(e, row, i)}
229
+ onClick={() => container && !isEditing && toggle(row)}
230
+ className={cx(
231
+ "group/row relative flex min-h-9 items-center gap-2 rounded-md pe-1 font-mono text-[13px] outline-none max-sm:min-h-11",
232
+ "transition-colors duration-150 motion-reduce:transition-none",
233
+ "hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring",
234
+ row.id === current && "bg-muted",
235
+ container && "cursor-pointer",
236
+ )}
237
+ style={{ paddingInlineStart: 6 + row.depth * INDENT }}
238
+ >
239
+ {Array.from({ length: row.depth }, (_, d) => (
240
+ <span key={d} aria-hidden="true" className="absolute inset-y-0 w-px bg-border" style={{ insetInlineStart: 6 + d * INDENT + 8 }} />
241
+ ))}
242
+ <span aria-hidden="true" className="grid size-4 shrink-0 place-items-center text-muted-foreground">
243
+ {container ? <Icon name="chevron-right" size={14} className={cx("transition-transform duration-150 motion-reduce:transition-none", row.open && "rotate-90")} /> : null}
244
+ </span>
245
+
246
+ {row.key !== null ? (
247
+ isEditing && editing.field === "key" ? (
248
+ <InlineInput
249
+ draft={editing}
250
+ onDraft={(d) => setEditing({ ...editing, draft: d, error: null })}
251
+ onCommit={(d) => commitKey(row, d)}
252
+ onCancel={() => {
253
+ setEditing(null);
254
+ focusRow(row.id);
255
+ }}
256
+ label={`Rename ${row.key}`}
257
+ />
258
+ ) : (
259
+ <span
260
+ className={cx("max-w-[45%] shrink-0 truncate", typeof row.key === "number" ? "text-muted-foreground tabular-nums" : "text-foreground")}
261
+ title={typeof row.key === "string" && row.key.length > 24 ? row.key : undefined}
262
+ onDoubleClick={(e) => {
263
+ if (readOnly || typeof row.key !== "string") return;
264
+ e.stopPropagation();
265
+ setEditing({ id: row.id, field: "key", draft: row.key, select: true });
266
+ }}
267
+ >
268
+ {row.key}
269
+ </span>
270
+ )
271
+ ) : null}
272
+ {row.key !== null ? <span aria-hidden="true" className="-ms-1.5 text-muted-foreground">:</span> : null}
273
+
274
+ {container ? (
275
+ <span className="min-w-0 truncate font-sans text-xs text-muted-foreground" title={row.open ? undefined : preview(row.value, 400)}>
276
+ {row.open ? summary(row.value) : preview(row.value)}
277
+ </span>
278
+ ) : isEditing && editing.field === "value" ? (
279
+ <InlineInput
280
+ draft={editing}
281
+ onDraft={(d) => setEditing({ ...editing, draft: d })}
282
+ onCommit={(d) => commitValue(row, d)}
283
+ onCancel={() => {
284
+ setEditing(null);
285
+ focusRow(row.id);
286
+ }}
287
+ label={`Edit ${row.key ?? "value"}`}
288
+ quoted={row.type === "string"}
289
+ />
290
+ ) : (
291
+ <span
292
+ className={cx("min-w-0 truncate", TONE[row.type])}
293
+ title={editText(row.value).length > 40 ? editText(row.value) : undefined}
294
+ onDoubleClick={(e) => {
295
+ if (readOnly) return;
296
+ e.stopPropagation();
297
+ setEditing({ id: row.id, field: "value", draft: editText(row.value), select: true });
298
+ }}
299
+ >
300
+ {row.type === "string" ? JSON.stringify(row.value) : String(row.value)}
301
+ </span>
302
+ )}
303
+
304
+ {/* The row's actions: only on the row in hand (focused or under the
305
+ pointer), so the tree stays one Tab stop and a long list
306
+ does not carry a menu per row. */}
307
+ {row.id === current || row.id === hoverId ? (
308
+ <span className="ms-auto flex shrink-0 items-center gap-0.5 ps-3" onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()}>
309
+ {container && !readOnly ? (
310
+ <IconButton icon="plus" size="sm" label={Array.isArray(row.value) ? `Add an item to ${pathLabel(row.path)}` : `Add a key to ${pathLabel(row.path)}`} onClick={() => add(row)} className="max-sm:hidden" />
311
+ ) : null}
312
+ <Menu items={menu} label={`Actions for ${pathLabel(row.path)}`} />
313
+ </span>
314
+ ) : null}
315
+ {isEditing && editing.error ? (
316
+ <span role="alert" className="absolute top-full z-10 mt-1 rounded-md border border-border bg-popover px-2 py-1 font-sans text-xs text-destructive shadow-lg" style={{ insetInlineStart: 6 + row.depth * INDENT + 24 }}>
317
+ {editing.error}
318
+ </span>
319
+ ) : null}
320
+ </div>
321
+ );
322
+ })}
323
+ {rootIsContainer && !readOnly ? (
324
+ <div className="px-1.5 pt-1">
325
+ {/* raw: the tree's last row — a quiet "add" in the rows' own shape, a Button would sit off the grid */}
326
+ <button
327
+ type="button"
328
+ onClick={() => add(null)}
329
+ className="flex min-h-9 w-full items-center gap-2 rounded-md ps-1.5 text-start text-sm text-muted-foreground outline-none transition-colors duration-150 hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring max-sm:min-h-11 motion-reduce:transition-none"
330
+ >
331
+ <Icon name="plus" size={14} />
332
+ {Array.isArray(value) ? "Add item" : "Add key"}
333
+ </button>
334
+ </div>
335
+ ) : null}
336
+ </div>
337
+ </div>
338
+ );
339
+ }
340
+
341
+ /** The field a key or a value is edited in, the row's own height. */
342
+ function InlineInput({ draft, onDraft, onCommit, onCancel, label, quoted = false }) {
343
+ const ref = useRef(null);
344
+ const done = useRef(false);
345
+ useEffect(() => {
346
+ const el = ref.current;
347
+ if (!el) return;
348
+ el.focus();
349
+ if (draft.select) el.select();
350
+ // Once: the field opened.
351
+ // eslint-disable-next-line react-hooks/exhaustive-deps
352
+ }, []);
353
+ const width = Math.min(48, Math.max(6, String(draft.draft).length + 2));
354
+ return (
355
+ <span className={cx("relative inline-flex min-w-0 items-center", quoted && "before:text-chart-2 before:content-['“'] after:text-chart-2 after:content-['”']")}>
356
+ {/* raw: an inline field the row's height (the kit's Input is a 44px form control) */}
357
+ <input
358
+ ref={ref}
359
+ aria-label={label}
360
+ aria-invalid={draft.error ? true : undefined}
361
+ value={draft.draft}
362
+ onChange={(e) => onDraft(e.target.value)}
363
+ onClick={(e) => e.stopPropagation()}
364
+ onDoubleClick={(e) => e.stopPropagation()}
365
+ onKeyDown={(e) => {
366
+ e.stopPropagation();
367
+ if (e.key === "Enter") {
368
+ e.preventDefault();
369
+ done.current = true;
370
+ onCommit(e.currentTarget.value);
371
+ // Still here (the key was refused): the next blur commits again.
372
+ queueMicrotask(() => {
373
+ done.current = false;
374
+ });
375
+ } else if (e.key === "Escape") {
376
+ e.preventDefault();
377
+ done.current = true;
378
+ onCancel();
379
+ }
380
+ }}
381
+ onBlur={(e) => {
382
+ if (done.current) return;
383
+ onCommit(e.currentTarget.value);
384
+ }}
385
+ style={{ width: `${width}ch` }}
386
+ className={cx(
387
+ "h-7 max-w-[60vw] rounded-sm border bg-background px-1.5 font-mono text-[13px] text-foreground outline-none max-sm:text-base",
388
+ draft.error ? "border-destructive" : "border-ring",
389
+ )}
390
+ />
391
+ </span>
392
+ );
393
+ }
@@ -0,0 +1,225 @@
1
+ // The tree view's model: a JSON value seen as rows, and the edits a row
2
+ // makes, as plain functions of plain values (node and the server run them).
3
+ //
4
+ // A PATH is the list of keys and indexes from the root to a value:
5
+ // ["deal", "owner", "email"], ["deal", "tags", 0]. Every edit returns a NEW
6
+ // root and leaves the old one untouched, so undo is keeping the old one.
7
+
8
+ /** "object" · "array" · "string" · "number" · "boolean" · "null". */
9
+ export function typeOf(v) {
10
+ if (v === null) return "null";
11
+ if (Array.isArray(v)) return "array";
12
+ const t = typeof v;
13
+ return t === "object" ? "object" : t === "string" || t === "number" || t === "boolean" ? t : "null";
14
+ }
15
+
16
+ export const isContainer = (v) => v !== null && typeof v === "object";
17
+
18
+ /** A stable id for a path: the key a row is remembered by. */
19
+ export const pathId = (path) => JSON.stringify(path);
20
+
21
+ const IDENT = /^[A-Za-z_$][\w$]*$/;
22
+
23
+ /** How people write a path: deal.owner.email, deal.tags[0], meta["first name"]. */
24
+ export function pathLabel(path) {
25
+ let out = "";
26
+ for (const k of path) {
27
+ if (typeof k === "number") out += `[${k}]`;
28
+ else if (IDENT.test(k)) out += out ? `.${k}` : k;
29
+ else out += `[${JSON.stringify(k)}]`;
30
+ }
31
+ return out || "(root)";
32
+ }
33
+
34
+ /** "3 keys" · "1 item" · "empty". */
35
+ export function summary(v) {
36
+ if (Array.isArray(v)) return v.length ? `${v.length} item${v.length === 1 ? "" : "s"}` : "empty list";
37
+ if (isContainer(v)) {
38
+ const n = Object.keys(v).length;
39
+ return n ? `${n} key${n === 1 ? "" : "s"}` : "empty object";
40
+ }
41
+ return "";
42
+ }
43
+
44
+ export function getAt(root, path) {
45
+ let v = root;
46
+ for (const k of path) {
47
+ if (!isContainer(v)) return undefined;
48
+ v = v[k];
49
+ }
50
+ return v;
51
+ }
52
+
53
+ /** The root with the value at `path` replaced. */
54
+ export function setAt(root, path, value) {
55
+ if (!path.length) return value;
56
+ const [k, ...rest] = path;
57
+ const here = Array.isArray(root) ? [...root] : { ...root };
58
+ here[k] = setAt(root?.[k], rest, value);
59
+ return here;
60
+ }
61
+
62
+ /** The root without the value at `path`: { root, removed, index } —
63
+ * `index` is where it stood (a key's position in its object), for undo. */
64
+ export function removeAt(root, path) {
65
+ if (!path.length) return { root: undefined, removed: root, index: 0 };
66
+ const parentPath = path.slice(0, -1);
67
+ const k = path[path.length - 1];
68
+ const parent = getAt(root, parentPath);
69
+ if (Array.isArray(parent)) {
70
+ const next = parent.filter((_, i) => i !== k);
71
+ return { root: setAt(root, parentPath, next), removed: parent[k], index: k };
72
+ }
73
+ const keys = Object.keys(parent);
74
+ const next = {};
75
+ for (const key of keys) if (key !== k) next[key] = parent[key];
76
+ return { root: setAt(root, parentPath, next), removed: parent[k], index: keys.indexOf(k) };
77
+ }
78
+
79
+ /** Put a value into the container at `parentPath`, at `index` (a list) or
80
+ * as `key` at position `index` (an object; the end when index is null). */
81
+ export function insertAt(root, parentPath, { key, index = null, value }) {
82
+ const parent = getAt(root, parentPath);
83
+ if (Array.isArray(parent)) {
84
+ const next = [...parent];
85
+ next.splice(index == null ? next.length : index, 0, value);
86
+ return setAt(root, parentPath, next);
87
+ }
88
+ const entries = Object.entries(parent ?? {}).filter(([k]) => k !== key);
89
+ entries.splice(index == null ? entries.length : Math.min(index, entries.length), 0, [key, value]);
90
+ return setAt(root, parentPath, Object.fromEntries(entries));
91
+ }
92
+
93
+ /** Rename the key at `path`, keeping its place. { root } or { error }. */
94
+ export function renameKey(root, path, to) {
95
+ const parentPath = path.slice(0, -1);
96
+ const from = path[path.length - 1];
97
+ const parent = getAt(root, parentPath);
98
+ const name = String(to);
99
+ if (name === from) return { root };
100
+ if (!name.length) return { error: "A key needs a name" };
101
+ if (Object.hasOwn(parent, name)) return { error: `There is already a key "${name}" here` };
102
+ const next = {};
103
+ for (const [k, v] of Object.entries(parent)) next[k === from ? name : k] = v;
104
+ return { root: setAt(root, parentPath, next) };
105
+ }
106
+
107
+ /** A key not yet used in `obj`: base, base_2, base_3… */
108
+ export function uniqueKey(obj, base = "new_key") {
109
+ if (!Object.hasOwn(obj ?? {}, base)) return base;
110
+ for (let n = 2; ; n++) if (!Object.hasOwn(obj, `${base}_${n}`)) return `${base}_${n}`;
111
+ }
112
+
113
+ /** What a typed edit means. Text stays text; for a number, true/false/
114
+ * null or a {…}/[…] the field is read as JSON — unless the value was text
115
+ * and still reads as text-ish. `prevType` is the type being edited. */
116
+ export function parseEdit(text, prevType) {
117
+ const s = String(text ?? "");
118
+ if (prevType === "string") return s;
119
+ const t = s.trim();
120
+ if (t === "true") return true;
121
+ if (t === "false") return false;
122
+ if (t === "null") return null;
123
+ if (/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(t)) return Number(t);
124
+ if (/^[[{"]/.test(t)) {
125
+ try {
126
+ return JSON.parse(t);
127
+ } catch {
128
+ /* fall through: keep it as text */
129
+ }
130
+ }
131
+ return s;
132
+ }
133
+
134
+ /** The text a value is edited as: text bare, everything else as JSON. */
135
+ export const editText = (v) => (typeof v === "string" ? v : JSON.stringify(v));
136
+
137
+ /** Turn a value into another type, keeping what can be kept. */
138
+ export function convertType(v, type) {
139
+ const from = typeOf(v);
140
+ if (from === type) return v;
141
+ switch (type) {
142
+ case "string":
143
+ return isContainer(v) ? JSON.stringify(v) : v === null ? "" : String(v);
144
+ case "number": {
145
+ const n = Number(typeof v === "string" ? v.trim() : v);
146
+ return Number.isFinite(n) ? n : 0;
147
+ }
148
+ case "boolean":
149
+ return typeof v === "string" ? v.trim().toLowerCase() === "true" : Boolean(isContainer(v) ? Object.keys(v).length : v);
150
+ case "null":
151
+ return null;
152
+ case "array":
153
+ return from === "object" ? Object.values(v) : v === null || v === "" ? [] : [v];
154
+ case "object":
155
+ return from === "array" ? Object.fromEntries(v.map((x, i) => [String(i), x])) : v === null || v === "" ? {} : { value: v };
156
+ default:
157
+ return v;
158
+ }
159
+ }
160
+
161
+ /** The ids of the containers open `depth` levels down: 1 opens the
162
+ * top-level rows, 2 their children too; 0 shows only the top level. */
163
+ export function expandedTo(value, depth) {
164
+ const out = new Set();
165
+ const walk = (v, path, d) => {
166
+ if (!isContainer(v)) return;
167
+ if (path.length) {
168
+ if (d >= depth) return;
169
+ out.add(pathId(path));
170
+ }
171
+ for (const [k, child] of entries(v)) walk(child, [...path, k], path.length ? d + 1 : 0);
172
+ };
173
+ walk(value, [], 0);
174
+ return out;
175
+ }
176
+
177
+ /** Every container id (Expand all). */
178
+ export const allContainers = (value) => expandedTo(value, Infinity);
179
+
180
+ const entries = (v) => (Array.isArray(v) ? v.map((x, i) => [i, x]) : Object.entries(v));
181
+
182
+ /**
183
+ * The rows the tree shows: the root's children (the root itself when it is
184
+ * not a container), each open container's children beneath it, depth
185
+ * first. Each row: { id, path, key, depth, type, value, size, open,
186
+ * parentId, last } — `size` a container's summary, `last` whether it is
187
+ * the last child of its parent (for the guide lines).
188
+ */
189
+ export function flattenTree(value, open) {
190
+ const rows = [];
191
+ if (!isContainer(value)) {
192
+ if (value !== undefined) rows.push({ id: pathId([]), path: [], key: null, depth: 0, type: typeOf(value), value, size: "", open: false, parentId: null, last: true });
193
+ return rows;
194
+ }
195
+ const walk = (v, path, depth) => {
196
+ const list = entries(v);
197
+ list.forEach(([k, child], i) => {
198
+ const p = [...path, k];
199
+ const id = pathId(p);
200
+ const container = isContainer(child);
201
+ const isOpen = container && open.has(id);
202
+ rows.push({ id, path: p, key: k, depth, type: typeOf(child), value: child, size: container ? summary(child) : "", open: isOpen, parentId: pathId(path), last: i === list.length - 1 });
203
+ if (isOpen) walk(child, p, depth + 1);
204
+ });
205
+ };
206
+ walk(value, [], 0);
207
+ return rows;
208
+ }
209
+
210
+ /** A short one-line look at a value, for a folded row. */
211
+ export function preview(v, max = 60) {
212
+ if (!isContainer(v)) return typeof v === "string" ? JSON.stringify(v) : String(v);
213
+ const parts = [];
214
+ let len = 0;
215
+ for (const [k, x] of entries(v)) {
216
+ const bit = (Array.isArray(v) ? "" : `${k}: `) + (isContainer(x) ? (Array.isArray(x) ? "[…]" : "{…}") : typeof x === "string" ? JSON.stringify(x) : String(x));
217
+ len += bit.length + 2;
218
+ if (len > max) {
219
+ parts.push("…");
220
+ break;
221
+ }
222
+ parts.push(bit);
223
+ }
224
+ return Array.isArray(v) ? `[${parts.join(", ")}]` : `{ ${parts.join(", ")} }`;
225
+ }