@alepha/ui 0.18.2 → 0.19.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 (257) hide show
  1. package/dist/admin/{AdminApiKeys-BJhIwfD6.js → AdminApiKeys-Bt1PjO6o.js} +3 -4
  2. package/dist/admin/{AdminApiKeys-BJhIwfD6.js.map → AdminApiKeys-Bt1PjO6o.js.map} +1 -1
  3. package/dist/admin/{AdminAudits-DzD_4cDt.js → AdminAudits-C7c1CN4c.js} +3 -4
  4. package/dist/admin/{AdminAudits-DzD_4cDt.js.map → AdminAudits-C7c1CN4c.js.map} +1 -1
  5. package/dist/admin/{AdminDashboard-C92tIc6x.js → AdminDashboard-C3RXpTp6.js} +3 -4
  6. package/dist/admin/{AdminDashboard-C92tIc6x.js.map → AdminDashboard-C3RXpTp6.js.map} +1 -1
  7. package/dist/admin/{AdminFiles-DLpfhBkf.js → AdminFiles-31ivR6Wq.js} +3 -4
  8. package/dist/admin/{AdminFiles-DLpfhBkf.js.map → AdminFiles-31ivR6Wq.js.map} +1 -1
  9. package/dist/admin/{AdminJobDashboard-KIOkeMgE.js → AdminJobDashboard-BABLe7hL.js} +73 -25
  10. package/dist/admin/AdminJobDashboard-BABLe7hL.js.map +1 -0
  11. package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js → AdminJobExecutions-D-G8RIlr.js} +3 -4
  12. package/dist/admin/{AdminJobExecutions-D0Yo_PU0.js.map → AdminJobExecutions-D-G8RIlr.js.map} +1 -1
  13. package/dist/admin/{AdminJobRegistry-PFajqaGK.js → AdminJobRegistry-oIS3K9NX.js} +3 -4
  14. package/dist/admin/{AdminJobRegistry-PFajqaGK.js.map → AdminJobRegistry-oIS3K9NX.js.map} +1 -1
  15. package/dist/admin/{AdminLayout-B1DXZHDn.js → AdminLayout-BmZ9mtXh.js} +8 -25
  16. package/dist/admin/AdminLayout-BmZ9mtXh.js.map +1 -0
  17. package/dist/admin/AdminNotifications-DHdzksww.js +541 -0
  18. package/dist/admin/AdminNotifications-DHdzksww.js.map +1 -0
  19. package/dist/admin/{AdminParameters-BspPeqp_.js → AdminParameters-CyZQSXnN.js} +118 -112
  20. package/dist/admin/AdminParameters-CyZQSXnN.js.map +1 -0
  21. package/dist/admin/{AdminSessions-BnH5CZQl.js → AdminSessions--xwELDSO.js} +3 -4
  22. package/dist/admin/{AdminSessions-BnH5CZQl.js.map → AdminSessions--xwELDSO.js.map} +1 -1
  23. package/dist/admin/{AdminUserLayout-DUbC6-BI.js → AdminUserLayout-DvBTG5gd.js} +82 -115
  24. package/dist/admin/AdminUserLayout-DvBTG5gd.js.map +1 -0
  25. package/dist/admin/{AdminUserProfile-DuTUnjdG.js → AdminUserProfile-CzsPBl6Z.js} +7 -6
  26. package/dist/admin/AdminUserProfile-CzsPBl6Z.js.map +1 -0
  27. package/dist/admin/{AdminUserSessions-DvZdAGpL.js → AdminUserSessions-C-aUnhVN.js} +3 -4
  28. package/dist/admin/{AdminUserSessions-DvZdAGpL.js.map → AdminUserSessions-C-aUnhVN.js.map} +1 -1
  29. package/dist/admin/{AdminUsers-CR9z0g_5.js → AdminUsers-BYwei5sj.js} +4 -4
  30. package/dist/admin/AdminUsers-BYwei5sj.js.map +1 -0
  31. package/dist/admin/{AuthLayout-DsUfp9RG.js → AuthLayout-CkPGLJku.js} +3 -4
  32. package/dist/admin/{AuthLayout-DsUfp9RG.js.map → AuthLayout-CkPGLJku.js.map} +1 -1
  33. package/dist/{demo/IconGoogle-CSQLPYwX.js → admin/IconGoogle-8Nkx6yax.js} +2 -4
  34. package/dist/admin/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
  35. package/dist/admin/Login-DSBqNsZc.js +274 -0
  36. package/dist/admin/Login-DSBqNsZc.js.map +1 -0
  37. package/dist/admin/{Profile-B2EcIDB9.js → Profile-CDRjJo0P.js} +31 -29
  38. package/dist/admin/Profile-CDRjJo0P.js.map +1 -0
  39. package/dist/admin/{Register-Z3fxRbUF.js → Register-4QGFOnfh.js} +201 -146
  40. package/dist/admin/Register-4QGFOnfh.js.map +1 -0
  41. package/dist/admin/{ResetPassword-_Y1qTTKh.js → ResetPassword-Gxc9L_mY.js} +9 -10
  42. package/dist/admin/ResetPassword-Gxc9L_mY.js.map +1 -0
  43. package/dist/admin/{VerifyEmail-Bg22bwcC.js → VerifyEmail-D7G5NnaN.js} +25 -11
  44. package/dist/admin/VerifyEmail-D7G5NnaN.js.map +1 -0
  45. package/dist/admin/adminUserAtom-DCi4wf-v.js +11 -0
  46. package/dist/admin/adminUserAtom-DCi4wf-v.js.map +1 -0
  47. package/dist/admin/{core-BVO_TQxb.js → core-D1AbU50V.js} +662 -570
  48. package/dist/admin/core-D1AbU50V.js.map +1 -0
  49. package/dist/admin/index.d.ts +141 -53
  50. package/dist/admin/index.d.ts.map +1 -1
  51. package/dist/admin/index.js +67 -49
  52. package/dist/admin/index.js.map +1 -1
  53. package/dist/admin/rolldown-runtime-CiIaOW0V.js +13 -0
  54. package/dist/{demo/AuthLayout-DN-ClJQk.js → auth/AuthLayout-CfRKcTqP.js} +3 -4
  55. package/dist/auth/{AuthLayout-C161NeF6.js.map → AuthLayout-CfRKcTqP.js.map} +1 -1
  56. package/dist/{admin/IconGoogle-Ch1m3Uzl.js → auth/IconGoogle-8Nkx6yax.js} +2 -4
  57. package/dist/auth/{IconGoogle-Ch1m3Uzl.js.map → IconGoogle-8Nkx6yax.js.map} +1 -1
  58. package/dist/auth/Login-DJyweoPS.js +274 -0
  59. package/dist/auth/Login-DJyweoPS.js.map +1 -0
  60. package/dist/auth/{Profile-BMpXJ0oi.js → Profile-Cy93pNTw.js} +31 -29
  61. package/dist/auth/Profile-Cy93pNTw.js.map +1 -0
  62. package/dist/auth/{Register-2gx8qll-.js → Register-CSqzzitW.js} +201 -146
  63. package/dist/auth/Register-CSqzzitW.js.map +1 -0
  64. package/dist/{demo/ResetPassword-CAPj8MO3.js → auth/ResetPassword-B61QPlQi.js} +9 -10
  65. package/dist/auth/ResetPassword-B61QPlQi.js.map +1 -0
  66. package/dist/{demo/VerifyEmail-DFmdCdYs.js → auth/VerifyEmail-CqBJ11id.js} +25 -11
  67. package/dist/auth/VerifyEmail-CqBJ11id.js.map +1 -0
  68. package/dist/auth/{core-DyfeVr5c.js → core-C6D3pazL.js} +403 -343
  69. package/dist/auth/core-C6D3pazL.js.map +1 -0
  70. package/dist/auth/index.d.ts +93 -54
  71. package/dist/auth/index.d.ts.map +1 -1
  72. package/dist/auth/index.js +30 -31
  73. package/dist/auth/index.js.map +1 -1
  74. package/dist/auth/rolldown-runtime-CiIaOW0V.js +13 -0
  75. package/dist/core/index.d.ts +123 -62
  76. package/dist/core/index.d.ts.map +1 -1
  77. package/dist/core/index.js +878 -776
  78. package/dist/core/index.js.map +1 -1
  79. package/dist/{auth/AuthLayout-C161NeF6.js → demo/AuthLayout-Dq5tSLSc.js} +3 -4
  80. package/dist/demo/{AuthLayout-DN-ClJQk.js.map → AuthLayout-Dq5tSLSc.js.map} +1 -1
  81. package/dist/demo/DemoButton-_Ws2w-J0.js +181 -0
  82. package/dist/demo/DemoButton-_Ws2w-J0.js.map +1 -0
  83. package/dist/demo/DemoControlSelect-ChP4ZOpQ.js +304 -0
  84. package/dist/demo/DemoControlSelect-ChP4ZOpQ.js.map +1 -0
  85. package/dist/demo/DemoDataTable-Hwf_UUni.js +361 -0
  86. package/dist/demo/DemoDataTable-Hwf_UUni.js.map +1 -0
  87. package/dist/demo/{DemoDialog-DW8QEvD1.js → DemoDialog-B01OMVRd.js} +3 -4
  88. package/dist/demo/{DemoDialog-DW8QEvD1.js.map → DemoDialog-B01OMVRd.js.map} +1 -1
  89. package/dist/demo/{DemoFlex-CAhLUanT.js → DemoFlex-870PEl0V.js} +4 -5
  90. package/dist/demo/{DemoFlex-CAhLUanT.js.map → DemoFlex-870PEl0V.js.map} +1 -1
  91. package/dist/demo/{DemoHeading-yIFmNjHB.js → DemoHeading-C1YR27fz.js} +4 -5
  92. package/dist/demo/{DemoHeading-yIFmNjHB.js.map → DemoHeading-C1YR27fz.js.map} +1 -1
  93. package/dist/demo/{DemoHome-BSGuBHus.js → DemoHome-DRbL2eGf.js} +4 -5
  94. package/dist/demo/{DemoHome-BSGuBHus.js.map → DemoHome-DRbL2eGf.js.map} +1 -1
  95. package/dist/demo/{DemoJsonViewer-DsA2IpgV.js → DemoJsonViewer-DoABiqBW.js} +4 -5
  96. package/dist/demo/{DemoJsonViewer-DsA2IpgV.js.map → DemoJsonViewer-DoABiqBW.js.map} +1 -1
  97. package/dist/demo/{DemoLayout-Cy6xjn6P.js → DemoLayout-CN_PDCX2.js} +16 -8
  98. package/dist/demo/DemoLayout-CN_PDCX2.js.map +1 -0
  99. package/dist/demo/{DemoLogin-vqxgTu4P.js → DemoLogin-B5x-ug3Q.js} +51 -35
  100. package/dist/demo/DemoLogin-B5x-ug3Q.js.map +1 -0
  101. package/dist/demo/{DemoRegister-YHPvPg77.js → DemoRegister-Q6sg2xuV.js} +51 -53
  102. package/dist/demo/DemoRegister-Q6sg2xuV.js.map +1 -0
  103. package/dist/demo/{DemoResetPassword-mOW18Zlm.js → DemoResetPassword-DrqZfmEw.js} +14 -19
  104. package/dist/demo/DemoResetPassword-DrqZfmEw.js.map +1 -0
  105. package/dist/demo/{DemoSidebar-od7aLjP_.js → DemoSidebar-CfKS6w1o.js} +4 -5
  106. package/dist/demo/{DemoSidebar-od7aLjP_.js.map → DemoSidebar-CfKS6w1o.js.map} +1 -1
  107. package/dist/demo/{DemoText-DU3JeRS0.js → DemoText-pT6Gi5b5.js} +4 -5
  108. package/dist/demo/{DemoText-DU3JeRS0.js.map → DemoText-pT6Gi5b5.js.map} +1 -1
  109. package/dist/demo/{DemoToast-CUJEiPRa.js → DemoToast-I13NBzQQ.js} +3 -4
  110. package/dist/demo/{DemoToast-CUJEiPRa.js.map → DemoToast-I13NBzQQ.js.map} +1 -1
  111. package/dist/demo/{DemoTypeForm-C1dNkahD.js → DemoTypeForm-BqzcrtvN.js} +9 -6
  112. package/dist/demo/DemoTypeForm-BqzcrtvN.js.map +1 -0
  113. package/dist/demo/DemoVerifyEmail-HwD8xfQw.js +33 -0
  114. package/dist/demo/DemoVerifyEmail-HwD8xfQw.js.map +1 -0
  115. package/dist/{auth/IconGoogle-Ch1m3Uzl.js → demo/IconGoogle-CwQy4G9y.js} +2 -4
  116. package/dist/demo/{IconGoogle-CSQLPYwX.js.map → IconGoogle-CwQy4G9y.js.map} +1 -1
  117. package/dist/demo/Login-CqG1iJbn.js +274 -0
  118. package/dist/demo/Login-CqG1iJbn.js.map +1 -0
  119. package/dist/demo/{Profile-BE_Y3co2.js → Profile-C0ojJCaG.js} +31 -29
  120. package/dist/demo/Profile-C0ojJCaG.js.map +1 -0
  121. package/dist/demo/{Register-fXHmBpr3.js → Register-KKZwr_lL.js} +201 -146
  122. package/dist/demo/Register-KKZwr_lL.js.map +1 -0
  123. package/dist/{auth/ResetPassword-DBxt9hKk.js → demo/ResetPassword-DMrLFEtr.js} +9 -10
  124. package/dist/demo/ResetPassword-DMrLFEtr.js.map +1 -0
  125. package/dist/demo/{Showcase-BtEU0pY9.js → Showcase-D49Wud2v.js} +65 -68
  126. package/dist/demo/Showcase-D49Wud2v.js.map +1 -0
  127. package/dist/{auth/VerifyEmail-Z80Ubajk.js → demo/VerifyEmail-BFCAFz6T.js} +25 -11
  128. package/dist/demo/VerifyEmail-BFCAFz6T.js.map +1 -0
  129. package/dist/demo/{auth-Djd7SKiw.js → auth-D9qTZzCa.js} +18 -35
  130. package/dist/demo/{auth-Djd7SKiw.js.map → auth-D9qTZzCa.js.map} +1 -1
  131. package/dist/demo/{core-B7LNjM78.js → core-DRtQklr3.js} +752 -647
  132. package/dist/demo/core-DRtQklr3.js.map +1 -0
  133. package/dist/demo/index.d.ts +1 -0
  134. package/dist/demo/index.d.ts.map +1 -1
  135. package/dist/demo/index.js +25 -22
  136. package/dist/demo/index.js.map +1 -1
  137. package/dist/demo/rolldown-runtime-CiIaOW0V.js +13 -0
  138. package/package.json +19 -19
  139. package/src/admin/AdminRouter.tsx +42 -2
  140. package/src/admin/atoms/adminUserAtom.ts +7 -0
  141. package/src/admin/components/AdminLayout.tsx +2 -14
  142. package/src/admin/components/jobs/AdminJobDashboard.tsx +51 -20
  143. package/src/admin/components/notifications/AdminNotifications.tsx +519 -0
  144. package/src/admin/components/parameters/ParameterDetails.tsx +12 -270
  145. package/src/admin/components/parameters/ParameterDetailsConfigForm.tsx +238 -0
  146. package/src/admin/components/parameters/ParameterDetailsLoading.tsx +24 -0
  147. package/src/admin/components/parameters/ParameterHistory.tsx +10 -11
  148. package/src/admin/components/parameters/ParameterTree.tsx +28 -184
  149. package/src/admin/components/parameters/ParameterTreeNode.tsx +151 -0
  150. package/src/admin/components/shared/AdminResourceHeader.tsx +2 -25
  151. package/src/admin/components/shared/AdminResourceHeaderMenuItem.tsx +37 -0
  152. package/src/admin/components/shared/AdminResourceTabs.tsx +2 -26
  153. package/src/admin/components/shared/AdminResourceTabsItem.tsx +36 -0
  154. package/src/admin/components/users/AdminUserLayout.tsx +84 -127
  155. package/src/admin/components/users/AdminUserProfile.tsx +5 -2
  156. package/src/admin/components/users/AdminUsers.tsx +1 -1
  157. package/src/auth/components/Login.tsx +188 -121
  158. package/src/auth/components/Profile.tsx +1 -22
  159. package/src/auth/components/ProfileField.tsx +39 -0
  160. package/src/auth/components/Register.tsx +215 -158
  161. package/src/auth/components/ResetPassword.tsx +7 -11
  162. package/src/auth/components/VerifyEmail.tsx +35 -10
  163. package/src/auth/components/buttons/UserButton.tsx +19 -21
  164. package/src/auth/index.ts +1 -0
  165. package/src/core/components/Flex.tsx +34 -0
  166. package/src/core/components/buttons/ActionButton.tsx +105 -78
  167. package/src/core/components/data/DetailDrawer.tsx +102 -96
  168. package/src/core/components/data/DetailList.tsx +2 -1
  169. package/src/core/components/dialogs/PromptDialog.tsx +1 -1
  170. package/src/core/components/layout/Breadcrumb.tsx +4 -7
  171. package/src/core/components/layout/DashboardShell.tsx +18 -4
  172. package/src/core/components/layout/Sidebar.tsx +16 -241
  173. package/src/core/components/layout/SidebarCollapsedItem.tsx +91 -0
  174. package/src/core/components/layout/SidebarItem.tsx +146 -0
  175. package/src/core/components/layout/index.ts +3 -1
  176. package/src/core/form/components/Control.tsx +31 -29
  177. package/src/core/form/components/ControlArray.tsx +13 -39
  178. package/src/core/form/components/ControlDate.tsx +10 -21
  179. package/src/core/form/components/ControlNumber.tsx +4 -33
  180. package/src/core/form/components/ControlQueryBuilder.tsx +12 -175
  181. package/src/core/form/components/ControlQueryBuilderHelp.tsx +165 -0
  182. package/src/core/form/components/ControlSelect.browser.spec.tsx +343 -0
  183. package/src/core/form/components/ControlSelect.tsx +294 -92
  184. package/src/core/form/components/TypeForm.browser.spec.tsx +3 -3
  185. package/src/core/form/components/TypeForm.tsx +5 -2
  186. package/src/core/form/index.ts +8 -1
  187. package/src/core/form/utils/parseInput.ts +7 -3
  188. package/src/core/index.ts +3 -1
  189. package/src/core/json/components/JsonViewer.tsx +103 -319
  190. package/src/core/json/components/JsonViewerCopyButton.tsx +46 -0
  191. package/src/core/json/components/JsonViewerRowNode.tsx +120 -0
  192. package/src/core/json/components/JsonViewerShared.ts +76 -0
  193. package/src/core/services/DialogService.tsx +2 -2
  194. package/src/core/styles.css +13 -2
  195. package/src/core/table/components/ColumnPicker.tsx +3 -3
  196. package/src/core/table/components/DataTable.tsx +88 -29
  197. package/src/core/table/components/DataTableFilters.tsx +6 -11
  198. package/src/core/table/components/DataTablePagination.tsx +9 -3
  199. package/src/core/table/components/DataTableToolbar.tsx +7 -3
  200. package/src/core/table/components/FilterPicker.tsx +3 -3
  201. package/src/core/table/interfaces/types.ts +29 -0
  202. package/src/core/utils/icons.tsx +2 -2
  203. package/src/demo/DemoRouter.ts +8 -1
  204. package/src/demo/components/DemoLayout.tsx +12 -2
  205. package/src/demo/components/auth/DemoLogin.tsx +35 -28
  206. package/src/demo/components/auth/DemoRegister.tsx +35 -49
  207. package/src/demo/components/auth/DemoResetPassword.tsx +5 -9
  208. package/src/demo/components/auth/DemoVerifyEmail.tsx +7 -6
  209. package/src/demo/components/core/DemoButton.tsx +123 -103
  210. package/src/demo/components/core/DemoControlSelect.tsx +325 -0
  211. package/src/demo/components/core/DemoDataTable.tsx +255 -237
  212. package/src/demo/components/core/DemoTypeForm.tsx +7 -2
  213. package/src/demo/components/shared/MacWindow.tsx +5 -11
  214. package/src/demo/components/shared/Showcase.tsx +28 -42
  215. package/dist/admin/AdminJobDashboard-KIOkeMgE.js.map +0 -1
  216. package/dist/admin/AdminLayout-B1DXZHDn.js.map +0 -1
  217. package/dist/admin/AdminParameters-BspPeqp_.js.map +0 -1
  218. package/dist/admin/AdminUserLayout-DUbC6-BI.js.map +0 -1
  219. package/dist/admin/AdminUserProfile-DuTUnjdG.js.map +0 -1
  220. package/dist/admin/AdminUsers-CR9z0g_5.js.map +0 -1
  221. package/dist/admin/Login-DHbYJKwg.js +0 -219
  222. package/dist/admin/Login-DHbYJKwg.js.map +0 -1
  223. package/dist/admin/Profile-B2EcIDB9.js.map +0 -1
  224. package/dist/admin/Register-Z3fxRbUF.js.map +0 -1
  225. package/dist/admin/ResetPassword-_Y1qTTKh.js.map +0 -1
  226. package/dist/admin/VerifyEmail-Bg22bwcC.js.map +0 -1
  227. package/dist/admin/core-BVO_TQxb.js.map +0 -1
  228. package/dist/admin/rolldown-runtime-CjeV3_4I.js +0 -18
  229. package/dist/auth/Login-C7jIqf00.js +0 -219
  230. package/dist/auth/Login-C7jIqf00.js.map +0 -1
  231. package/dist/auth/Profile-BMpXJ0oi.js.map +0 -1
  232. package/dist/auth/Register-2gx8qll-.js.map +0 -1
  233. package/dist/auth/ResetPassword-DBxt9hKk.js.map +0 -1
  234. package/dist/auth/VerifyEmail-Z80Ubajk.js.map +0 -1
  235. package/dist/auth/core-DyfeVr5c.js.map +0 -1
  236. package/dist/auth/rolldown-runtime-CjeV3_4I.js +0 -18
  237. package/dist/demo/DemoButton-CGUyR9eM.js +0 -178
  238. package/dist/demo/DemoButton-CGUyR9eM.js.map +0 -1
  239. package/dist/demo/DemoDataTable-QFG-xXSx.js +0 -358
  240. package/dist/demo/DemoDataTable-QFG-xXSx.js.map +0 -1
  241. package/dist/demo/DemoLayout-Cy6xjn6P.js.map +0 -1
  242. package/dist/demo/DemoLogin-vqxgTu4P.js.map +0 -1
  243. package/dist/demo/DemoRegister-YHPvPg77.js.map +0 -1
  244. package/dist/demo/DemoResetPassword-mOW18Zlm.js.map +0 -1
  245. package/dist/demo/DemoTypeForm-C1dNkahD.js.map +0 -1
  246. package/dist/demo/DemoVerifyEmail-D9EcXZ38.js +0 -30
  247. package/dist/demo/DemoVerifyEmail-D9EcXZ38.js.map +0 -1
  248. package/dist/demo/Login-CoYf_P_F.js +0 -219
  249. package/dist/demo/Login-CoYf_P_F.js.map +0 -1
  250. package/dist/demo/Profile-BE_Y3co2.js.map +0 -1
  251. package/dist/demo/Register-fXHmBpr3.js.map +0 -1
  252. package/dist/demo/ResetPassword-CAPj8MO3.js.map +0 -1
  253. package/dist/demo/Showcase-BtEU0pY9.js.map +0 -1
  254. package/dist/demo/VerifyEmail-DFmdCdYs.js.map +0 -1
  255. package/dist/demo/core-B7LNjM78.js.map +0 -1
  256. package/dist/demo/rolldown-runtime-CjeV3_4I.js +0 -18
  257. package/src/demo/styles.css +0 -0
