@treenity/react 3.0.0 → 3.0.2

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 (379) hide show
  1. package/README.md +91 -0
  2. package/dist/AclEditor.d.ts +1 -1
  3. package/dist/AclEditor.d.ts.map +1 -1
  4. package/dist/AclEditor.js +5 -5
  5. package/dist/AclEditor.js.map +1 -1
  6. package/dist/ActionCards.d.ts +9 -0
  7. package/dist/ActionCards.d.ts.map +1 -0
  8. package/dist/ActionCards.js +96 -0
  9. package/dist/ActionCards.js.map +1 -0
  10. package/dist/App.d.ts.map +1 -1
  11. package/dist/App.js +97 -185
  12. package/dist/App.js.map +1 -1
  13. package/dist/ComponentSection.d.ts +15 -0
  14. package/dist/ComponentSection.d.ts.map +1 -0
  15. package/dist/ComponentSection.js +25 -0
  16. package/dist/ComponentSection.js.map +1 -0
  17. package/dist/ErrorBoundary.d.ts +18 -0
  18. package/dist/ErrorBoundary.d.ts.map +1 -0
  19. package/dist/ErrorBoundary.js +18 -0
  20. package/dist/ErrorBoundary.js.map +1 -0
  21. package/dist/Inspector.d.ts +1 -0
  22. package/dist/Inspector.d.ts.map +1 -1
  23. package/dist/Inspector.js +22 -347
  24. package/dist/Inspector.js.map +1 -1
  25. package/dist/Login.d.ts +8 -0
  26. package/dist/Login.d.ts.map +1 -0
  27. package/dist/Login.js +45 -0
  28. package/dist/Login.js.map +1 -0
  29. package/dist/NodeEditor.d.ts +11 -0
  30. package/dist/NodeEditor.d.ts.map +1 -0
  31. package/dist/NodeEditor.js +157 -0
  32. package/dist/NodeEditor.js.map +1 -0
  33. package/dist/Tree.d.ts +1 -0
  34. package/dist/Tree.d.ts.map +1 -1
  35. package/dist/Tree.js +8 -27
  36. package/dist/Tree.js.map +1 -1
  37. package/dist/bind/engine.js +1 -1
  38. package/dist/bind/engine.js.map +1 -1
  39. package/dist/bind/eval.d.ts +1 -1
  40. package/dist/bind/eval.d.ts.map +1 -1
  41. package/dist/bind/hook.d.ts +1 -1
  42. package/dist/bind/hook.d.ts.map +1 -1
  43. package/dist/bind/hook.js +1 -1
  44. package/dist/bind/hook.js.map +1 -1
  45. package/dist/cache.d.ts +1 -1
  46. package/dist/cache.d.ts.map +1 -1
  47. package/dist/cache.js +9 -0
  48. package/dist/cache.js.map +1 -1
  49. package/dist/client-tree.d.ts +1 -2
  50. package/dist/client-tree.d.ts.map +1 -1
  51. package/dist/client-tree.js +12 -5
  52. package/dist/client-tree.js.map +1 -1
  53. package/dist/client.d.ts +1 -1
  54. package/dist/client.d.ts.map +1 -1
  55. package/dist/client.js +2 -4
  56. package/dist/client.js.map +1 -1
  57. package/dist/components/ConfirmDialog.d.ts +9 -0
  58. package/dist/components/ConfirmDialog.d.ts.map +1 -0
  59. package/dist/components/ConfirmDialog.js +6 -0
  60. package/dist/components/ConfirmDialog.js.map +1 -0
  61. package/dist/components/ConfirmPopover.d.ts +8 -0
  62. package/dist/components/ConfirmPopover.d.ts.map +1 -0
  63. package/dist/components/ConfirmPopover.js +9 -0
  64. package/dist/components/ConfirmPopover.js.map +1 -0
  65. package/dist/components/PathBreadcrumb.d.ts +5 -0
  66. package/dist/components/PathBreadcrumb.d.ts.map +1 -0
  67. package/dist/components/PathBreadcrumb.js +16 -0
  68. package/dist/components/PathBreadcrumb.js.map +1 -0
  69. package/dist/components/lib/utils.d.ts +3 -0
  70. package/dist/components/lib/utils.d.ts.map +1 -0
  71. package/dist/components/lib/utils.js +6 -0
  72. package/dist/components/lib/utils.js.map +1 -0
  73. package/dist/components/ui/accordion.js +1 -1
  74. package/dist/components/ui/accordion.js.map +1 -1
  75. package/dist/components/ui/alert-dialog.d.ts +19 -0
  76. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  77. package/dist/components/ui/alert-dialog.js +42 -0
  78. package/dist/components/ui/alert-dialog.js.map +1 -0
  79. package/dist/components/ui/badge.js +1 -1
  80. package/dist/components/ui/badge.js.map +1 -1
  81. package/dist/components/ui/breadcrumb.d.ts +12 -0
  82. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  83. package/dist/components/ui/breadcrumb.js +28 -0
  84. package/dist/components/ui/breadcrumb.js.map +1 -0
  85. package/dist/components/ui/button.d.ts +8 -7
  86. package/dist/components/ui/button.d.ts.map +1 -1
  87. package/dist/components/ui/button.js +25 -20
  88. package/dist/components/ui/button.js.map +1 -1
  89. package/dist/components/ui/card.d.ts +10 -0
  90. package/dist/components/ui/card.d.ts.map +1 -0
  91. package/dist/components/ui/card.js +25 -0
  92. package/dist/components/ui/card.js.map +1 -0
  93. package/dist/components/ui/checkbox.js +1 -1
  94. package/dist/components/ui/checkbox.js.map +1 -1
  95. package/dist/components/ui/collapsible.d.ts +6 -0
  96. package/dist/components/ui/collapsible.d.ts.map +1 -0
  97. package/dist/components/ui/collapsible.js +13 -0
  98. package/dist/components/ui/collapsible.js.map +1 -0
  99. package/dist/components/ui/command.d.ts +19 -0
  100. package/dist/components/ui/command.d.ts.map +1 -0
  101. package/dist/components/ui/command.js +35 -0
  102. package/dist/components/ui/command.js.map +1 -0
  103. package/dist/components/ui/dialog.d.ts.map +1 -1
  104. package/dist/components/ui/dialog.js +1 -1
  105. package/dist/components/ui/dialog.js.map +1 -1
  106. package/dist/components/ui/drawer.js +1 -1
  107. package/dist/components/ui/drawer.js.map +1 -1
  108. package/dist/components/ui/dropdown-menu.d.ts +26 -0
  109. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  110. package/dist/components/ui/dropdown-menu.js +52 -0
  111. package/dist/components/ui/dropdown-menu.js.map +1 -0
  112. package/dist/components/ui/form-field.d.ts +7 -0
  113. package/dist/components/ui/form-field.d.ts.map +1 -0
  114. package/dist/components/ui/form-field.js +17 -0
  115. package/dist/components/ui/form-field.js.map +1 -0
  116. package/dist/components/ui/input.js +1 -1
  117. package/dist/components/ui/input.js.map +1 -1
  118. package/dist/components/ui/label.js +1 -1
  119. package/dist/components/ui/label.js.map +1 -1
  120. package/dist/components/ui/pagination.d.ts +14 -0
  121. package/dist/components/ui/pagination.d.ts.map +1 -0
  122. package/dist/components/ui/pagination.js +30 -0
  123. package/dist/components/ui/pagination.js.map +1 -0
  124. package/dist/components/ui/popover.js +2 -2
  125. package/dist/components/ui/popover.js.map +1 -1
  126. package/dist/components/ui/progress.js +1 -1
  127. package/dist/components/ui/progress.js.map +1 -1
  128. package/dist/components/ui/resizable.d.ts +8 -0
  129. package/dist/components/ui/resizable.d.ts.map +1 -0
  130. package/dist/components/ui/resizable.js +14 -0
  131. package/dist/components/ui/resizable.js.map +1 -0
  132. package/dist/components/ui/scroll-area.d.ts +6 -0
  133. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  134. package/dist/components/ui/scroll-area.js +13 -0
  135. package/dist/components/ui/scroll-area.js.map +1 -0
  136. package/dist/components/ui/select.js +1 -1
  137. package/dist/components/ui/select.js.map +1 -1
  138. package/dist/components/ui/separator.d.ts +5 -0
  139. package/dist/components/ui/separator.d.ts.map +1 -0
  140. package/dist/components/ui/separator.js +9 -0
  141. package/dist/components/ui/separator.js.map +1 -0
  142. package/dist/components/ui/sheet.d.ts +15 -0
  143. package/dist/components/ui/sheet.d.ts.map +1 -0
  144. package/dist/components/ui/sheet.js +40 -0
  145. package/dist/components/ui/sheet.js.map +1 -0
  146. package/dist/components/ui/skeleton.d.ts +3 -0
  147. package/dist/components/ui/skeleton.d.ts.map +1 -0
  148. package/dist/components/ui/skeleton.js +7 -0
  149. package/dist/components/ui/skeleton.js.map +1 -0
  150. package/dist/components/ui/slider.js +1 -1
  151. package/dist/components/ui/slider.js.map +1 -1
  152. package/dist/components/ui/switch.js +1 -1
  153. package/dist/components/ui/switch.js.map +1 -1
  154. package/dist/components/ui/table.d.ts +11 -0
  155. package/dist/components/ui/table.d.ts.map +1 -0
  156. package/dist/components/ui/table.js +29 -0
  157. package/dist/components/ui/table.js.map +1 -0
  158. package/dist/components/ui/tabs.d.ts +12 -0
  159. package/dist/components/ui/tabs.d.ts.map +1 -0
  160. package/dist/components/ui/tabs.js +29 -0
  161. package/dist/components/ui/tabs.js.map +1 -0
  162. package/dist/components/ui/textarea.js +2 -2
  163. package/dist/components/ui/textarea.js.map +1 -1
  164. package/dist/components/ui/toggle-group.d.ts +10 -0
  165. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  166. package/dist/components/ui/toggle-group.js +23 -0
  167. package/dist/components/ui/toggle-group.js.map +1 -0
  168. package/dist/components/ui/toggle.d.ts +10 -0
  169. package/dist/components/ui/toggle.d.ts.map +1 -0
  170. package/dist/components/ui/toggle.js +27 -0
  171. package/dist/components/ui/toggle.js.map +1 -0
  172. package/dist/components/ui/tooltip.js +1 -1
  173. package/dist/components/ui/tooltip.js.map +1 -1
  174. package/dist/context/index.d.ts +27 -10
  175. package/dist/context/index.d.ts.map +1 -1
  176. package/dist/context/index.js +43 -36
  177. package/dist/context/index.js.map +1 -1
  178. package/dist/events.d.ts +12 -0
  179. package/dist/events.d.ts.map +1 -0
  180. package/dist/events.js +123 -0
  181. package/dist/events.js.map +1 -0
  182. package/dist/fiber-tree.d.ts +3 -0
  183. package/dist/fiber-tree.d.ts.map +1 -0
  184. package/dist/fiber-tree.js +93 -0
  185. package/dist/fiber-tree.js.map +1 -0
  186. package/dist/hooks.d.ts +14 -2
  187. package/dist/hooks.d.ts.map +1 -1
  188. package/dist/hooks.js +146 -11
  189. package/dist/hooks.js.map +1 -1
  190. package/dist/idb.d.ts +1 -1
  191. package/dist/idb.d.ts.map +1 -1
  192. package/dist/lib/minimd.d.ts.map +1 -1
  193. package/dist/lib/minimd.js +8 -1
  194. package/dist/lib/minimd.js.map +1 -1
  195. package/dist/lib/sanitize-href.d.ts +3 -0
  196. package/dist/lib/sanitize-href.d.ts.map +1 -0
  197. package/dist/lib/sanitize-href.js +14 -0
  198. package/dist/lib/sanitize-href.js.map +1 -0
  199. package/dist/lib/to-plain.d.ts +2 -0
  200. package/dist/lib/to-plain.d.ts.map +1 -0
  201. package/dist/lib/to-plain.js +21 -0
  202. package/dist/lib/to-plain.js.map +1 -0
  203. package/dist/main.d.ts +1 -1
  204. package/dist/main.d.ts.map +1 -1
  205. package/dist/main.js +11 -4
  206. package/dist/main.js.map +1 -1
  207. package/dist/mods/clients.d.ts +3 -0
  208. package/dist/mods/clients.d.ts.map +1 -0
  209. package/dist/mods/clients.js +4 -0
  210. package/dist/mods/clients.js.map +1 -0
  211. package/dist/mods/editor-ui/FieldLabel.d.ts +15 -0
  212. package/dist/mods/editor-ui/FieldLabel.d.ts.map +1 -0
  213. package/dist/mods/editor-ui/FieldLabel.js +56 -0
  214. package/dist/mods/editor-ui/FieldLabel.js.map +1 -0
  215. package/dist/mods/editor-ui/client.d.ts +1 -1
  216. package/dist/mods/editor-ui/client.d.ts.map +1 -1
  217. package/dist/mods/editor-ui/client.js +1 -1
  218. package/dist/mods/editor-ui/client.js.map +1 -1
  219. package/dist/mods/editor-ui/default-edit.d.ts +2 -0
  220. package/dist/mods/editor-ui/default-edit.d.ts.map +1 -0
  221. package/dist/mods/editor-ui/default-edit.js +56 -0
  222. package/dist/mods/editor-ui/default-edit.js.map +1 -0
  223. package/dist/mods/editor-ui/default-view.d.ts +8 -1
  224. package/dist/mods/editor-ui/default-view.d.ts.map +1 -1
  225. package/dist/mods/editor-ui/default-view.js +8 -5
  226. package/dist/mods/editor-ui/default-view.js.map +1 -1
  227. package/dist/mods/editor-ui/dir-view.js +0 -2
  228. package/dist/mods/editor-ui/dir-view.js.map +1 -1
  229. package/dist/mods/editor-ui/empty-placeholder.d.ts +5 -0
  230. package/dist/mods/editor-ui/empty-placeholder.d.ts.map +1 -0
  231. package/dist/mods/editor-ui/empty-placeholder.js +14 -0
  232. package/dist/mods/editor-ui/empty-placeholder.js.map +1 -0
  233. package/dist/mods/editor-ui/form-field.d.ts +17 -0
  234. package/dist/mods/editor-ui/form-field.d.ts.map +1 -0
  235. package/dist/mods/editor-ui/form-field.js +69 -0
  236. package/dist/mods/editor-ui/form-field.js.map +1 -0
  237. package/dist/mods/editor-ui/form-fields.d.ts +1 -2
  238. package/dist/mods/editor-ui/form-fields.d.ts.map +1 -1
  239. package/dist/mods/editor-ui/form-fields.js +56 -60
  240. package/dist/mods/editor-ui/form-fields.js.map +1 -1
  241. package/dist/mods/editor-ui/layout-view.js +3 -2
  242. package/dist/mods/editor-ui/layout-view.js.map +1 -1
  243. package/dist/mods/editor-ui/list-items.js +1 -1
  244. package/dist/mods/editor-ui/list-items.js.map +1 -1
  245. package/dist/mods/editor-ui/node-utils.d.ts +2 -2
  246. package/dist/mods/editor-ui/node-utils.d.ts.map +1 -1
  247. package/dist/mods/editor-ui/node-utils.js +4 -5
  248. package/dist/mods/editor-ui/node-utils.js.map +1 -1
  249. package/dist/mods/editor-ui/type-picker.d.ts +15 -0
  250. package/dist/mods/editor-ui/type-picker.d.ts.map +1 -0
  251. package/dist/mods/editor-ui/type-picker.js +70 -0
  252. package/dist/mods/editor-ui/type-picker.js.map +1 -0
  253. package/dist/mods/editor-ui/user-view.js +1 -1
  254. package/dist/mods/editor-ui/user-view.js.map +1 -1
  255. package/dist/mods/servers.d.ts +1 -0
  256. package/dist/mods/servers.d.ts.map +1 -0
  257. package/dist/mods/servers.js +4 -0
  258. package/dist/mods/servers.js.map +1 -0
  259. package/dist/mods/treenity/groups/index.js +1 -1
  260. package/dist/mods/treenity/groups/index.js.map +1 -1
  261. package/dist/mods/treenity/preview.d.ts.map +1 -1
  262. package/dist/mods/treenity/preview.js +3 -4
  263. package/dist/mods/treenity/preview.js.map +1 -1
  264. package/dist/mods/treenity/ref-view.js +3 -2
  265. package/dist/mods/treenity/ref-view.js.map +1 -1
  266. package/dist/mods/treenity/schema-form.js +1 -1
  267. package/dist/mods/treenity/schema-form.js.map +1 -1
  268. package/dist/mods/treenity/seed.js +3 -2
  269. package/dist/mods/treenity/seed.js.map +1 -1
  270. package/dist/mods/treenity/type-view.js +1 -1
  271. package/dist/mods/treenity/type-view.js.map +1 -1
  272. package/dist/schema-loader.d.ts +1 -1
  273. package/dist/schema-loader.d.ts.map +1 -1
  274. package/dist/schema-loader.js +1 -1
  275. package/dist/schema-loader.js.map +1 -1
  276. package/dist/symbols.d.ts +5 -0
  277. package/dist/symbols.d.ts.map +1 -0
  278. package/dist/symbols.js +22 -0
  279. package/dist/symbols.js.map +1 -0
  280. package/dist/trpc.d.ts +10 -3
  281. package/dist/trpc.d.ts.map +1 -1
  282. package/package.json +76 -8
  283. package/src/AclEditor.tsx +11 -18
  284. package/src/ActionCards.tsx +224 -0
  285. package/src/App.tsx +232 -385
  286. package/src/ComponentSection.tsx +113 -0
  287. package/src/ErrorBoundary.tsx +40 -0
  288. package/src/Inspector.css +54 -0
  289. package/src/Inspector.tsx +73 -793
  290. package/src/Login.tsx +97 -0
  291. package/src/NodeEditor.tsx +300 -0
  292. package/src/Tree.css +91 -0
  293. package/src/Tree.tsx +40 -43
  294. package/src/bind/engine.ts +1 -1
  295. package/src/bind/eval.ts +1 -1
  296. package/src/bind/hook.ts +1 -1
  297. package/src/bind/pipes.ts +1 -1
  298. package/src/cache.ts +12 -1
  299. package/src/client-tree.ts +18 -12
  300. package/src/client.ts +2 -4
  301. package/src/components/ConfirmDialog.tsx +34 -0
  302. package/src/components/ConfirmPopover.tsx +41 -0
  303. package/src/components/PathBreadcrumb.tsx +36 -0
  304. package/src/components/lib/utils.ts +6 -0
  305. package/src/components/lib/utils.ts.bak +6 -0
  306. package/src/components/ui/accordion.tsx +1 -1
  307. package/src/components/ui/alert-dialog.tsx +189 -0
  308. package/src/components/ui/badge.tsx +1 -1
  309. package/src/components/ui/breadcrumb.tsx +108 -0
  310. package/src/components/ui/button.tsx +51 -30
  311. package/src/components/ui/card.tsx +91 -0
  312. package/src/components/ui/checkbox.tsx +1 -1
  313. package/src/components/ui/collapsible.tsx +31 -0
  314. package/src/components/ui/command.tsx +177 -0
  315. package/src/components/ui/dialog.tsx +1 -2
  316. package/src/components/ui/drawer.tsx +1 -1
  317. package/src/components/ui/dropdown-menu.tsx +256 -0
  318. package/src/components/ui/form-field.tsx +37 -0
  319. package/src/components/ui/input.tsx +1 -1
  320. package/src/components/ui/label.tsx +1 -1
  321. package/src/components/ui/pagination.tsx +122 -0
  322. package/src/components/ui/popover.tsx +2 -2
  323. package/src/components/ui/progress.tsx +1 -1
  324. package/src/components/ui/resizable.tsx +47 -0
  325. package/src/components/ui/scroll-area.tsx +55 -0
  326. package/src/components/ui/select.tsx +1 -1
  327. package/src/components/ui/separator.tsx +27 -0
  328. package/src/components/ui/sheet.tsx +140 -0
  329. package/src/components/ui/skeleton.tsx +13 -0
  330. package/src/components/ui/slider.tsx +1 -1
  331. package/src/components/ui/switch.tsx +1 -1
  332. package/src/components/ui/table.tsx +115 -0
  333. package/src/components/ui/tabs.tsx +88 -0
  334. package/src/components/ui/textarea.tsx +2 -2
  335. package/src/components/ui/toggle-group.tsx +82 -0
  336. package/src/components/ui/toggle.tsx +46 -0
  337. package/src/components/ui/tooltip.tsx +1 -1
  338. package/src/context/index.tsx +75 -42
  339. package/src/events.ts +121 -0
  340. package/src/fiber-tree.ts +112 -0
  341. package/src/hooks.ts +161 -13
  342. package/src/idb.ts +1 -1
  343. package/src/lib/minimd.ts +7 -1
  344. package/src/lib/sanitize-href.ts +13 -0
  345. package/src/lib/to-plain.ts +21 -0
  346. package/src/main.tsx +14 -4
  347. package/src/mods/clients.ts +3 -0
  348. package/src/mods/editor-ui/FieldLabel.tsx +125 -0
  349. package/src/mods/editor-ui/client.ts +1 -1
  350. package/src/mods/editor-ui/default-edit.tsx +101 -0
  351. package/src/mods/editor-ui/default-view.tsx +13 -8
  352. package/src/mods/editor-ui/dir-view.tsx +2 -2
  353. package/src/mods/editor-ui/editor-ui.css +174 -0
  354. package/src/mods/editor-ui/empty-placeholder.tsx +39 -0
  355. package/src/mods/editor-ui/form-field.tsx +146 -0
  356. package/src/mods/editor-ui/form-fields.tsx +132 -113
  357. package/src/mods/editor-ui/layout-view.tsx +4 -2
  358. package/src/mods/editor-ui/list-items.tsx +2 -2
  359. package/src/mods/editor-ui/node-utils.ts +4 -5
  360. package/src/mods/editor-ui/type-picker.tsx +148 -0
  361. package/src/mods/editor-ui/user-view.tsx +1 -1
  362. package/src/mods/servers.ts +2 -0
  363. package/src/mods/treenity/groups/index.tsx +1 -1
  364. package/src/mods/treenity/preview.tsx +7 -8
  365. package/src/mods/treenity/ref-view.tsx +12 -7
  366. package/src/mods/treenity/schema-form.tsx +1 -1
  367. package/src/mods/treenity/seed.ts +3 -2
  368. package/src/mods/treenity/type-view.tsx +1 -1
  369. package/src/remote-tree.ts +1 -1
  370. package/src/root.css +117 -0
  371. package/src/schema-loader.ts +1 -1
  372. package/src/symbols.ts +25 -0
  373. package/src/bind/bind.test.ts +0 -316
  374. package/src/cache.test.ts +0 -139
  375. package/src/client-tree.test.ts +0 -116
  376. package/src/index.html +0 -14
  377. package/src/remote-tree.test.ts +0 -142
  378. package/src/style.css +0 -1269
  379. package/src/vite-env.d.ts +0 -3
