@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,24 @@
1
1
  import {
2
- ActionIcon,
3
- Flex,
4
2
  getTreeExpandedState,
5
3
  type MantineSize,
6
4
  Text,
7
5
  Tree,
8
6
  useTree,
9
7
  } from "@mantine/core";
8
+ import { type ReactNode, useCallback, useMemo } from "react";
9
+ import { JsonViewerRowNode } from "./JsonViewerRowNode.tsx";
10
10
  import {
11
- IconCheck,
12
- IconChevronDown,
13
- IconChevronRight,
14
- IconCopy,
15
- } from "@tabler/icons-react";
16
- import {
17
- type CSSProperties,
18
- type ReactNode,
19
- useCallback,
20
- useMemo,
21
- useState,
22
- } from "react";
11
+ getValueType,
12
+ type JsonTreeNode,
13
+ SIZE_CONFIG,
14
+ STYLES,
15
+ } from "./JsonViewerShared.ts";
23
16
 
24
17
  // =============================================================================
25
- // TYPES
18
+ // PROPS
26
19
  // =============================================================================
27
20
 
28
- interface JsonViewerProps {
21
+ export interface JsonViewerProps {
29
22
  data: any;
30
23
  /**
31
24
  * Depth level to expand by default (0 = collapsed, Infinity = all expanded)
@@ -57,312 +50,21 @@ interface JsonViewerProps {
57
50
  ) => string | number | undefined;
58
51
  }
59
52
 
60
- interface JsonTreeNode {
61
- value: string;
62
- label: string;
63
- children?: JsonTreeNode[];
64
- // Custom properties
65
- nodeValue: any;
66
- nodeKey: string | undefined;
67
- path: string[];
68
- isArrayItem: boolean;
69
- isRoot?: boolean;
70
- }
71
-
72
- // =============================================================================
73
- // CONSTANTS
74
- // =============================================================================
75
-
76
- const SIZE_CONFIG: Record<MantineSize, { icon: number; levelOffset: number }> =
77
- {
78
- xs: { icon: 14, levelOffset: 16 },
79
- sm: { icon: 16, levelOffset: 20 },
80
- md: { icon: 18, levelOffset: 24 },
81
- lg: { icon: 20, levelOffset: 28 },
82
- xl: { icon: 22, levelOffset: 32 },
83
- };
84
-
85
- const STYLES = {
86
- root: {
87
- fontFamily: "var(--mantine-font-family-monospace)",
88
- } satisfies CSSProperties,
89
- chevron: {
90
- flexShrink: 0,
91
- color: "var(--mantine-color-dimmed)",
92
- } satisfies CSSProperties,
93
- key: {
94
- color: "var(--mantine-color-cyan-text)",
95
- fontWeight: 500,
96
- } satisfies CSSProperties,
97
- colon: {
98
- color: "var(--mantine-color-dimmed)",
99
- } satisfies CSSProperties,
100
- string: {
101
- color: "var(--mantine-color-teal-text)",
102
- } satisfies CSSProperties,
103
- number: {
104
- color: "var(--mantine-color-blue-text)",
105
- } satisfies CSSProperties,
106
- boolean: {
107
- color: "var(--mantine-color-violet-text)",
108
- } satisfies CSSProperties,
109
- null: {
110
- color: "var(--mantine-color-dimmed)",
111
- fontStyle: "italic",
112
- } satisfies CSSProperties,
113
- preview: {
114
- color: "var(--mantine-color-dimmed)",
115
- } satisfies CSSProperties,
116
- };
117
-
118
- // =============================================================================
119
- // HELPERS
120
- // =============================================================================
121
-
122
- const getValueType = (val: any): string => {
123
- if (val === null) return "null";
124
- if (val === undefined) return "undefined";
125
- if (Array.isArray(val)) return "array";
126
- return typeof val;
127
- };
128
-
129
- // Convert JSON to tree data structure
130
- function buildTreeNodes(
131
- data: any,
132
- path: string[] = [],
133
- key?: string,
134
- isArrayItem = false,
135
- maxDepth = 10,
136
- ): JsonTreeNode | null {
137
- const currentPath = key !== undefined ? [...path, key] : path;
138
- const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
139
-
140
- if (currentPath.length > maxDepth) {
141
- return {
142
- value: nodeId,
143
- label: key ?? "",
144
- nodeValue: data,
145
- nodeKey: key,
146
- path: currentPath,
147
- isArrayItem,
148
- };
149
- }
150
-
151
- const type = getValueType(data);
152
-
153
- if (type === "object" || type === "array") {
154
- const entries =
155
- type === "array"
156
- ? (data as any[]).map((v, i) => [String(i), v] as const)
157
- : Object.entries(data);
158
-
159
- const children = entries
160
- .map(([k, v]) =>
161
- buildTreeNodes(v, currentPath, k, type === "array", maxDepth),
162
- )
163
- .filter((n): n is JsonTreeNode => n !== null);
164
-
165
- return {
166
- value: nodeId,
167
- label: key ?? "",
168
- nodeValue: data,
169
- nodeKey: key,
170
- path: currentPath,
171
- isArrayItem,
172
- children: children.length > 0 ? children : undefined,
173
- };
174
- }
175
-
176
- return {
177
- value: nodeId,
178
- label: key ?? "",
179
- nodeValue: data,
180
- nodeKey: key,
181
- path: currentPath,
182
- isArrayItem,
183
- };
184
- }
185
-
186
- // Get all expandable node IDs up to a certain depth
187
- function getExpandedIds(
188
- nodes: JsonTreeNode[],
189
- targetDepth: number,
190
- currentDepth = 0,
191
- ): string[] {
192
- if (currentDepth >= targetDepth) return [];
193
- const ids: string[] = [];
194
- for (const node of nodes) {
195
- if (node.children) {
196
- ids.push(node.value);
197
- ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
198
- }
199
- }
200
- return ids;
201
- }
202
-
203
53
  // =============================================================================
204
- // COPY BUTTON COMPONENT
54
+ // COMPONENT
205
55
  // =============================================================================
206
56
 
207
- const CopyButton = ({
208
- value,
209
- iconSize,
210
- }: {
211
- value: string;
212
- iconSize: number;
213
- }) => {
214
- const [copied, setCopied] = useState(false);
215
-
216
- const handleCopy = useCallback(
217
- (e: React.MouseEvent) => {
218
- e.stopPropagation();
219
- navigator.clipboard.writeText(value);
220
- setCopied(true);
221
- setTimeout(() => setCopied(false), 1500);
222
- },
223
- [value],
224
- );
225
-
226
- return (
227
- <ActionIcon
228
- size={iconSize + 4}
229
- variant="transparent"
230
- c={copied ? "green" : "dimmed"}
231
- onClick={handleCopy}
232
- className="alepha-json-viewer-copy"
233
- >
234
- {copied ? <IconCheck size={iconSize} /> : <IconCopy size={iconSize} />}
235
- </ActionIcon>
236
- );
237
- };
238
-
239
- // =============================================================================
240
- // ROW NODE COMPONENT
241
- // =============================================================================
242
-
243
- interface RowNodeProps {
244
- node: JsonTreeNode;
245
- expanded: boolean;
246
- hasChildren: boolean;
247
- elementProps: any;
248
- size: MantineSize;
249
- config: { icon: number; levelOffset: number };
250
- showQuotes: boolean;
251
- showCopyButton: boolean;
252
- renderValue: (val: any, key: string | undefined, path: string[]) => ReactNode;
253
- }
57
+ export const JsonViewer = (props: JsonViewerProps) => {
58
+ const {
59
+ data,
60
+ defaultExpandedDepth = 2,
61
+ maxDepth = 10,
62
+ size = "sm",
63
+ showQuotes = false,
64
+ showCopyButton = true,
65
+ formatValue,
66
+ } = props;
254
67
 
255
- const RowNode = ({
256
- node,
257
- expanded,
258
- hasChildren,
259
- elementProps,
260
- size,
261
- config,
262
- showQuotes,
263
- showCopyButton,
264
- renderValue,
265
- }: RowNodeProps) => {
266
- const { nodeValue, nodeKey, path, isArrayItem, isRoot } = node;
267
- const type = getValueType(nodeValue);
268
- const isExpandable = type === "object" || type === "array";
269
-
270
- const getPreview = () => {
271
- if (!isExpandable) return null;
272
- const entries = type === "array" ? nodeValue : Object.keys(nodeValue);
273
- const count = entries.length;
274
- const label = type === "array" ? "item" : "key";
275
-
276
- // For root node or collapsed nodes, show the count
277
- if (!expanded) {
278
- return (
279
- <Text fs={"italic"} component="span" size={size} style={STYLES.preview}>
280
- {count === 0
281
- ? type === "array"
282
- ? "[]"
283
- : "{}"
284
- : type === "array"
285
- ? `[ ${count} ${count === 1 ? label : `${label}s`} ]`
286
- : `{ ${count} ${count === 1 ? label : `${label}s`} }`}
287
- </Text>
288
- );
289
- }
290
-
291
- return null;
292
- };
293
-
294
- const getCopyValue = () =>
295
- isExpandable ? JSON.stringify(nodeValue, null, 2) : String(nodeValue ?? "");
296
-
297
- return (
298
- <Flex
299
- gap={6}
300
- wrap="nowrap"
301
- {...elementProps}
302
- className={`alepha-json-viewer-row ${elementProps.className || ""}`}
303
- >
304
- {hasChildren ? (
305
- expanded ? (
306
- <IconChevronDown size={config.icon} style={STYLES.chevron} />
307
- ) : (
308
- <IconChevronRight size={config.icon} style={STYLES.chevron} />
309
- )
310
- ) : (
311
- <span style={{ width: config.icon, flexShrink: 0 }} />
312
- )}
313
-
314
- {nodeKey !== undefined && !isArrayItem && (
315
- <Text component="span" size={size}>
316
- <span style={STYLES.key}>
317
- {showQuotes ? `"${nodeKey}"` : nodeKey}
318
- </span>
319
- <span style={STYLES.colon}>:</span>
320
- </Text>
321
- )}
322
-
323
- {nodeKey !== undefined && isArrayItem && (
324
- <Text component="span" size={size}>
325
- <span style={STYLES.key}>{nodeKey}</span>
326
- <span style={STYLES.colon}>:</span>
327
- </Text>
328
- )}
329
-
330
- {hasChildren ? (
331
- getPreview()
332
- ) : isExpandable ? (
333
- type === "array" ? (
334
- <Text component="span" size={size} style={STYLES.preview}>
335
- []
336
- </Text>
337
- ) : (
338
- <Text component="span" size={size} style={STYLES.preview}>
339
- {"{}"}
340
- </Text>
341
- )
342
- ) : (
343
- renderValue(nodeValue, nodeKey, path)
344
- )}
345
-
346
- {showCopyButton && (
347
- <CopyButton value={getCopyValue()} iconSize={config.icon} />
348
- )}
349
- </Flex>
350
- );
351
- };
352
-
353
- // =============================================================================
354
- // MAIN COMPONENT
355
- // =============================================================================
356
-
357
- export const JsonViewer = ({
358
- data,
359
- defaultExpandedDepth = 2,
360
- maxDepth = 10,
361
- size = "sm",
362
- showQuotes = false,
363
- showCopyButton = true,
364
- formatValue,
365
- }: JsonViewerProps) => {
366
68
  const config = SIZE_CONFIG[size] || SIZE_CONFIG.sm;
367
69
 
368
70
  // Build tree data from JSON with root wrapper
@@ -487,7 +189,7 @@ export const JsonViewer = ({
487
189
  elementProps: any;
488
190
  }): ReactNode => {
489
191
  return (
490
- <RowNode
192
+ <JsonViewerRowNode
491
193
  node={node}
492
194
  expanded={expanded}
493
195
  hasChildren={hasChildren}
@@ -523,4 +225,86 @@ export const JsonViewer = ({
523
225
  );
524
226
  };
525
227
 
228
+ // =============================================================================
229
+ // HELPERS
230
+ // =============================================================================
231
+
232
+ /**
233
+ * Convert JSON to tree data structure.
234
+ */
235
+ const buildTreeNodes = (
236
+ data: any,
237
+ path: string[] = [],
238
+ key?: string,
239
+ isArrayItem = false,
240
+ maxDepth = 10,
241
+ ): JsonTreeNode | null => {
242
+ const currentPath = key !== undefined ? [...path, key] : path;
243
+ const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
244
+
245
+ if (currentPath.length > maxDepth) {
246
+ return {
247
+ value: nodeId,
248
+ label: key ?? "",
249
+ nodeValue: data,
250
+ nodeKey: key,
251
+ path: currentPath,
252
+ isArrayItem,
253
+ };
254
+ }
255
+
256
+ const type = getValueType(data);
257
+
258
+ if (type === "object" || type === "array") {
259
+ const entries =
260
+ type === "array"
261
+ ? (data as any[]).map((v, i) => [String(i), v] as const)
262
+ : Object.entries(data);
263
+
264
+ const children = entries
265
+ .map(([k, v]) =>
266
+ buildTreeNodes(v, currentPath, k, type === "array", maxDepth),
267
+ )
268
+ .filter((n): n is JsonTreeNode => n !== null);
269
+
270
+ return {
271
+ value: nodeId,
272
+ label: key ?? "",
273
+ nodeValue: data,
274
+ nodeKey: key,
275
+ path: currentPath,
276
+ isArrayItem,
277
+ children: children.length > 0 ? children : undefined,
278
+ };
279
+ }
280
+
281
+ return {
282
+ value: nodeId,
283
+ label: key ?? "",
284
+ nodeValue: data,
285
+ nodeKey: key,
286
+ path: currentPath,
287
+ isArrayItem,
288
+ };
289
+ };
290
+
291
+ /**
292
+ * Get all expandable node IDs up to a certain depth.
293
+ */
294
+ const getExpandedIds = (
295
+ nodes: JsonTreeNode[],
296
+ targetDepth: number,
297
+ currentDepth = 0,
298
+ ): string[] => {
299
+ if (currentDepth >= targetDepth) return [];
300
+ const ids: string[] = [];
301
+ for (const node of nodes) {
302
+ if (node.children) {
303
+ ids.push(node.value);
304
+ ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
305
+ }
306
+ }
307
+ return ids;
308
+ };
309
+
526
310
  export default JsonViewer;
@@ -0,0 +1,46 @@
1
+ import { ActionIcon } from "@mantine/core";
2
+ import { IconCheck, IconCopy } from "@tabler/icons-react";
3
+ import { useCallback, useState } from "react";
4
+
5
+ // =============================================================================
6
+ // PROPS
7
+ // =============================================================================
8
+
9
+ export interface JsonViewerCopyButtonProps {
10
+ value: string;
11
+ iconSize: number;
12
+ }
13
+
14
+ // =============================================================================
15
+ // COMPONENT
16
+ // =============================================================================
17
+
18
+ export const JsonViewerCopyButton = (props: JsonViewerCopyButtonProps) => {
19
+ const [copied, setCopied] = useState(false);
20
+
21
+ const handleCopy = useCallback(
22
+ (e: React.MouseEvent) => {
23
+ e.stopPropagation();
24
+ navigator.clipboard.writeText(props.value);
25
+ setCopied(true);
26
+ setTimeout(() => setCopied(false), 1500);
27
+ },
28
+ [props.value],
29
+ );
30
+
31
+ return (
32
+ <ActionIcon
33
+ size={props.iconSize + 4}
34
+ variant="transparent"
35
+ c={copied ? "green" : "dimmed"}
36
+ onClick={handleCopy}
37
+ className="alepha-json-viewer-copy"
38
+ >
39
+ {copied ? (
40
+ <IconCheck size={props.iconSize} />
41
+ ) : (
42
+ <IconCopy size={props.iconSize} />
43
+ )}
44
+ </ActionIcon>
45
+ );
46
+ };
@@ -0,0 +1,120 @@
1
+ import { Flex, type MantineSize, Text } from "@mantine/core";
2
+ import { IconChevronDown, IconChevronRight } from "@tabler/icons-react";
3
+ import type { ReactNode } from "react";
4
+ import { JsonViewerCopyButton } from "./JsonViewerCopyButton.tsx";
5
+ import { getValueType, type JsonTreeNode, STYLES } from "./JsonViewerShared.ts";
6
+
7
+ // =============================================================================
8
+ // PROPS
9
+ // =============================================================================
10
+
11
+ export interface JsonViewerRowNodeProps {
12
+ node: JsonTreeNode;
13
+ expanded: boolean;
14
+ hasChildren: boolean;
15
+ elementProps: any;
16
+ size: MantineSize;
17
+ config: { icon: number; levelOffset: number };
18
+ showQuotes: boolean;
19
+ showCopyButton: boolean;
20
+ renderValue: (val: any, key: string | undefined, path: string[]) => ReactNode;
21
+ }
22
+
23
+ // =============================================================================
24
+ // COMPONENT
25
+ // =============================================================================
26
+
27
+ export const JsonViewerRowNode = (props: JsonViewerRowNodeProps) => {
28
+ const { nodeValue, nodeKey, path, isArrayItem } = props.node;
29
+ const type = getValueType(nodeValue);
30
+ const isExpandable = type === "object" || type === "array";
31
+
32
+ const getPreview = () => {
33
+ if (!isExpandable) return null;
34
+ const entries = type === "array" ? nodeValue : Object.keys(nodeValue);
35
+ const count = entries.length;
36
+ const label = type === "array" ? "item" : "key";
37
+
38
+ if (!props.expanded) {
39
+ return (
40
+ <Text
41
+ fs={"italic"}
42
+ component="span"
43
+ size={props.size}
44
+ style={STYLES.preview}
45
+ >
46
+ {count === 0
47
+ ? type === "array"
48
+ ? "[]"
49
+ : "{}"
50
+ : type === "array"
51
+ ? `[ ${count} ${count === 1 ? label : `${label}s`} ]`
52
+ : `{ ${count} ${count === 1 ? label : `${label}s`} }`}
53
+ </Text>
54
+ );
55
+ }
56
+
57
+ return null;
58
+ };
59
+
60
+ const getCopyValue = () =>
61
+ isExpandable ? JSON.stringify(nodeValue, null, 2) : String(nodeValue ?? "");
62
+
63
+ return (
64
+ <Flex
65
+ gap={6}
66
+ wrap="nowrap"
67
+ {...props.elementProps}
68
+ className={`alepha-json-viewer-row ${props.elementProps.className || ""}`}
69
+ >
70
+ {props.hasChildren ? (
71
+ props.expanded ? (
72
+ <IconChevronDown size={props.config.icon} style={STYLES.chevron} />
73
+ ) : (
74
+ <IconChevronRight size={props.config.icon} style={STYLES.chevron} />
75
+ )
76
+ ) : (
77
+ <span style={{ width: props.config.icon, flexShrink: 0 }} />
78
+ )}
79
+
80
+ {nodeKey !== undefined && !isArrayItem && (
81
+ <Text component="span" size={props.size}>
82
+ <span style={STYLES.key}>
83
+ {props.showQuotes ? `"${nodeKey}"` : nodeKey}
84
+ </span>
85
+ <span style={STYLES.colon}>:</span>
86
+ </Text>
87
+ )}
88
+
89
+ {nodeKey !== undefined && isArrayItem && (
90
+ <Text component="span" size={props.size}>
91
+ <span style={STYLES.key}>{nodeKey}</span>
92
+ <span style={STYLES.colon}>:</span>
93
+ </Text>
94
+ )}
95
+
96
+ {props.hasChildren ? (
97
+ getPreview()
98
+ ) : isExpandable ? (
99
+ type === "array" ? (
100
+ <Text component="span" size={props.size} style={STYLES.preview}>
101
+ []
102
+ </Text>
103
+ ) : (
104
+ <Text component="span" size={props.size} style={STYLES.preview}>
105
+ {"{}"}
106
+ </Text>
107
+ )
108
+ ) : (
109
+ props.renderValue(nodeValue, nodeKey, path)
110
+ )}
111
+
112
+ {props.showCopyButton && (
113
+ <JsonViewerCopyButton
114
+ value={getCopyValue()}
115
+ iconSize={props.config.icon}
116
+ />
117
+ )}
118
+ </Flex>
119
+ );
120
+ };
@@ -0,0 +1,76 @@
1
+ import type { MantineSize } from "@mantine/core";
2
+ import type { CSSProperties } from "react";
3
+
4
+ // =============================================================================
5
+ // TYPES
6
+ // =============================================================================
7
+
8
+ export interface JsonTreeNode {
9
+ value: string;
10
+ label: string;
11
+ children?: JsonTreeNode[];
12
+ nodeValue: any;
13
+ nodeKey: string | undefined;
14
+ path: string[];
15
+ isArrayItem: boolean;
16
+ isRoot?: boolean;
17
+ }
18
+
19
+ // =============================================================================
20
+ // CONSTANTS
21
+ // =============================================================================
22
+
23
+ export const SIZE_CONFIG: Record<
24
+ MantineSize,
25
+ { icon: number; levelOffset: number }
26
+ > = {
27
+ xs: { icon: 14, levelOffset: 16 },
28
+ sm: { icon: 16, levelOffset: 20 },
29
+ md: { icon: 18, levelOffset: 24 },
30
+ lg: { icon: 20, levelOffset: 28 },
31
+ xl: { icon: 22, levelOffset: 32 },
32
+ };
33
+
34
+ export const STYLES = {
35
+ root: {
36
+ fontFamily: "var(--mantine-font-family-monospace)",
37
+ } satisfies CSSProperties,
38
+ chevron: {
39
+ flexShrink: 0,
40
+ color: "var(--mantine-color-dimmed)",
41
+ } satisfies CSSProperties,
42
+ key: {
43
+ color: "var(--mantine-color-cyan-text)",
44
+ fontWeight: 500,
45
+ } satisfies CSSProperties,
46
+ colon: {
47
+ color: "var(--mantine-color-dimmed)",
48
+ } satisfies CSSProperties,
49
+ string: {
50
+ color: "var(--mantine-color-teal-text)",
51
+ } satisfies CSSProperties,
52
+ number: {
53
+ color: "var(--mantine-color-blue-text)",
54
+ } satisfies CSSProperties,
55
+ boolean: {
56
+ color: "var(--mantine-color-violet-text)",
57
+ } satisfies CSSProperties,
58
+ null: {
59
+ color: "var(--mantine-color-dimmed)",
60
+ fontStyle: "italic",
61
+ } satisfies CSSProperties,
62
+ preview: {
63
+ color: "var(--mantine-color-dimmed)",
64
+ } satisfies CSSProperties,
65
+ };
66
+
67
+ // =============================================================================
68
+ // HELPERS
69
+ // =============================================================================
70
+
71
+ export const getValueType = (val: any): string => {
72
+ if (val === null) return "null";
73
+ if (val === undefined) return "undefined";
74
+ if (Array.isArray(val)) return "array";
75
+ return typeof val;
76
+ };