@@ -1,31 +1,17 @@
1
1
  import { ActionButton, Flex, Text } from "@alepha/ui";
2
- import { Collapse, ScrollArea, TextInput, UnstyledButton } from "@mantine/core";
3
- import {
4
- IconChevronDown,
5
- IconChevronRight,
6
- IconFolder,
7
- IconFolderOpen,
8
- IconRefresh,
9
- IconSearch,
10
- IconSettings,
11
- } from "@tabler/icons-react";
12
- import type { ParameterTreeNode } from "alepha/api/parameters";
13
- import { memo, useCallback, useMemo, useState } from "react";
14
-
15
- export interface ParameterTreeProps {
16
- treeData: ParameterTreeNode[];
17
- selectedConfig: string | null;
18
- onSelect: (name: string) => void;
19
- onRefresh: () => void;
20
- }
2
+ import { ScrollArea, TextInput } from "@mantine/core";
3
+ import { IconRefresh, IconSearch } from "@tabler/icons-react";
4
+ import type { ParameterTreeNode as ParameterTreeNodeData } from "alepha/api/parameters";
5
+ import { useCallback, useMemo, useState } from "react";
6
+ import ParameterTreeNode from "./ParameterTreeNode.tsx";
21
7
 
22
8
  /**
23
9
  * Filters tree nodes by search query.
24
10
  */