package/src/AclEditor.tsx CHANGED
@@ -1,7 +1,8 @@
1
1
  import { Button } from '#components/ui/button';
2
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '#components/ui/collapsible';
2
3
  import { Input } from '#components/ui/input';
3
- import { A, type GroupPerm, R, S, W } from '@treenity/core/core';
4
- import { ChevronDown, ChevronRight, X } from 'lucide-react';
4
+ import { A, type GroupPerm, R, S, W } from '@treenity/core';
5
+ import { ChevronRight, X } from 'lucide-react';
5
6
  import { useMemo, useState } from 'react';
6
7
  import * as cache from './cache';
7
8
 
@@ -136,7 +137,6 @@ function ancestorChain(path: string): { path: string; owner?: string; acl?: Grou
136
137
  }
137
138
 
138
139
  export function AclEditor({ path, owner, rules, currentUserId, onChange }: Props) {
139
- const [open, setOpen] = useState(false);
140
140
  const [newGroup, setNewGroup] = useState('');
141
141
  const chain = useMemo(() => ancestorChain(path), [path]);
142
142
 
@@ -162,11 +162,8 @@ export function AclEditor({ path, owner, rules, currentUserId, onChange }: Props
162
162
  }
163
163
 
164
164
  return (
165
- <div className="card">
166
- <div
167
- className="card-header cursor-pointer select-none"
168
- onClick={() => setOpen((v) => !v)}
169
- >
165
+ <Collapsible className="border-t border-border mt-2 pt-0.5 first:border-t-0 first:mt-0 first:pt-0">
166
+ <CollapsibleTrigger className="flex w-full items-center justify-between py-2 pb-1.5 text-[11px] font-semibold text-muted-foreground uppercase tracking-wider cursor-pointer select-none">
170
167
  <span>Access Control</span>
171
168
  <span className="flex items-center gap-2 normal-case tracking-normal font-normal">
172
169
  {effective && (
@@ -192,15 +189,11 @@ export function AclEditor({ path, owner, rules, currentUserId, onChange }: Props
192
189
  </span>
193
190
  </span>
194
191
  )}
195
- {open ? (
196
- <ChevronDown className="h-3 w-3" />
197
- ) : (
198
- <ChevronRight className="h-3 w-3" />
199
- )}
192
+ <ChevronRight className="h-3 w-3 transition-transform duration-200 group-data-[state=open]:rotate-90" />
200
193
  </span>
201
- </div>
202
- {open && (
203
- <div className="card-body space-y-3">
194
+ </CollapsibleTrigger>
195
+ <CollapsibleContent>
196
+ <div className="py-0.5 pb-2.5 space-y-3">
204
197
  <div className="field">
205
198
  <label className="text-xs text-muted-foreground">$owner</label>
206
199
  <Input value={owner} onChange={(e) => onChange(e.target.value, rules)} />
@@ -258,8 +251,8 @@ export function AclEditor({ path, owner, rules, currentUserId, onChange }: Props
258
251
  </div>
259
252
  )}
260
253
  </div>
261
- )}
262
- </div>
254
+ </CollapsibleContent>
255
+ </Collapsible>
263
256
  );
264
257
  }