25
11
  const filterTree = (
26
- nodes: ParameterTreeNode[],
12
+ nodes: ParameterTreeNodeData[],
27
13
  query: string,
28
- ): ParameterTreeNode[] => {
14
+ ): ParameterTreeNodeData[] => {
29
15
  if (!query.trim()) return nodes;
30
16
 
31
17
  const lowerQuery = query.toLowerCase();
@@ -45,163 +31,16 @@ const filterTree = (
45
31
 
46
32
  return null;
47
33
  })
48
- .filter((node): node is ParameterTreeNode => node !== null);
34
+ .filter((node): node is ParameterTreeNodeData => node !== null);
49
35
  };
50
36
 
51
- interface TreeNodeProps {
52
- node: ParameterTreeNode;
53
- level: number;
54
- selectedConfig: string | null;
55
- onSelect: (name: string) => void;
56
- expandedNodes: Set<string>;
57
- onToggle: (path: string) => void;
58
- }
59
-
60
- /**
61
- * Memoized tree node to prevent unnecessary re-renders.
62
- */
63
- const TreeNode = memo(
64
- ({
65
- node,
66
- level,
67
- selectedConfig,
68
- onSelect,
69
- expandedNodes,
70
- onToggle,
71
- }: TreeNodeProps) => {
72
- const [isHovered, setIsHovered] = useState(false);
73
- const hasChildren = node.children.length > 0;
74
- const isExpanded = expandedNodes.has(node.path);
75
- const isSelected = selectedConfig === node.path;
76
- const isLeaf = !hasChildren;
77
-
78
- const handleClick = useCallback(() => {
79
- if (hasChildren) {
80
- onToggle(node.path);
81
- } else {
82
- onSelect(node.path);
83
- }
84
- }, [hasChildren, node.path, onToggle, onSelect]);
85
-
86
- const handleMouseEnter = useCallback(() => setIsHovered(true), []);
87
- const handleMouseLeave = useCallback(() => setIsHovered(false), []);
88
-
89
- return (
90
- <Flex>
91
- <UnstyledButton
92
- onClick={handleClick}
93
- onMouseEnter={handleMouseEnter}
94
- onMouseLeave={handleMouseLeave}
95
- w="100%"
96
- style={{ display: "block" }}
97
- >
98
- <Flex
99
- gap={6}
100
- wrap="nowrap"
101
- p="4px 8px"
102
- pl={8 + level * 16}
103
- style={{
104
- borderRadius: "var(--mantine-radius-sm)",
105
- backgroundColor:
106
- isSelected || isHovered
107
- ? "var(--mantine-color-default-hover)"
108
- : undefined,
109
- }}
110
- >
111
- {hasChildren ? (
112
- <>
113
- <Flex
114
- style={{
115
- display: "flex",
116
- alignItems: "center",
117
- justifyContent: "center",
118
- width: 16,
119
- }}
120
- >
121
- {isExpanded ? (
122
- <IconChevronDown
123
- size={14}
124
- color="var(--mantine-color-dimmed)"
125
- />
126
- ) : (
127
- <IconChevronRight
128
- size={14}
129
- color="var(--mantine-color-dimmed)"
130
- />
131
- )}
132
- </Flex>
133
- {isExpanded ? (
134
- <IconFolderOpen
135
- size={16}
136
- color="var(--mantine-color-dimmed)"
137
- style={{ flexShrink: 0 }}
138
- />
139
- ) : (
140
- <IconFolder
141
- size={16}
142
- color="var(--mantine-color-dimmed)"
143
- style={{ flexShrink: 0 }}
144
- />
145
- )}
146
- </>
147
- ) : (
148
- <>
149
- <Flex w={16} />
150
- <IconSettings
151
- size={16}
152
- color={
153
- isSelected
154
- ? "var(--mantine-color-blue-6)"
155
- : "var(--mantine-color-dimmed)"
156
- }
157
- style={{ flexShrink: 0 }}
158
- />
159
- </>
160
- )}
161
- <Text
162
- size="sm"
163
- fw={isSelected ? 600 : 400}
164
- c={isSelected ? undefined : isLeaf ? undefined : "dimmed"}
165
- style={{
166
- whiteSpace: "nowrap",
167
- overflow: "hidden",
168
- textOverflow: "ellipsis",
169
- }}
170
- >
171
- {node.name}
172
- </Text>
173
- </Flex>
174
- </UnstyledButton>
175
-
176
- {hasChildren && (
177
- <Collapse in={isExpanded}>
178
- {node.children.map((child: ParameterTreeNode) => (
179
- <TreeNode
180
- key={child.path}
181
- node={child}
182
- level={level + 1}
183
- selectedConfig={selectedConfig}
184
- onSelect={onSelect}
185
- expandedNodes={expandedNodes}
186
- onToggle={onToggle}
187
- />
188
- ))}
189
- </Collapse>
190
- )}
191
- </Flex>
192
- );
193
- },
194
- );
195
-
196
- TreeNode.displayName = "TreeNode";
197
-
198
37
  /**
199
38
  * Collects all folder paths to expand by default.
200
39
  */