265
258
 
@@ -0,0 +1,224 @@
1
+ // ActionCards — action pill buttons with expandable params, run, and results
2
+
3
+ import { Button } from '#components/ui/button';
4
+ import { Checkbox } from '#components/ui/checkbox';
5
+ import { Input } from '#components/ui/input';
6
+ import { Render } from '#context';
7
+ import { getActions, getActionSchema } from '#mods/editor-ui/node-utils';
8
+ import type { ComponentData, NodeData } from '@treenity/core';
9
+ import { useState } from 'react';
10
+ import * as cache from './cache';
11
+ import { useSchema } from './schema-loader';
12
+ import { trpc } from './trpc';
13
+
14
+ function ResultView({ value }: { value: unknown }) {
15
+ if (value === undefined || value === null) return null;
16
+ if (typeof value !== 'object')
17
+ return <span className="font-mono text-[11px]">{String(value)}</span>;
18
+
19
+ if ('$type' in (value as Record<string, unknown>)) {
20
+ return <Render value={value as ComponentData} />;
21
+ }
22
+
23
+ const entries = Object.entries(value as Record<string, unknown>);
24
+ if (entries.length === 0) return <span className="text-muted-foreground text-[11px]">empty</span>;
25
+
26
+ return (
27
+ <div className="flex flex-col gap-0.5">
28
+ {entries.map(([k, v]) => (
29
+ <div key={k} className="flex gap-2 text-[11px]">
30
+ <span className="text-muted-foreground shrink-0">{k}</span>
31
+ <span className="font-mono text-foreground/80 truncate">
32
+ {typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '')}
33
+ </span>
34
+ </div>
35
+ ))}
36
+ </div>
37
+ );
38
+ }
39
+
40
+ export function ActionCardList({
41
+ path,
42
+ componentName,
43
+ compType,
44
+ toast,
45
+ onActionComplete,
46
+ }: {
47
+ path: string;
48
+ componentName: string;
49
+ compType: string;
50
+ compData: Record<string, unknown>;
51
+ toast: (msg: string) => void;
52
+ onActionComplete?: () => void;
53
+ }) {
54
+ const schema = useSchema(compType);
55
+ const [expanded, setExpanded] = useState<string | null>(null);
56
+ const [paramsText, setParamsText] = useState<Record<string, string>>({});
57
+ const [schemaData, setSchemaData] = useState<Record<string, Record<string, unknown>>>({});
58
+ const [running, setRunning] = useState<string | null>(null);
59
+ const [results, setResults] = useState<Record<string, { ok: boolean; value: unknown }>>({});
60
+ const [resultMode, setResultMode] = useState<Record<string, 'pretty' | 'json'>>({});
61
+
62
+ if (schema === undefined) return null;
63
+
64
+ const actions = getActions(compType, schema);
65
+ if (actions.length === 0) return null;
66
+
67
+ async function run(a: string) {
68
+ setRunning(a);
69
+ try {
70
+ const actionSchema = getActionSchema(compType, a);
71
+ let data: unknown = {};
72
+ if (actionSchema) {
73
+ data = schemaData[a] ?? {};
74
+ } else {
75
+ const raw = (paramsText[a] ?? '').trim();
76
+ if (raw && raw !== '{}') {
77
+ try { data = JSON.parse(raw); }
78
+ catch { toast('Invalid JSON params'); setRunning(null); return; }
79
+ }
80
+ }
81
+ const result = await trpc.execute.mutate({ path, key: componentName, action: a, data });
82
+ const fresh = (await trpc.get.query({ path, watch: true })) as NodeData | undefined;
83
+ if (fresh) cache.put(fresh);
84
+ onActionComplete?.();
85
+ setResults((prev) => ({ ...prev, [a]: { ok: true, value: result } }));
86
+ setExpanded(a);
87
+ } catch (e) {
88
+ setResults((prev) => ({
89
+ ...prev,
90
+ [a]: { ok: false, value: e instanceof Error ? e.message : String(e) },
91
+ }));
92
+ setExpanded(a);
93
+ } finally {
94
+ setRunning(null);
95
+ }
96
+ }
97
+
98
+ return (
99
+ <div className="mt-2.5 pt-2.5 border-t border-border">
100
+ <div className="flex flex-wrap gap-1.5">
101
+ {actions.map((a) => (
102
+ <Button
103
+ key={a}
104
+ variant="outline"
105
+ size="sm"
106
+ className={`h-6 rounded-full font-mono text-[11px] text-green-300 bg-green-400/10 border-green-400/40 hover:bg-green-400/20 hover:border-green-400/60 ${expanded === a ? 'bg-green-400/20 border-green-300' : ''} ${running === a ? 'opacity-60 pointer-events-none' : ''}`}
107
+ onClick={() => setExpanded(expanded === a ? null : a)}
108
+ >
109
+ {running === a ? '...' : a}
110
+ {results[a] && !results[a].ok && expanded !== a && (
111
+ <span className="ml-1 text-destructive">!</span>
112
+ )}
113
+ {results[a]?.ok && expanded !== a && (
114
+ <span className="ml-1 text-primary/60">✓</span>
115
+ )}
116
+ </Button>
117
+ ))}
118
+ </div>
119
+
120
+ {expanded && (() => {
121
+ const a = expanded;
122
+ const actionSchema = getActionSchema(compType, a);
123
+ const hasParams = actionSchema !== null && Object.keys(actionSchema.properties).length > 0;
124
+ const noParams = actionSchema !== null && Object.keys(actionSchema.properties).length === 0;
125
+ const result = results[a];
126
+ const mode = resultMode[a] ?? 'pretty';
127
+
128
+ return (
129
+ <div className="mt-2 p-2 px-2.5 border border-border rounded-md bg-card">
130
+ {hasParams && (
131
+ <div className="flex flex-col gap-1.5 mb-2">
132
+ {Object.entries(actionSchema!.properties).map(([field, prop]) => {
133
+ const p = prop as { type: string; title?: string; format?: string };
134
+ const val = (schemaData[a] ?? {})[field];
135
+ const setField = (v: unknown) =>
136
+ setSchemaData((prev) => ({
137
+ ...prev,
138
+ [a]: { ...(prev[a] ?? {}), [field]: v },
139
+ }));
140
+ return (
141
+ <div key={field} className="flex flex-col gap-0.5">
142
+ <label>{p.title ?? field}</label>
143
+ {p.type === 'number' || p.format === 'number' ? (
144
+ <Input type="number" className="h-7 text-xs" value={String(val ?? 0)}
145
+ onChange={(e) => setField(Number(e.target.value))} />
146
+ ) : p.type === 'boolean' ? (
147
+ <label className="flex items-center gap-1.5 cursor-pointer">
148
+ <Checkbox checked={!!val}
149
+ onChange={(e) => setField((e.target as HTMLInputElement).checked)} />
150
+ <span className="text-[11px]">{val ? 'true' : 'false'}</span>
151
+ </label>
152
+ ) : (
153
+ <Input className="h-7 text-xs" value={String(val ?? '')}
154
+ onChange={(e) => setField(e.target.value)} />
155
+ )}
156
+ </div>
157
+ );
158
+ })}
159
+ </div>
160
+ )}
161
+
162
+ {!hasParams && !noParams && (
163
+ <textarea
164
+ className="min-h-12 text-[11px] mb-2"
165
+ value={paramsText[a] ?? '{}'}
166
+ onChange={(e) => setParamsText((prev) => ({ ...prev, [a]: e.target.value }))}
167
+ spellCheck={false}
168
+ rows={2}
169
+ />
170
+ )}
171
+
172
+ <Button
173
+ size="sm"
174
+ className="h-6 rounded-full text-[11px] font-medium"
175
+ disabled={running !== null}
176
+ onClick={() => run(a)}
177
+ >
178
+ {running === a ? '...' : '▶'} {a}
179
+ </Button>
180
+
181
+ {result && (
182
+ <div className={`mt-2 p-1.5 px-2 rounded-md bg-background border ${result.ok ? 'border-border' : 'border-destructive/40 bg-destructive/5'}`}>
183
+ {!result.ok ? (
184
+ <span className="text-destructive font-mono text-[11px]">{String(result.value)}</span>
185
+ ) : result.value === undefined || result.value === null ? (
186
+ <span className="text-primary text-[11px]">✓ done</span>
187
+ ) : (
188
+ <>
189
+ <div className="flex items-center justify-between mb-1">
190
+ <span className="text-[10px] text-muted-foreground uppercase tracking-wider">Result</span>
191
+ {typeof result.value === 'object' && (
192
+ <div className="flex gap-0.5">
193
+ <Button
194
+ variant={mode === 'pretty' ? 'secondary' : 'ghost'}
195
+ size="sm"
196
+ className="h-5 px-1.5 text-[10px] rounded-full"
197
+ onClick={() => setResultMode((p) => ({ ...p, [a]: 'pretty' }))}
198
+ >View</Button>
199
+ <Button
200
+ variant={mode === 'json' ? 'secondary' : 'ghost'}
201
+ size="sm"
202
+ className="h-5 px-1.5 text-[10px] rounded-full"
203
+ onClick={() => setResultMode((p) => ({ ...p, [a]: 'json' }))}
204
+ >JSON</Button>
205
+ </div>
206
+ )}
207
+ </div>
208
+ {mode === 'json' ? (
209
+ <pre className="text-[11px] font-mono text-foreground/60 whitespace-pre-wrap break-all leading-relaxed">
210
+ {JSON.stringify(result.value, null, 2)}
211
+ </pre>
212
+ ) : (
213
+ <ResultView value={result.value} />
214
+ )}
215
+ </>
216
+ )}
217
+ </div>
218
+ )}
219
+ </div>
220
+ );
221
+ })()}
222
+ </div>
223
+ );
224
+ }