201
- const collectAllFolderPaths = (nodes: ParameterTreeNode[]): Set<string> => {
40
+ const collectAllFolderPaths = (nodes: ParameterTreeNodeData[]): Set<string> => {
202
41
  const paths = new Set<string>();
203
42
 
204
- const traverse = (nodeList: ParameterTreeNode[]) => {
43
+ const traverse = (nodeList: ParameterTreeNodeData[]) => {
205
44
  for (const node of nodeList) {
206
45
  if (node.children.length > 0) {
207
46
  paths.add(node.path);
@@ -214,21 +53,26 @@ const collectAllFolderPaths = (nodes: ParameterTreeNode[]): Set<string> => {
214
53
  return paths;
215
54
  };
216
55
 
217
- const ParameterTree = ({
218
- treeData,
219
- selectedConfig,
220
- onSelect,
221
- onRefresh,
222
- }: ParameterTreeProps) => {
56
+ interface Props {
57
+ treeData: ParameterTreeNodeData[];
58
+ selectedConfig: string | null;
59
+ onSelect: (name: string) => void;
60
+ onRefresh: () => void;
61
+ }
62
+
63
+ /**
64
+ * Parameter tree sidebar with search and refresh.
65
+ */
66
+ const ParameterTree = (props: Props) => {
223
67
  const [searchQuery, setSearchQuery] = useState("");
224
68
  const [expandedNodes, setExpandedNodes] = useState<Set<string>>(() =>
225
- collectAllFolderPaths(treeData),
69
+ collectAllFolderPaths(props.treeData),
226
70
  );
227
71
 
228
72
  // Filter tree by search query
229
73
  const filteredTreeData = useMemo(
230
- () => filterTree(treeData, searchQuery),
231
- [treeData, searchQuery],
74
+ () => filterTree(props.treeData, searchQuery),
75
+ [props.treeData, searchQuery],
232
76
  );
233
77
 
234
78
  const handleToggle = useCallback((path: string) => {
@@ -270,7 +114,7 @@ const ParameterTree = ({
270
114
  <ActionButton
271
115
  variant="subtle"
272
116
  size="compact-xs"
273
- onClick={onRefresh}
117
+ onClick={props.onRefresh}
274
118
  tooltip="Refresh"
275
119
  >
276
120
  <IconRefresh size={14} />
@@ -293,12 +137,12 @@ const ParameterTree = ({
293
137
  ) : (
294
138
  <Flex direction="column" gap={0} style={{ gap: 1 }}>
295
139
  {filteredTreeData.map((node) => (
296
- <TreeNode
140
+ <ParameterTreeNode
297
141
  key={node.path}
298
142
  node={node}
299
143
  level={0}
300
- selectedConfig={selectedConfig}
301
- onSelect={onSelect}
144
+ selectedConfig={props.selectedConfig}
145
+ onSelect={props.onSelect}
302
146
  expandedNodes={expandedNodes}
303
147
  onToggle={handleToggle}
304
148
  />
@@ -0,0 +1,151 @@
1
+ import { Flex, Text } from "@alepha/ui";
2
+ import { Collapse, UnstyledButton } from "@mantine/core";
3
+ import {
4
+ IconChevronDown,
5
+ IconChevronRight,
6
+ IconFolder,
7
+ IconFolderOpen,
8
+ IconSettings,
9
+ } from "@tabler/icons-react";
10
+ import type { ParameterTreeNode as ParameterTreeNodeData } from "alepha/api/parameters";
11
+ import { memo, useCallback, useState } from "react";
12
+
13
+ interface Props {
14
+ node: ParameterTreeNodeData;
15
+ level: number;
16
+ selectedConfig: string | null;
17
+ onSelect: (name: string) => void;
18
+ expandedNodes: Set<string>;
19
+ onToggle: (path: string) => void;
20
+ }
21
+
22
+ /**
23
+ * Memoized tree node to prevent unnecessary re-renders.
24
+ */
25
+ const ParameterTreeNode = memo((props: Props) => {
26
+ const [isHovered, setIsHovered] = useState(false);
27
+ const hasChildren = props.node.children.length > 0;
28
+ const isExpanded = props.expandedNodes.has(props.node.path);
29
+ const isSelected = props.selectedConfig === props.node.path;
30
+ const isLeaf = !hasChildren;
31
+
32
+ const handleClick = useCallback(() => {
33
+ if (hasChildren) {
34
+ props.onToggle(props.node.path);
35
+ } else {
36
+ props.onSelect(props.node.path);
37
+ }
38
+ }, [hasChildren, props.node.path, props.onToggle, props.onSelect]);
39
+
40
+ const handleMouseEnter = useCallback(() => setIsHovered(true), []);
41
+ const handleMouseLeave = useCallback(() => setIsHovered(false), []);
42
+
43
+ return (
44
+ <Flex>
45
+ <UnstyledButton
46
+ onClick={handleClick}
47
+ onMouseEnter={handleMouseEnter}
48
+ onMouseLeave={handleMouseLeave}
49
+ w="100%"
50
+ style={{ display: "block" }}
51
+ >
52
+ <Flex
53
+ gap={6}
54
+ wrap="nowrap"
55
+ p="4px 8px"
56
+ pl={8 + props.level * 16}
57
+ style={{
58
+ borderRadius: "var(--mantine-radius-sm)",
59
+ backgroundColor:
60
+ isSelected || isHovered
61
+ ? "var(--mantine-color-default-hover)"
62
+ : undefined,
63
+ }}
64
+ >
65
+ {hasChildren ? (
66
+ <>
67
+ <Flex
68
+ style={{
69
+ display: "flex",
70
+ alignItems: "center",
71
+ justifyContent: "center",
72
+ width: 16,
73
+ }}
74
+ >
75
+ {isExpanded ? (
76
+ <IconChevronDown
77
+ size={14}
78
+ color="var(--mantine-color-dimmed)"
79
+ />
80
+ ) : (
81
+ <IconChevronRight
82
+ size={14}
83
+ color="var(--mantine-color-dimmed)"
84
+ />
85
+ )}
86
+ </Flex>
87
+ {isExpanded ? (
88
+ <IconFolderOpen
89
+ size={16}
90
+ color="var(--mantine-color-dimmed)"
91
+ style={{ flexShrink: 0 }}
92
+ />
93
+ ) : (
94
+ <IconFolder
95
+ size={16}
96
+ color="var(--mantine-color-dimmed)"
97
+ style={{ flexShrink: 0 }}
98
+ />
99
+ )}
100
+ </>
101
+ ) : (
102
+ <>
103
+ <Flex w={16} />
104
+ <IconSettings
105
+ size={16}
106
+ color={
107
+ isSelected
108
+ ? "var(--mantine-color-blue-6)"
109
+ : "var(--mantine-color-dimmed)"
110
+ }
111
+ style={{ flexShrink: 0 }}
112
+ />
113
+ </>
114
+ )}
115
+ <Text
116
+ size="sm"
117
+ fw={isSelected ? 600 : 400}
118
+ c={isSelected ? undefined : isLeaf ? undefined : "dimmed"}
119
+ style={{
120
+ whiteSpace: "nowrap",
121
+ overflow: "hidden",
122
+ textOverflow: "ellipsis",
123
+ }}
124
+ >
125
+ {props.node.name}
126
+ </Text>
127
+ </Flex>
128
+ </UnstyledButton>
129
+
130
+ {hasChildren && (
131
+ <Collapse in={isExpanded}>
132
+ {props.node.children.map((child: ParameterTreeNodeData) => (
133
+ <ParameterTreeNode
134
+ key={child.path}
135
+ node={child}
136
+ level={props.level + 1}
137
+ selectedConfig={props.selectedConfig}
138
+ onSelect={props.onSelect}
139
+ expandedNodes={props.expandedNodes}
140
+ onToggle={props.onToggle}
141
+ />
142
+ ))}
143
+ </Collapse>
144
+ )}
145
+ </Flex>
146
+ );
147
+ });
148
+
149
+ ParameterTreeNode.displayName = "ParameterTreeNode";
150
+
151
+ export default ParameterTreeNode;
@@ -14,8 +14,8 @@ import {
14
14
  IconChevronLeft,
15
15
  IconExternalLink,
16
16
  } from "@tabler/icons-react";
17
- import { useRouter } from "alepha/react/router";
18
17
  import type { ComponentType, ReactNode } from "react";
18
+ import AdminResourceHeaderMenuItem from "./AdminResourceHeaderMenuItem.tsx";
19
19
 
20
20
  export interface AdminResourceAction {
21
21
  label: string;
@@ -107,29 +107,6 @@ export interface AdminResourceHeaderProps {
107
107
  loading?: boolean;
108
108
  }
109
109
 
110
- const ActionMenuItem = (props: { action: AdminResourceAction }) => {
111
- const { action } = props;
112
- const router = useRouter();
113
-
114
- const menuItemProps: Record<string, unknown> = {};
115
- if (action.href) {
116
- Object.assign(menuItemProps, router.anchor(action.href));
117
- } else if (action.onClick) {
118
- menuItemProps.onClick = action.onClick;
119
- }
120
-
121
- return (
122
- <Menu.Item
123
- leftSection={action.icon ? <action.icon size={16} /> : undefined}
124
- color={action.color}
125
- disabled={action.disabled}
126
- {...menuItemProps}
127
- >
128
- {action.label}
129
- </Menu.Item>
130
- );
131
- };
132
-
133
110
  const AdminResourceHeader = (props: AdminResourceHeaderProps) => {
134
111
  const {
135
112
  backHref,
@@ -271,7 +248,7 @@ const AdminResourceHeader = (props: AdminResourceHeaderProps) => {
271
248
  </Menu.Target>
272
249
  <Menu.Dropdown>
273
250
  {menuActions.map((action, index) => (
274
- <ActionMenuItem key={index} action={action} />
251
+ <AdminResourceHeaderMenuItem key={index} action={action} />
275
252
  ))}
276
253
  </Menu.Dropdown>
277
254
  </Menu>
@@ -0,0 +1,37 @@
1
+ import { Menu } from "@mantine/core";
2
+ import { useRouter } from "alepha/react/router";
3
+ import type { AdminResourceAction } from "./AdminResourceHeader.tsx";
4
+
5
+ export interface AdminResourceHeaderMenuItemProps {
6
+ /**
7
+ * Action configuration
8
+ */
9
+ action: AdminResourceAction;
10
+ }
11
+
12
+ const AdminResourceHeaderMenuItem = (
13
+ props: AdminResourceHeaderMenuItemProps,
14
+ ) => {
15
+ const { action } = props;
16
+ const router = useRouter();
17
+
18
+ const menuItemProps: Record<string, unknown> = {};
19
+ if (action.href) {
20
+ Object.assign(menuItemProps, router.anchor(action.href));
21
+ } else if (action.onClick) {
22
+ menuItemProps.onClick = action.onClick;
23
+ }
24
+
25
+ return (
26
+ <Menu.Item
27
+ leftSection={action.icon ? <action.icon size={16} /> : undefined}
28
+ color={action.color}
29
+ disabled={action.disabled}
30
+ {...menuItemProps}
31
+ >
32
+ {action.label}
33
+ </Menu.Item>
34
+ );
35
+ };
36
+
37
+ export default AdminResourceHeaderMenuItem;
@@ -1,6 +1,6 @@
1
1
  import { Tabs } from "@mantine/core";
2
- import { useActive, useRouter } from "alepha/react/router";
3
2
  import type { ComponentType, ReactNode } from "react";
3
+ import AdminResourceTabsItem from "./AdminResourceTabsItem.tsx";
4
4
 
5
5
  export interface AdminResourceTab {
6
6
  /**
@@ -51,30 +51,6 @@ export interface AdminResourceTabsProps {
51
51
  children?: ReactNode;
52
52
  }
53
53
 
54
- const TabItem = (props: { tab: AdminResourceTab }) => {
55
- const { tab } = props;
56
- const router = useRouter();
57
- const { isActive, isPending } = useActive({ href: tab.href });
58
- const anchorProps = router.anchor(tab.href);
59
-
60
- return (
61
- <Tabs.Tab
62
- value={tab.value}
63
- component="a"
64
- leftSection={tab.icon ? <tab.icon size={16} /> : undefined}
65
- disabled={tab.disabled}
66
- data-active={isActive || undefined}
67
- style={{
68
- opacity: isPending ? 0.6 : 1,
69
- }}
70
- {...anchorProps}
71
- >
72
- {tab.label}
73
- {tab.count !== undefined && tab.count > 0 && ` (${tab.count})`}
74
- </Tabs.Tab>
75
- );
76
- };
77
-
78
54
  const AdminResourceTabs = (props: AdminResourceTabsProps) => {
79
55
  const { tabs, activeTab, children } = props;
80
56
 
@@ -82,7 +58,7 @@ const AdminResourceTabs = (props: AdminResourceTabsProps) => {
82
58
  <Tabs value={activeTab} variant="default">
83
59
  <Tabs.List>
84
60
  {tabs.map((tab) => (
85
- <TabItem key={tab.value} tab={tab} />
61
+ <AdminResourceTabsItem key={tab.value} tab={tab} />
86
62
  ))}
87
63
  </Tabs.List>
88
64
 
@@ -0,0 +1,36 @@
1
+ import { Tabs } from "@mantine/core";
2
+ import { useActive, useRouter } from "alepha/react/router";
3
+ import type { AdminResourceTab } from "./AdminResourceTabs.tsx";
4
+
5
+ export interface AdminResourceTabsItemProps {
6
+ /**
7
+ * Tab configuration
8
+ */
9
+ tab: AdminResourceTab;
10
+ }
11
+
12
+ const AdminResourceTabsItem = (props: AdminResourceTabsItemProps) => {
13
+ const { tab } = props;
14
+ const router = useRouter();
15
+ const { isActive, isPending } = useActive({ href: tab.href });
16
+ const anchorProps = router.anchor(tab.href);
17
+
18
+ return (
19
+ <Tabs.Tab
20
+ value={tab.value}
21
+ component="a"
22
+ leftSection={tab.icon ? <tab.icon size={16} /> : undefined}
23
+ disabled={tab.disabled}
24
+ data-active={isActive || undefined}
25
+ style={{
26
+ opacity: isPending ? 0.6 : 1,
27
+ }}
28
+ {...anchorProps}
29
+ >
30
+ {tab.label}
31
+ {tab.count !== undefined && tab.count > 0 && ` (${tab.count})`}
32
+ </Tabs.Tab>
33
+ );
34
+ };
35
+
36
+ export default AdminResourceTabsItem;