@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,5 +1,5 @@
1
1
  import { $atom, $context, $inject, $module, Alepha, AlephaError, TypeBoxError, t } from "alepha";
2
- import { AlephaReactForm, FormValidationError, useForm, useFormState } from "alepha/react/form";
2
+ import { AlephaReactForm, FormModel, FormValidationError, useFieldValue, useForm, useFormState } from "alepha/react/form";
3
3
  import { $head, AlephaReactHead, BrowserHeadProvider } from "alepha/react/head";
4
4
  import { AlephaReactI18n, useI18n } from "alepha/react/i18n";
5
5
  import { $cookie } from "alepha/server/cookies";
@@ -18,7 +18,6 @@ import { useOs } from "@mantine/hooks";
18
18
  import { DateInput, DateTimePicker, TimeInput } from "@mantine/dates";
19
19
  import { parseQueryString } from "alepha/orm";
20
20
  import { DateTimeProvider } from "alepha/datetime";
21
-
22
21
  //#region ../../src/core/atoms/alephaSidebarAtom.ts
23
22
  const alephaSidebarAtom = $atom({
24
23
  name: "alepha.ui.sidebar",
@@ -35,7 +34,6 @@ const alephaSidebarAtom = $atom({
35
34
  collapsedWidth: 72
36
35
  }
37
36
  });
38
-
39
37
  //#endregion
40
38
  //#region ../../src/core/atoms/alephaThemeAtom.ts
41
39
  const alephaThemeAtom = $atom({
@@ -43,7 +41,6 @@ const alephaThemeAtom = $atom({
43
41
  schema: t.object({ index: t.integer() }),
44
42
  default: { index: 0 }
45
43
  });
46
-
47
44
  //#endregion
48
45
  //#region ../../src/core/atoms/alephaThemeOverridesAtom.ts
49
46
  const alephaThemeOverridesAtom = $atom({
@@ -57,14 +54,12 @@ const alephaThemeOverridesAtom = $atom({
57
54
  }),
58
55
  default: {}
59
56
  });
60
-
61
57
  //#endregion
62
58
  //#region ../../src/core/atoms/themes/default.ts
63
59
  const defaultTheme = {
64
60
  name: "Default",
65
61
  description: "Default Alepha Theme"
66
62
  };
67
-
68
63
  //#endregion
69
64
  //#region ../../src/core/atoms/themes/editorial.ts
70
65
  /**
@@ -219,7 +214,6 @@ const editorialTheme = {
219
214
  })
220
215
  }
221
216
  };
222
-
223
217
  //#endregion
224
218
  //#region ../../src/core/atoms/themes/midnight.ts
225
219
  const midnightTheme = {
@@ -334,7 +328,6 @@ const midnightTheme = {
334
328
  ]
335
329
  }
336
330
  };
337
-
338
331
  //#endregion
339
332
  //#region ../../src/core/atoms/themes/monochrome.ts
340
333
  /**
@@ -502,7 +495,6 @@ const monochromeTheme = {
502
495
  })
503
496
  }
504
497
  };
505
-
506
498
  //#endregion
507
499
  //#region ../../src/core/atoms/themes/rosePine.ts
508
500
  /**
@@ -674,7 +666,6 @@ const rosePineTheme = {
674
666
  Badge: Badge.extend({ defaultProps: { fw: 500 } })
675
667
  }
676
668
  };
677
-
678
669
  //#endregion
679
670
  //#region ../../src/core/atoms/themes/softBrutalism.ts
680
671
  /**
@@ -861,7 +852,6 @@ const softBrutalismTheme = {
861
852
  })
862
853
  }
863
854
  };
864
-
865
855
  //#endregion
866
856
  //#region ../../src/core/atoms/themes/terminal.ts
867
857
  /**
@@ -1017,7 +1007,6 @@ const terminalTheme = {
1017
1007
  })
1018
1008
  }
1019
1009
  };
1020
-
1021
1010
  //#endregion
1022
1011
  //#region ../../src/core/atoms/alephaThemeListAtom.ts
1023
1012
  const alephaThemeListAtom = $atom({
@@ -1033,7 +1022,6 @@ const alephaThemeListAtom = $atom({
1033
1022
  monochromeTheme
1034
1023
  ]
1035
1024
  });
1036
-
1037
1025
  //#endregion
1038
1026
  //#region ../../src/core/providers/ThemeProvider.ts
1039
1027
  var ThemeProvider = class ThemeProvider {
@@ -1131,7 +1119,6 @@ var ThemeProvider = class ThemeProvider {
1131
1119
  }
1132
1120
  }
1133
1121
  };
1134
-
1135
1122
  //#endregion
1136
1123
  //#region ../../src/core/components/dialogs/AlertDialog.tsx
1137
1124
  const AlertDialog = ({ options, onClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [options?.message && /* @__PURE__ */ jsx(Text$1, {
@@ -1144,7 +1131,6 @@ const AlertDialog = ({ options, onClose }) => /* @__PURE__ */ jsxs(Fragment, { c
1144
1131
  children: options?.okLabel || "OK"
1145
1132
  })
1146
1133
  })] });
1147
-
1148
1134
  //#endregion
1149
1135
  //#region ../../src/core/components/dialogs/ConfirmDialog.tsx
1150
1136
  const ConfirmDialog = ({ options, onConfirm }) => /* @__PURE__ */ jsxs(Fragment, { children: [options?.message && /* @__PURE__ */ jsx(Text$1, {
@@ -1162,7 +1148,6 @@ const ConfirmDialog = ({ options, onConfirm }) => /* @__PURE__ */ jsxs(Fragment,
1162
1148
  children: options?.confirmLabel || "Confirm"
1163
1149
  })]
1164
1150
  })] });
1165
-
1166
1151
  //#endregion
1167
1152
  //#region ../../src/core/components/dialogs/PromptDialog.tsx
1168
1153
  const PromptDialog = ({ options, onSubmit }) => {
@@ -1194,6 +1179,7 @@ const PromptDialog = ({ options, onSubmit }) => {
1194
1179
  }),
1195
1180
  /* @__PURE__ */ jsxs(Flex$1, {
1196
1181
  justify: "flex-end",
1182
+ gap: "xs",
1197
1183
  children: [/* @__PURE__ */ jsx(Button, {
1198
1184
  variant: "subtle",
1199
1185
  onClick: () => onSubmit(null),
@@ -1206,7 +1192,6 @@ const PromptDialog = ({ options, onSubmit }) => {
1206
1192
  })
1207
1193
  ] });
1208
1194
  };
1209
-
1210
1195
  //#endregion
1211
1196
  //#region ../../src/core/services/DialogService.tsx
1212
1197
  var DialogService = class {
@@ -1268,8 +1253,8 @@ var DialogService = class {
1268
1253
  content: /* @__PURE__ */ jsx(ConfirmDialog, {
1269
1254
  options,
1270
1255
  onConfirm: (confirmed) => {
1271
- this.close(modalId);
1272
1256
  done(confirmed);
1257
+ this.close(modalId);
1273
1258
  }
1274
1259
  })
1275
1260
  });
@@ -1295,8 +1280,8 @@ var DialogService = class {
1295
1280
  content: /* @__PURE__ */ jsx(PromptDialog, {
1296
1281
  options,
1297
1282
  onSubmit: (value) => {
1298
- this.close(modalId);
1299
1283
  done(value);
1284
+ this.close(modalId);
1300
1285
  }
1301
1286
  })
1302
1287
  });
@@ -1320,7 +1305,6 @@ var DialogService = class {
1320
1305
  else modals.closeAll();
1321
1306
  }
1322
1307
  };
1323
-
1324
1308
  //#endregion
1325
1309
  //#region ../../src/core/services/ToastService.tsx
1326
1310
  var ToastService = class {
@@ -1379,7 +1363,6 @@ var ToastService = class {
1379
1363
  });
1380
1364
  }
1381
1365
  };
1382
-
1383
1366
  //#endregion
1384
1367
  //#region ../../src/core/UiRouter.ts
1385
1368
  /**
@@ -1394,7 +1377,6 @@ var UiRouter = class {
1394
1377
  component: AlephaMantineProvider
1395
1378
  });
1396
1379
  };
1397
-
1398
1380
  //#endregion
1399
1381
  //#region ../../src/core/hooks/useTheme.ts
1400
1382
  /**
@@ -1429,7 +1411,6 @@ const useTheme = () => {
1429
1411
  }
1430
1412
  ];
1431
1413
  };
1432
-
1433
1414
  //#endregion
1434
1415
  //#region ../../src/core/hooks/useToast.ts
1435
1416
  /**
@@ -1445,7 +1426,6 @@ const useTheme = () => {
1445
1426
  const useToast = () => {
1446
1427
  return useInject(ToastService);
1447
1428
  };
1448
-
1449
1429
  //#endregion
1450
1430
  //#region ../../src/core/components/layout/Omnibar.tsx
1451
1431
  const Omnibar = (props) => {
@@ -1477,7 +1457,6 @@ const Omnibar = (props) => {
1477
1457
  nothingFound
1478
1458
  });
1479
1459
  };
1480
-
1481
1460
  //#endregion
1482
1461
  //#region ../../src/core/components/AlephaMantineProvider.tsx
1483
1462
  const AlephaMantineProvider = (props) => {
@@ -1519,7 +1498,6 @@ const AlephaMantineProvider = (props) => {
1519
1498
  ]
1520
1499
  })] });
1521
1500
  };
1522
-
1523
1501
  //#endregion
1524
1502
  //#region ../../src/core/constants/ui.ts
1525
1503
  const ui = {
@@ -1538,51 +1516,18 @@ const ui = {
1538
1516
  xl: 32
1539
1517
  } }
1540
1518
  };
1541
-
1542
1519
  //#endregion
1543
1520
  //#region ../../src/core/helpers/isComponentType.ts
1544
1521
  function isComponentType(param) {
1545
1522
  if (isValidElement(param)) return false;
1546
1523
  return typeof param === "function" || typeof param === "object" && param !== null && "$$typeof" in param;
1547
1524
  }
1548
-
1549
1525
  //#endregion
1550
1526
  //#region ../../src/core/components/buttons/ActionButton.tsx
1551
- const ActionMenuItem = (props) => {
1552
- const { item, index } = props;
1553
- const router = useRouter();
1554
- const action = useAction({ handler: async (e) => {
1555
- await item.onClick?.();
1556
- } }, [item.onClick]);
1557
- if (item.type === "divider") return /* @__PURE__ */ jsx(Menu.Divider, {}, index);
1558
- if (item.type === "label") return /* @__PURE__ */ jsx(Menu.Label, { children: item.label }, index);
1559
- if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Menu, {
1560
- trigger: "hover",
1561
- position: "right-start",
1562
- offset: 2,
1563
- children: [/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Menu.Item, {
1564
- leftSection: item.icon,
1565
- rightSection: /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }),
1566
- children: item.label
1567
- }) }), /* @__PURE__ */ jsx(Menu.Dropdown, { children: item.children.map((child, childIndex) => /* @__PURE__ */ jsx(ActionMenuItem, {
1568
- item: child,
1569
- index: childIndex
1570
- }, childIndex)) })]
1571
- }, index);
1572
- const menuItemProps = {};
1573
- if (props.item.onClick) menuItemProps.onClick = action.run;
1574
- else if (props.item.href) Object.assign(menuItemProps, router.anchor(props.item.href));
1575
- return /* @__PURE__ */ jsx(Menu.Item, {
1576
- leftSection: item.icon ?? (item.active ? /* @__PURE__ */ jsx(IconCheck, { size: ui.sizes.icon.sm }) : /* @__PURE__ */ jsx(Flex$1, { w: ui.sizes.icon.sm })),
1577
- onClick: item.onClick,
1578
- color: item.color,
1579
- ...menuItemProps,
1580
- children: item.label
1581
- }, index);
1582
- };
1583
1527
  const ActionButton = (_props) => {
1584
1528
  const theme = useMantineTheme();
1585
1529
  const props = { ..._props };
1530
+ if (props.variant === "minimal") {}
1586
1531
  const { tooltip, menu, icon, iconSize, ...restProps } = props;
1587
1532
  if (props.intent) {
1588
1533
  if (props.intent === "primary") restProps.color ??= theme.primaryColor;
@@ -1627,6 +1572,7 @@ const ActionButton = (_props) => {
1627
1572
  children: /* @__PURE__ */ jsx(ActionButton, {
1628
1573
  px: "xs",
1629
1574
  ...rest,
1575
+ "aria-label": typeof children === "string" ? children : void 0,
1630
1576
  tooltip,
1631
1577
  menu,
1632
1578
  children: leftSection
@@ -1783,7 +1729,7 @@ const ActionClickButton = ({ preventDefault, ...props }) => {
1783
1729
  * Action for navigation with active state support.
1784
1730
  */
1785
1731
  const ActionNavigationButton = (props) => {
1786
- const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, onClick: propsOnClick, anchor, ...buttonProps } = props;
1732
+ const { active: options, classNameActive, variantActive, propsActive, routerGoOptions, onClick: propsOnClick, anchorProps: buttonAnchorProps, anchor, ...buttonProps } = props;
1787
1733
  const router = useRouter();
1788
1734
  const { isPending, isActive } = useActive(options ? {
1789
1735
  href: props.href,
@@ -1797,11 +1743,11 @@ const ActionNavigationButton = (props) => {
1797
1743
  };
1798
1744
  const className = buttonProps.className || "";
1799
1745
  if (isActive && options !== false && classNameActive) buttonProps.className = `${className} ${classNameActive}`.trim();
1800
- if (props.anchorProps || anchor) return /* @__PURE__ */ jsx(Anchor, {
1746
+ if (buttonAnchorProps || anchor) return /* @__PURE__ */ jsx(Anchor, {
1801
1747
  component: "a",
1802
1748
  ...anchorProps,
1803
1749
  ...buttonProps,
1804
- ...props.anchorProps,
1750
+ ...buttonAnchorProps,
1805
1751
  onClick: combinedOnClick,
1806
1752
  children: props.children
1807
1753
  });
@@ -1824,7 +1770,38 @@ const ActionHrefButton = (props) => {
1824
1770
  children: props.children
1825
1771
  });
1826
1772
  };
1827
-
1773
+ const ActionMenuItem = (props) => {
1774
+ const { item, index } = props;
1775
+ const router = useRouter();
1776
+ const action = useAction({ handler: async (e) => {
1777
+ await item.onClick?.();
1778
+ } }, [item.onClick]);
1779
+ if (item.type === "divider") return /* @__PURE__ */ jsx(Menu.Divider, {}, index);
1780
+ if (item.type === "label") return /* @__PURE__ */ jsx(Menu.Label, { children: item.label }, index);
1781
+ if (item.children && item.children.length > 0) return /* @__PURE__ */ jsxs(Menu, {
1782
+ trigger: "hover",
1783
+ position: "right-start",
1784
+ offset: 2,
1785
+ children: [/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(Menu.Item, {
1786
+ leftSection: item.icon,
1787
+ rightSection: /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }),
1788
+ children: item.label
1789
+ }) }), /* @__PURE__ */ jsx(Menu.Dropdown, { children: item.children.map((child, childIndex) => /* @__PURE__ */ jsx(ActionMenuItem, {
1790
+ item: child,
1791
+ index: childIndex
1792
+ }, childIndex)) })]
1793
+ }, index);
1794
+ const menuItemProps = {};
1795
+ if (props.item.onClick) menuItemProps.onClick = action.run;
1796
+ else if (props.item.href) Object.assign(menuItemProps, router.anchor(props.item.href));
1797
+ return /* @__PURE__ */ jsx(Menu.Item, {
1798
+ leftSection: item.icon ?? (item.active ? /* @__PURE__ */ jsx(IconCheck, { size: ui.sizes.icon.sm }) : /* @__PURE__ */ jsx(Flex$1, { w: ui.sizes.icon.sm })),
1799
+ onClick: item.onClick,
1800
+ color: item.color,
1801
+ ...menuItemProps,
1802
+ children: item.label
1803
+ }, index);
1804
+ };
1828
1805
  //#endregion
1829
1806
  //#region ../../src/core/components/buttons/BurgerButton.tsx
1830
1807
  const BurgerButton = (props) => {
@@ -1840,7 +1817,6 @@ const BurgerButton = (props) => {
1840
1817
  ...props
1841
1818
  });
1842
1819
  };
1843
-
1844
1820
  //#endregion
1845
1821
  //#region ../../src/core/components/buttons/ClipboardButton.tsx
1846
1822
  const ClipboardButton = (props) => {
@@ -1861,7 +1837,6 @@ const ClipboardButton = (props) => {
1861
1837
  })
1862
1838
  });
1863
1839
  };
1864
-
1865
1840
  //#endregion
1866
1841
  //#region ../../src/core/components/buttons/DarkModeButton.tsx
1867
1842
  /**
@@ -1893,7 +1868,6 @@ const DarkModeButton = (props) => {
1893
1868
  ...props
1894
1869
  });
1895
1870
  };
1896
-
1897
1871
  //#endregion
1898
1872
  //#region ../../src/core/components/buttons/LanguageButton.tsx
1899
1873
  const LanguageButton = (props) => {
@@ -1909,7 +1883,6 @@ const LanguageButton = (props) => {
1909
1883
  ...props
1910
1884
  });
1911
1885
  };
1912
-
1913
1886
  //#endregion
1914
1887
  //#region ../../src/core/components/buttons/OmnibarButton.tsx
1915
1888
  const OmnibarButton = (props) => {
@@ -1954,7 +1927,6 @@ const OmnibarButton = (props) => {
1954
1927
  })
1955
1928
  });
1956
1929
  };
1957
-
1958
1930
  //#endregion
1959
1931
  //#region ../../src/core/hooks/useDialog.ts
1960
1932
  /**
@@ -1971,7 +1943,6 @@ const OmnibarButton = (props) => {
1971
1943
  const useDialog = () => {
1972
1944
  return useInject(DialogService);
1973
1945
  };
1974
-
1975
1946
  //#endregion
1976
1947
  //#region ../../src/core/components/buttons/ThemeExpertModal.tsx
1977
1948
  const MANTINE_COLORS = [
@@ -2180,7 +2151,6 @@ const ThemeExpertModal = () => {
2180
2151
  ]
2181
2152
  });
2182
2153
  };
2183
-
2184
2154
  //#endregion
2185
2155
  //#region ../../src/core/components/buttons/ThemeButton.tsx
2186
2156
  const ThemeButton = (props) => {
@@ -2209,7 +2179,6 @@ const ThemeButton = (props) => {
2209
2179
  ...actionProps
2210
2180
  });
2211
2181
  };
2212
-
2213
2182
  //#endregion
2214
2183
  //#region ../../src/core/components/buttons/ToggleSidebarButton.tsx
2215
2184
  const ToggleSidebarButton = (props) => {
@@ -2231,102 +2200,104 @@ const ToggleSidebarButton = (props) => {
2231
2200
  ...props
2232
2201
  });
2233
2202
  };
2234
-
2235
2203
  //#endregion
2236
2204
  //#region ../../src/core/components/data/DetailDrawer.tsx
2237
- const DetailDrawer = ({ opened, onClose, title, subtitle, status, actions, tabs, children, loading, size = "xl", defaultTab }) => /* @__PURE__ */ jsxs(Drawer, {
2238
- opened,
2239
- onClose,
2240
- position: "right",
2241
- size,
2242
- withCloseButton: false,
2243
- padding: 0,
2244
- children: [/* @__PURE__ */ jsxs(Flex$1, {
2245
- p: "md",
2246
- justify: "space-between",
2247
- align: "flex-start",
2248
- style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
2205
+ const DetailDrawer = (props) => {
2206
+ const { opened, onClose, title, subtitle, status, actions, tabs, children, loading, size = "xl", defaultTab } = props;
2207
+ return /* @__PURE__ */ jsxs(Drawer, {
2208
+ opened,
2209
+ onClose,
2210
+ position: "right",
2211
+ size,
2212
+ withCloseButton: false,
2213
+ padding: 0,
2249
2214
  children: [/* @__PURE__ */ jsxs(Flex$1, {
2250
- direction: "column",
2251
- gap: 2,
2252
- style: {
2253
- minWidth: 0,
2254
- flex: 1
2255
- },
2215
+ p: "md",
2216
+ justify: "space-between",
2217
+ align: "flex-start",
2218
+ style: { borderBottom: "1px solid var(--mantine-color-default-border)" },
2256
2219
  children: [/* @__PURE__ */ jsxs(Flex$1, {
2220
+ direction: "column",
2221
+ gap: 2,
2222
+ style: {
2223
+ minWidth: 0,
2224
+ flex: 1
2225
+ },
2226
+ children: [/* @__PURE__ */ jsxs(Flex$1, {
2227
+ gap: "xs",
2228
+ align: "center",
2229
+ children: [status && /* @__PURE__ */ jsx(Flex$1, {
2230
+ w: 8,
2231
+ h: 8,
2232
+ style: {
2233
+ borderRadius: "50%",
2234
+ backgroundColor: status.active ? "var(--mantine-color-green-6)" : "var(--mantine-color-red-6)",
2235
+ flexShrink: 0
2236
+ }
2237
+ }), /* @__PURE__ */ jsx(Text$1, {
2238
+ size: "lg",
2239
+ fw: 600,
2240
+ truncate: true,
2241
+ children: title
2242
+ })]
2243
+ }), subtitle && /* @__PURE__ */ jsx(Text$1, {
2244
+ size: "sm",
2245
+ c: "dimmed",
2246
+ truncate: true,
2247
+ children: subtitle
2248
+ })]
2249
+ }), /* @__PURE__ */ jsxs(Flex$1, {
2257
2250
  gap: "xs",
2258
2251
  align: "center",
2259
- children: [status && /* @__PURE__ */ jsx(Flex$1, {
2260
- w: 8,
2261
- h: 8,
2262
- style: {
2263
- borderRadius: "50%",
2264
- backgroundColor: status.active ? "var(--mantine-color-green-6)" : "var(--mantine-color-red-6)",
2265
- flexShrink: 0
2266
- }
2267
- }), /* @__PURE__ */ jsx(Text$1, {
2268
- size: "lg",
2269
- fw: 600,
2270
- truncate: true,
2271
- children: title
2252
+ style: { flexShrink: 0 },
2253
+ children: [actions && actions.length > 0 && /* @__PURE__ */ jsx(ActionButton, {
2254
+ variant: "default",
2255
+ size: "xs",
2256
+ menu: {
2257
+ items: actions,
2258
+ position: "bottom-end",
2259
+ width: 200
2260
+ },
2261
+ children: "Actions"
2262
+ }), /* @__PURE__ */ jsx(ActionButton, {
2263
+ variant: "subtle",
2264
+ size: "xs",
2265
+ c: "dimmed",
2266
+ onClick: onClose,
2267
+ children: "Close"
2272
2268
  })]
2273
- }), subtitle && /* @__PURE__ */ jsx(Text$1, {
2274
- size: "sm",
2275
- c: "dimmed",
2276
- truncate: true,
2277
- children: subtitle
2278
2269
  })]
2279
- }), /* @__PURE__ */ jsxs(Flex$1, {
2280
- gap: "xs",
2270
+ }), loading ? /* @__PURE__ */ jsx(Flex$1, {
2271
+ flex: 1,
2272
+ justify: "center",
2281
2273
  align: "center",
2282
- style: { flexShrink: 0 },
2283
- children: [actions && actions.length > 0 && /* @__PURE__ */ jsx(ActionButton, {
2284
- variant: "default",
2285
- size: "xs",
2286
- menu: {
2287
- items: actions,
2288
- position: "bottom-end",
2289
- width: 200
2290
- },
2291
- children: "Actions"
2292
- }), /* @__PURE__ */ jsx(ActionButton, {
2293
- variant: "subtle",
2294
- size: "xs",
2295
- c: "dimmed",
2296
- onClick: onClose,
2297
- children: "Close"
2298
- })]
2299
- })]
2300
- }), loading ? /* @__PURE__ */ jsx(Flex$1, {
2301
- flex: 1,
2302
- justify: "center",
2303
- align: "center",
2304
- py: "xl",
2305
- children: /* @__PURE__ */ jsx(Loader, {})
2306
- }) : tabs && tabs.length > 0 ? /* @__PURE__ */ jsxs(Tabs, {
2307
- defaultValue: defaultTab || tabs[0].value,
2308
- children: [/* @__PURE__ */ jsx(Tabs.List, {
2309
- px: "md",
2310
- children: tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Tab, {
2274
+ py: "xl",
2275
+ children: /* @__PURE__ */ jsx(Loader, {})
2276
+ }) : tabs && tabs.length > 0 ? /* @__PURE__ */ jsxs(Tabs, {
2277
+ defaultValue: defaultTab || tabs[0].value,
2278
+ children: [/* @__PURE__ */ jsx(Tabs.List, {
2279
+ px: "md",
2280
+ children: tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Tab, {
2281
+ value: tab.value,
2282
+ leftSection: tab.icon ? /* @__PURE__ */ jsx(tab.icon, { size: 14 }) : void 0,
2283
+ children: tab.label
2284
+ }, tab.value))
2285
+ }), tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Panel, {
2311
2286
  value: tab.value,
2312
- leftSection: tab.icon ? /* @__PURE__ */ jsx(tab.icon, { size: 14 }) : void 0,
2313
- children: tab.label
2314
- }, tab.value))
2315
- }), tabs.map((tab) => /* @__PURE__ */ jsx(Tabs.Panel, {
2316
- value: tab.value,
2287
+ p: "md",
2288
+ children: tab.content
2289
+ }, tab.value))]
2290
+ }) : /* @__PURE__ */ jsx(Flex$1, {
2291
+ direction: "column",
2317
2292
  p: "md",
2318
- children: tab.content
2319
- }, tab.value))]
2320
- }) : /* @__PURE__ */ jsx(Flex$1, {
2321
- direction: "column",
2322
- p: "md",
2323
- children
2324
- })]
2325
- });
2326
-
2293
+ children
2294
+ })]
2295
+ });
2296
+ };
2327
2297
  //#endregion
2328
2298
  //#region ../../src/core/components/data/DetailList.tsx
2329
- const DetailList = ({ items, columns = 1 }) => {
2299
+ const DetailList = (props) => {
2300
+ const { items, columns = 1 } = props;
2330
2301
  return /* @__PURE__ */ jsx(Grid, {
2331
2302
  gutter: "xs",
2332
2303
  children: items.filter((item) => !item.hidden).map((item) => /* @__PURE__ */ jsx(Grid.Col, {
@@ -2365,7 +2336,6 @@ const DetailList = ({ items, columns = 1 }) => {
2365
2336
  }, item.label))
2366
2337
  });
2367
2338
  };
2368
-
2369
2339
  //#endregion
2370
2340
  //#region ../../src/core/components/data/StatCards.tsx
2371
2341
  const StatCards = ({ items }) => /* @__PURE__ */ jsx(Flex$1, {
@@ -2401,11 +2371,10 @@ const StatCards = ({ items }) => /* @__PURE__ */ jsx(Flex$1, {
2401
2371
  }, item.label);
2402
2372
  })
2403
2373
  });
2404
-
2405
2374
  //#endregion
2406
2375
  //#region ../../src/core/components/Flex.tsx
2407
2376
  const Flex = forwardRef((props, ref) => {
2408
- const { fill, center, centerX, centerY, col, ground, surface, elevated, rounded, bordered, borderedTop, borderedBottom, shadowed, ...rest } = props;
2377
+ const { fill, center, centerX, centerY, col, ground, surface, elevated, rounded, bordered, borderedTop, borderedBottom, shadowed, overflow, form, ...rest } = props;
2409
2378
  if (fill) rest.flex ??= 1;
2410
2379
  if (col) rest.direction ??= "column";
2411
2380
  if (center) {
@@ -2428,19 +2397,28 @@ const Flex = forwardRef((props, ref) => {
2428
2397
  ...rest.style ?? {}
2429
2398
  };
2430
2399
  if (shadowed) rest.className = `${rest.className ?? ""} shadow-${shadowed === true ? "md" : shadowed}`.trim();
2400
+ if (overflow) rest.className = `${rest.className ?? ""} overflow-auto`.trim();
2401
+ if (form) {
2402
+ let formProps = typeof form === "object" ? form : {};
2403
+ if (formProps instanceof FormModel) formProps = formProps.props;
2404
+ return /* @__PURE__ */ jsx(Flex$1, {
2405
+ ref,
2406
+ component: "form",
2407
+ ...formProps,
2408
+ ...rest
2409
+ });
2410
+ }
2431
2411
  return /* @__PURE__ */ jsx(Flex$1, {
2432
2412
  ref,
2433
2413
  ...rest
2434
2414
  });
2435
2415
  });
2436
2416
  Flex.displayName = "Flex";
2437
-
2438
2417
  //#endregion
2439
2418
  //#region ../../src/core/components/Heading.tsx
2440
2419
  const Heading = (props) => {
2441
2420
  return /* @__PURE__ */ jsx("h1", { children: "Heading" });
2442
2421
  };
2443
-
2444
2422
  //#endregion
2445
2423
  //#region ../../src/core/components/layout/AppBar.tsx
2446
2424
  const AppBar = (props) => {
@@ -2555,7 +2533,6 @@ const AppBar = (props) => {
2555
2533
  });
2556
2534
  return content;
2557
2535
  };
2558
-
2559
2536
  //#endregion
2560
2537
  //#region ../../src/core/components/layout/Breadcrumb.tsx
2561
2538
  /**
@@ -2565,7 +2542,8 @@ const AppBar = (props) => {
2565
2542
  * Pages should define a `label` in their `$page()` options for best results.
2566
2543
  * Falls back to the page name converted to Title Case.
2567
2544
  */
2568
- const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) => {
2545
+ const Breadcrumbs = (props) => {
2546
+ const { home = "Home", separator, size = "sm", ...groupProps } = props;
2569
2547
  const state = useRouterState();
2570
2548
  const router = useRouter();
2571
2549
  const crumbs = [];
@@ -2609,7 +2587,6 @@ const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) =>
2609
2587
  }, crumb.href))
2610
2588
  });
2611
2589
  };
2612
-
2613
2590
  //#endregion
2614
2591
  //#region ../../src/core/components/layout/Container.tsx
2615
2592
  const Container = forwardRef((props, ref) => {
@@ -2619,69 +2596,228 @@ const Container = forwardRef((props, ref) => {
2619
2596
  });
2620
2597
  });
2621
2598
  Container.displayName = "Container";
2622
-
2623
2599
  //#endregion
2624
- //#region ../../src/core/components/layout/Sidebar.tsx
2625
- const Sidebar = (props) => {
2600
+ //#region ../../src/core/helpers/renderIcon.tsx
2601
+ const renderIcon = (icon, size) => {
2602
+ if (!icon) return null;
2603
+ if (isValidElement(icon)) return icon;
2604
+ if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
2605
+ return icon;
2606
+ };
2607
+ //#endregion
2608
+ //#region ../../src/core/components/Text.tsx
2609
+ const INTENT_COLORS = {
2610
+ primary: "blue",
2611
+ info: "cyan",
2612
+ success: "green",
2613
+ warning: "yellow",
2614
+ danger: "red"
2615
+ };
2616
+ const Text = forwardRef((props, ref) => {
2617
+ const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
2618
+ if (intent) rest.c ??= INTENT_COLORS[intent];
2619
+ if (bold) rest.fw ??= 700;
2620
+ if (light) rest.fw ??= 300;
2621
+ if (italic) rest.fs ??= "italic";
2622
+ if (muted) rest.c ??= "dimmed";
2623
+ if (small) rest.size ??= "xs";
2624
+ if (uppercase) rest.tt ??= "uppercase";
2625
+ if (capitalize) rest.tt ??= "capitalize";
2626
+ if (center) rest.ta ??= "center";
2627
+ if (monospace) rest.ff ??= "monospace";
2628
+ if (title) rest.size ??= "xl";
2629
+ return /* @__PURE__ */ jsx(Text$1, {
2630
+ ref,
2631
+ ...rest
2632
+ });
2633
+ });
2634
+ Text.displayName = "Text";
2635
+ //#endregion
2636
+ //#region ../../src/core/components/layout/SidebarCollapsedItem.tsx
2637
+ const SidebarCollapsedItem = (props) => {
2626
2638
  const router = useRouter();
2627
- const { onItemClick } = props;
2628
- const divider = (key, fill, collapsed) => {
2629
- return /* @__PURE__ */ jsx(Flex, {
2630
- h: 1,
2631
- bg: "var(--mantine-color-default-border)",
2632
- my: "xs",
2633
- mx: fill ? "calc(-1 * var(--mantine-spacing-md))" : collapsed ? 0 : "sm"
2634
- }, key);
2639
+ const handleItemClick = () => {
2640
+ props.onItemClick?.(props.item);
2641
+ props.item.onClick?.();
2635
2642
  };
2636
- const renderNode = (item, key, collapsed) => {
2637
- if ("type" in item) {
2638
- if (item.type === "spacer") {
2639
- if (collapsed) return null;
2640
- return /* @__PURE__ */ jsx(Flex, { h: 16 }, key);
2641
- }
2642
- if (item.type === "divider") return divider(key, item.fill, collapsed);
2643
- if (item.type === "search") return /* @__PURE__ */ jsx(Flex, {
2644
- mb: "xs",
2645
- w: "100%",
2646
- justify: "center",
2647
- pos: "relative",
2648
- children: /* @__PURE__ */ jsx(OmnibarButton, { collapsed })
2649
- }, key);
2650
- if (item.type === "toggle") return /* @__PURE__ */ jsx(ToggleSidebarButton, {}, key);
2651
- if (item.type === "section") {
2652
- if (item.children && item.children.length > 0) {
2653
- if (!item.children.some((child) => !("can" in child) || !child.can || child.can())) return null;
2654
- }
2655
- if (collapsed) return /* @__PURE__ */ jsx(Fragment$1, { children: item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed)) }, key);
2656
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Flex, {
2657
- mt: "md",
2658
- align: "center",
2659
- gap: "xs",
2660
- children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Text, {
2661
- size: "xs",
2662
- c: "dimmed",
2663
- tt: "uppercase",
2664
- fw: "bold",
2665
- children: item.label
2666
- })]
2667
- }), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed))] }, key);
2668
- }
2669
- }
2670
- if ("element" in item) return /* @__PURE__ */ jsx(Fragment$1, { children: item.element }, key);
2671
- if (item.can && !item.can()) return null;
2672
- if (item.children && item.children.length > 0) {
2643
+ const hasChildren = props.item.children && props.item.children.length > 0;
2644
+ const menu = hasChildren ? {
2645
+ on: "hover",
2646
+ position: "right",
2647
+ menuProps: {
2648
+ arrowPosition: "center",
2649
+ arrowSize: 10,
2650
+ withArrow: true
2651
+ },
2652
+ items: [{
2653
+ type: "label",
2654
+ label: props.item.label
2655
+ }, ...props.item.children.filter((child) => !child.can || child.can()).map((child) => ({
2656
+ label: child.label,
2657
+ icon: renderIcon(child.icon, ui.sizes.icon.sm),
2658
+ href: child.href,
2659
+ active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
2660
+ }))]
2661
+ } : void 0;
2662
+ return /* @__PURE__ */ jsx(Flex, {
2663
+ w: "100%",
2664
+ justify: "center",
2665
+ pos: "relative",
2666
+ children: /* @__PURE__ */ jsx(ActionButton, {
2667
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2668
+ bd: 0,
2669
+ variant: "default",
2670
+ propsActive: { variant: "outline" },
2671
+ tooltip: hasChildren ? void 0 : {
2672
+ label: props.item.label,
2673
+ position: "right"
2674
+ },
2675
+ onClick: hasChildren ? void 0 : handleItemClick,
2676
+ icon: renderIcon(props.item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
2677
+ href: hasChildren ? void 0 : props.item.href,
2678
+ target: hasChildren ? void 0 : props.item.target,
2679
+ menu,
2680
+ ...props.item.actionProps
2681
+ })
2682
+ });
2683
+ };
2684
+ //#endregion
2685
+ //#region ../../src/core/components/layout/SidebarItem.tsx
2686
+ const SidebarItem = (props) => {
2687
+ const maxLevel = 2;
2688
+ const router = useRouter();
2689
+ const isActive = useCallback((item) => {
2690
+ if (!item.children) return false;
2691
+ for (const child of item.children) {
2692
+ if (child.href) {
2693
+ if (router.isActive(child.href)) return true;
2694
+ }
2695
+ if (isActive(child)) return true;
2696
+ }
2697
+ return false;
2698
+ }, []);
2699
+ const [isOpen, setIsOpen] = useState(isActive(props.item));
2700
+ useEvents({ "react:transition:end": () => {
2701
+ if (isActive(props.item)) setIsOpen(true);
2702
+ } }, []);
2703
+ if (props.level > maxLevel) return null;
2704
+ const handleItemClick = (e) => {
2705
+ if (!props.item.target) e.preventDefault();
2706
+ if (props.item.children && props.item.children.length > 0) setIsOpen(!isOpen);
2707
+ else {
2708
+ props.onItemClick?.(props.item);
2709
+ props.item.onClick?.();
2710
+ }
2711
+ };
2712
+ return /* @__PURE__ */ jsxs(Flex, {
2713
+ direction: "column",
2714
+ ps: props.level === 0 ? 0 : 32,
2715
+ pos: "relative",
2716
+ children: [/* @__PURE__ */ jsx(ActionButton, {
2717
+ w: "100%",
2718
+ justify: "space-between",
2719
+ href: props.item.href,
2720
+ target: props.item.target,
2721
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2722
+ bd: 0,
2723
+ fw: "normal",
2724
+ variant: "default",
2725
+ propsActive: { variant: "outline" },
2726
+ radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
2727
+ onClick: handleItemClick,
2728
+ leftSection: /* @__PURE__ */ jsxs(Flex, {
2729
+ w: "100%",
2730
+ align: "center",
2731
+ gap: "sm",
2732
+ children: [renderIcon(props.item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex, {
2733
+ direction: "column",
2734
+ children: /* @__PURE__ */ jsx(Flex, { children: props.item.label })
2735
+ })]
2736
+ }),
2737
+ rightSection: props.item.children ? /* @__PURE__ */ jsx(Flex, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
2738
+ ...props.item.actionProps
2739
+ }), props.item.children && isOpen && /* @__PURE__ */ jsxs(Flex, {
2740
+ direction: "column",
2741
+ "data-parent-level": props.level,
2742
+ gap: 2,
2743
+ py: 2,
2744
+ children: [/* @__PURE__ */ jsx(Flex, { style: {
2745
+ position: "absolute",
2746
+ width: 1,
2747
+ background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
2748
+ top: 48,
2749
+ left: 20 + 32 * props.level,
2750
+ bottom: 16
2751
+ } }), props.item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
2752
+ item: child,
2753
+ level: props.level + 1,
2754
+ onItemClick: props.onItemClick,
2755
+ theme: props.theme
2756
+ }, index))]
2757
+ })]
2758
+ });
2759
+ };
2760
+ //#endregion
2761
+ //#region ../../src/core/components/layout/Sidebar.tsx
2762
+ const Sidebar = (props) => {
2763
+ const router = useRouter();
2764
+ const divider = (key, fill, collapsed) => {
2765
+ return /* @__PURE__ */ jsx(Flex, {
2766
+ h: 1,
2767
+ bg: "var(--mantine-color-default-border)",
2768
+ my: "xs",
2769
+ mx: fill ? "calc(-1 * var(--mantine-spacing-md))" : collapsed ? 0 : "sm"
2770
+ }, key);
2771
+ };
2772
+ const renderNode = (item, key, collapsed) => {
2773
+ if ("type" in item) {
2774
+ if (item.type === "spacer") {
2775
+ if (collapsed) return null;
2776
+ return /* @__PURE__ */ jsx(Flex, { h: 16 }, key);
2777
+ }
2778
+ if (item.type === "divider") return divider(key, item.fill, collapsed);
2779
+ if (item.type === "search") return /* @__PURE__ */ jsx(Flex, {
2780
+ mb: "xs",
2781
+ w: "100%",
2782
+ justify: "center",
2783
+ pos: "relative",
2784
+ children: /* @__PURE__ */ jsx(OmnibarButton, { collapsed })
2785
+ }, key);
2786
+ if (item.type === "toggle") return /* @__PURE__ */ jsx(ToggleSidebarButton, {}, key);
2787
+ if (item.type === "section") {
2788
+ if (item.children && item.children.length > 0) {
2789
+ if (!item.children.some((child) => !("can" in child) || !child.can || child.can())) return null;
2790
+ }
2791
+ if (collapsed) return /* @__PURE__ */ jsx(Fragment$1, { children: item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed)) }, key);
2792
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Flex, {
2793
+ mt: "md",
2794
+ align: "center",
2795
+ gap: "xs",
2796
+ children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Text, {
2797
+ size: "xs",
2798
+ c: "dimmed",
2799
+ tt: "uppercase",
2800
+ fw: "bold",
2801
+ children: item.label
2802
+ })]
2803
+ }), item.children?.map((child, index) => renderNode(child, `s${key}-${index}`, collapsed))] }, key);
2804
+ }
2805
+ }
2806
+ if ("element" in item) return /* @__PURE__ */ jsx(Fragment$1, { children: item.element }, key);
2807
+ if (item.can && !item.can()) return null;
2808
+ if (item.children && item.children.length > 0) {
2673
2809
  if (!item.children.some((child) => !child.can || child.can())) return null;
2674
2810
  }
2675
2811
  if (collapsed) return /* @__PURE__ */ jsx(SidebarCollapsedItem, {
2676
2812
  item,
2677
2813
  level: 0,
2678
- onItemClick,
2814
+ onItemClick: props.onItemClick,
2679
2815
  theme: props.theme ?? {}
2680
2816
  }, key);
2681
2817
  return /* @__PURE__ */ jsx(SidebarItem, {
2682
2818
  item,
2683
2819
  level: 0,
2684
- onItemClick,
2820
+ onItemClick: props.onItemClick,
2685
2821
  theme: props.theme ?? {}
2686
2822
  }, key);
2687
2823
  };
@@ -2744,130 +2880,6 @@ const Sidebar = (props) => {
2744
2880
  })] });
2745
2881
  return renderSidebar(false);
2746
2882
  };
2747
- const SidebarItem = (props) => {
2748
- const { item, level } = props;
2749
- const maxLevel = 2;
2750
- const router = useRouter();
2751
- const isActive = useCallback((item) => {
2752
- if (!item.children) return false;
2753
- for (const child of item.children) {
2754
- if (child.href) {
2755
- if (router.isActive(child.href)) return true;
2756
- }
2757
- if (isActive(child)) return true;
2758
- }
2759
- return false;
2760
- }, []);
2761
- const [isOpen, setIsOpen] = useState(isActive(item));
2762
- useEvents({ "react:transition:end": () => {
2763
- if (isActive(item)) setIsOpen(true);
2764
- } }, []);
2765
- if (level > maxLevel) return null;
2766
- const handleItemClick = (e) => {
2767
- if (!props.item.target) e.preventDefault();
2768
- if (item.children && item.children.length > 0) setIsOpen(!isOpen);
2769
- else {
2770
- props.onItemClick?.(item);
2771
- item.onClick?.();
2772
- }
2773
- };
2774
- return /* @__PURE__ */ jsxs(Flex, {
2775
- direction: "column",
2776
- ps: level === 0 ? 0 : 32,
2777
- pos: "relative",
2778
- children: [/* @__PURE__ */ jsx(ActionButton, {
2779
- w: "100%",
2780
- justify: "space-between",
2781
- href: props.item.href,
2782
- target: props.item.target,
2783
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
2784
- bd: 0,
2785
- fw: "normal",
2786
- variant: "default",
2787
- propsActive: { variant: "outline" },
2788
- radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
2789
- onClick: handleItemClick,
2790
- leftSection: /* @__PURE__ */ jsxs(Flex, {
2791
- w: "100%",
2792
- align: "center",
2793
- gap: "sm",
2794
- children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex, {
2795
- direction: "column",
2796
- children: /* @__PURE__ */ jsx(Flex, { children: item.label })
2797
- })]
2798
- }),
2799
- rightSection: item.children ? /* @__PURE__ */ jsx(Flex, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
2800
- ...props.item.actionProps
2801
- }), item.children && isOpen && /* @__PURE__ */ jsxs(Flex, {
2802
- direction: "column",
2803
- "data-parent-level": level,
2804
- gap: 2,
2805
- py: 2,
2806
- children: [/* @__PURE__ */ jsx(Flex, { style: {
2807
- position: "absolute",
2808
- width: 1,
2809
- background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
2810
- top: 48,
2811
- left: 20 + 32 * level,
2812
- bottom: 16
2813
- } }), item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
2814
- item: child,
2815
- level: level + 1,
2816
- onItemClick: props.onItemClick,
2817
- theme: props.theme
2818
- }, index))]
2819
- })]
2820
- });
2821
- };
2822
- const SidebarCollapsedItem = (props) => {
2823
- const { item, level } = props;
2824
- const router = useRouter();
2825
- const handleItemClick = () => {
2826
- props.onItemClick?.(item);
2827
- item.onClick?.();
2828
- };
2829
- const hasChildren = item.children && item.children.length > 0;
2830
- const menu = hasChildren ? {
2831
- on: "hover",
2832
- position: "right",
2833
- menuProps: {
2834
- arrowPosition: "center",
2835
- arrowSize: 10,
2836
- withArrow: true
2837
- },
2838
- items: [{
2839
- type: "label",
2840
- label: item.label
2841
- }, ...item.children.filter((child) => !child.can || child.can()).map((child) => ({
2842
- label: child.label,
2843
- icon: renderIcon(child.icon, ui.sizes.icon.sm),
2844
- href: child.href,
2845
- active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
2846
- }))]
2847
- } : void 0;
2848
- return /* @__PURE__ */ jsx(Flex, {
2849
- w: "100%",
2850
- justify: "center",
2851
- pos: "relative",
2852
- children: /* @__PURE__ */ jsx(ActionButton, {
2853
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
2854
- bd: 0,
2855
- variant: "default",
2856
- propsActive: { variant: "outline" },
2857
- tooltip: hasChildren ? void 0 : {
2858
- label: item.label,
2859
- position: "right"
2860
- },
2861
- onClick: hasChildren ? void 0 : handleItemClick,
2862
- icon: renderIcon(item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
2863
- href: hasChildren ? void 0 : props.item.href,
2864
- target: hasChildren ? void 0 : props.item.target,
2865
- menu,
2866
- ...props.item.actionProps
2867
- })
2868
- });
2869
- };
2870
-
2871
2883
  //#endregion
2872
2884
  //#region ../../src/core/components/layout/DashboardShell.tsx
2873
2885
  const DashboardShell = (props) => {
@@ -2907,6 +2919,8 @@ const DashboardShell = (props) => {
2907
2919
  const fHeight = props.footerHeight ?? 24;
2908
2920
  const headerHeight = hasAppBar ? hHeight : 0;
2909
2921
  const footerHeight = footerElement ? fHeight : 0;
2922
+ const navbarWidth = collapsed ? collapsedWidth : expandedWidth;
2923
+ const mainContent = props.children ?? /* @__PURE__ */ jsx(NestedView, {});
2910
2924
  return /* @__PURE__ */ jsxs(AppShell, {
2911
2925
  layout: "alt",
2912
2926
  w: "100%",
@@ -2914,7 +2928,7 @@ const DashboardShell = (props) => {
2914
2928
  flex: 1,
2915
2929
  header: hasAppBar ? { height: hHeight } : void 0,
2916
2930
  navbar: hasSidebar ? {
2917
- width: { base: collapsed ? collapsedWidth : expandedWidth },
2931
+ width: { base: navbarWidth },
2918
2932
  breakpoint: "md",
2919
2933
  collapsed: { mobile: sidebar.closed }
2920
2934
  } : void 0,
@@ -2951,8 +2965,12 @@ const DashboardShell = (props) => {
2951
2965
  display: "flex",
2952
2966
  bg: "var(--alepha-ground)",
2953
2967
  pos: "relative",
2968
+ h: props.fill ? "100%" : "inherit",
2954
2969
  ...props.appShellMainProps,
2955
- children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
2970
+ children: props.container ? /* @__PURE__ */ jsx(Container, {
2971
+ ...typeof props.container === "boolean" ? {} : props.container,
2972
+ children: mainContent
2973
+ }) : mainContent
2956
2974
  }),
2957
2975
  footerElement && /* @__PURE__ */ jsx(AppShell.Footer, {
2958
2976
  ...props.appShellFooterProps,
@@ -2961,42 +2979,12 @@ const DashboardShell = (props) => {
2961
2979
  ]
2962
2980
  });
2963
2981
  };
2964
-
2965
- //#endregion
2966
- //#region ../../src/core/components/Text.tsx
2967
- const INTENT_COLORS = {
2968
- primary: "blue",
2969
- info: "cyan",
2970
- success: "green",
2971
- warning: "yellow",
2972
- danger: "red"
2973
- };
2974
- const Text = forwardRef((props, ref) => {
2975
- const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
2976
- if (intent) rest.c ??= INTENT_COLORS[intent];
2977
- if (bold) rest.fw ??= 700;
2978
- if (light) rest.fw ??= 300;
2979
- if (italic) rest.fs ??= "italic";
2980
- if (muted) rest.c ??= "dimmed";
2981
- if (small) rest.size ??= "xs";
2982
- if (uppercase) rest.tt ??= "uppercase";
2983
- if (capitalize) rest.tt ??= "capitalize";
2984
- if (center) rest.ta ??= "center";
2985
- if (monospace) rest.ff ??= "monospace";
2986
- if (title) rest.size ??= "xl";
2987
- return /* @__PURE__ */ jsx(Text$1, {
2988
- ref,
2989
- ...rest
2990
- });
2991
- });
2992
- Text.displayName = "Text";
2993
-
2994
2982
  //#endregion
2995
2983
  //#region ../../src/core/form/utils/parseInput.ts
2996
2984
  const parseInput = (props, form) => {
2997
2985
  const disabled = false;
2998
2986
  const id = props.input.props.id;
2999
- const label = props.title ?? ("title" in props.input.schema && typeof props.input.schema.title === "string" ? props.input.schema.title : void 0) ?? prettyName(props.input.path);
2987
+ const label = props.label ?? ("title" in props.input.schema && typeof props.input.schema.title === "string" ? props.input.schema.title : void 0) ?? prettyName(props.input.path);
3000
2988
  const description = props.description ?? ("description" in props.input.schema && typeof props.input.schema.description === "string" ? props.input.schema.description : void 0);
3001
2989
  const error = form.error && form.error instanceof TypeBoxError ? form.error.value.message : void 0;
3002
2990
  const icon = !props.icon ? getDefaultIcon({
@@ -3004,17 +2992,20 @@ const parseInput = (props, form) => {
3004
2992
  format: props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0,
3005
2993
  name: props.input.props.name,
3006
2994
  isEnum: props.input.schema && "enum" in props.input.schema && Boolean(props.input.schema.enum),
3007
- isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array"
3008
- }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.md });
2995
+ isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array",
2996
+ size: props.size
2997
+ }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.sm });
3009
2998
  const format = props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0;
3010
2999
  const required = props.input.required;
3011
3000
  const schema = props.input.schema;
3001
+ const testId = props.input.props?.["data-testid"];
3012
3002
  const inputProps = {
3013
3003
  label,
3014
3004
  description,
3015
3005
  error,
3016
3006
  required,
3017
- disabled
3007
+ disabled,
3008
+ ...testId ? { "data-testid": testId } : {}
3018
3009
  };
3019
3010
  if ("minLength" in schema && typeof schema.minLength === "number") inputProps.minLength = schema.minLength;
3020
3011
  if ("maxLength" in schema && typeof schema.maxLength === "number") inputProps.maxLength = schema.maxLength;
@@ -3028,7 +3019,6 @@ const parseInput = (props, form) => {
3028
3019
  inputProps
3029
3020
  };
3030
3021
  };
3031
-
3032
3022
  //#endregion
3033
3023
  //#region ../../src/core/form/components/ControlArray.tsx
3034
3024
  /**
@@ -3039,8 +3029,8 @@ const useArrayItems = (input) => {
3039
3029
  const alepha = useAlepha();
3040
3030
  const keyCounter = useRef(0);
3041
3031
  const [items, setItemsState] = useState(() => {
3042
- const defaultValue = input?.props?.defaultValue;
3043
- if (Array.isArray(defaultValue)) return defaultValue.map((value) => ({
3032
+ const initial = input?.initialValue;
3033
+ if (Array.isArray(initial)) return initial.map((value) => ({
3044
3034
  key: keyCounter.current++,
3045
3035
  value
3046
3036
  }));
@@ -3066,22 +3056,9 @@ const useArrayItems = (input) => {
3066
3056
  if (!input?.form) return;
3067
3057
  const formId = input.form.id;
3068
3058
  const fieldPath = input.path;
3069
- const listeners = [alepha.events.on("form:reset", (event) => {
3070
- if (event.id === formId) {
3071
- const defaultValue = input.props?.defaultValue;
3072
- keyCounter.current = 0;
3073
- if (Array.isArray(defaultValue)) setItemsState(defaultValue.map((value) => ({
3074
- key: keyCounter.current++,
3075
- value
3076
- })));
3077
- else setItemsState([]);
3078
- }
3079
- }), alepha.events.on("form:change", (event) => {
3059
+ return alepha.events.on("form:change", (event) => {
3080
3060
  if (event.id === formId && event.path === fieldPath) syncFromFormValue(event.value);
3081
- })];
3082
- return () => {
3083
- for (const unsub of listeners) unsub();
3084
- };
3061
+ });
3085
3062
  }, [
3086
3063
  alepha,
3087
3064
  input,
@@ -3106,10 +3083,10 @@ const createArrayItemInput = (parentInput, itemSchema, index, _itemKey, value, o
3106
3083
  path: `${parentInput.path}/${index}`,
3107
3084
  required: false,
3108
3085
  form: parentInput.form,
3086
+ initialValue: value,
3109
3087
  props: {
3110
3088
  id: `${parentInput.props.id}-${index}`,
3111
- name: `${parentInput.props.name}[${index}]`,
3112
- defaultValue: value
3089
+ name: `${parentInput.props.name}[${index}]`
3113
3090
  },
3114
3091
  set: onValueChange
3115
3092
  };
@@ -3124,10 +3101,10 @@ const createArrayItemFieldInput = (parentInput, itemSchema, fieldName, index, _i
3124
3101
  path: `${parentInput.path}/${index}/${fieldName}`,
3125
3102
  required: itemSchema.required?.includes(fieldName) ?? false,
3126
3103
  form: parentInput.form,
3104
+ initialValue: itemValue?.[fieldName],
3127
3105
  props: {
3128
3106
  id: `${parentInput.props.id}-${index}-${fieldName}`,
3129
- name: `${parentInput.props.name}[${index}].${fieldName}`,
3130
- defaultValue: itemValue?.[fieldName]
3107
+ name: `${parentInput.props.name}[${index}].${fieldName}`
3131
3108
  },
3132
3109
  set: (value) => onFieldChange(fieldName, value)
3133
3110
  };
@@ -3331,7 +3308,6 @@ const ControlArray = (props) => {
3331
3308
  })
3332
3309
  });
3333
3310
  };
3334
-
3335
3311
  //#endregion
3336
3312
  //#region ../../src/core/form/components/ControlDate.tsx
3337
3313
  /**
@@ -3345,7 +3321,9 @@ const ControlArray = (props) => {
3345
3321
  * Automatically detects date formats from schema and renders appropriate picker.
3346
3322
  */
3347
3323
  const ControlDate = (props) => {
3348
- const { inputProps, id, icon, format } = parseInput(props, useFormState(props.input));
3324
+ const form = useFormState(props.input);
3325
+ const [value, setValue] = useFieldValue(props.input);
3326
+ const { inputProps, id, icon, format } = parseInput(props, form);
3349
3327
  if (!props.input?.props) return null;
3350
3328
  if (props.datetime || format === "date-time") {
3351
3329
  const dateTimePickerProps = typeof props.datetime === "object" ? props.datetime : {};
@@ -3353,10 +3331,8 @@ const ControlDate = (props) => {
3353
3331
  ...inputProps,
3354
3332
  id,
3355
3333
  leftSection: icon,
3356
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
3357
- onChange: (value) => {
3358
- props.input.set(value ? new Date(value).toISOString() : void 0);
3359
- },
3334
+ value: value ? new Date(value) : null,
3335
+ onChange: (val) => setValue(val ? new Date(val).toISOString() : void 0),
3360
3336
  ...dateTimePickerProps
3361
3337
  });
3362
3338
  }
@@ -3366,10 +3342,8 @@ const ControlDate = (props) => {
3366
3342
  ...inputProps,
3367
3343
  id,
3368
3344
  leftSection: icon,
3369
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
3370
- onChange: (value) => {
3371
- props.input.set(value ? new Date(value).toISOString().slice(0, 10) : void 0);
3372
- },
3345
+ value: value ? new Date(value) : null,
3346
+ onChange: (val) => setValue(val ? new Date(val).toISOString().slice(0, 10) : void 0),
3373
3347
  ...dateInputProps
3374
3348
  });
3375
3349
  }
@@ -3379,30 +3353,23 @@ const ControlDate = (props) => {
3379
3353
  ...inputProps,
3380
3354
  id,
3381
3355
  leftSection: icon,
3382
- defaultValue: props.input.props.defaultValue,
3383
- onChange: (event) => {
3384
- props.input.set(event.currentTarget.value);
3385
- },
3356
+ value: value ?? "",
3357
+ onChange: (event) => setValue(event.currentTarget.value),
3386
3358
  ...timeInputProps
3387
3359
  });
3388
3360
  }
3389
3361
  return null;
3390
3362
  };
3391
-
3392
3363
  //#endregion
3393
3364
  //#region ../../src/core/form/components/ControlNumber.tsx
3394
3365
  /**
3395
3366
  *
3396
3367
  */
3397
3368
  const ControlNumber = (props) => {
3398
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
3399
- const ref = useRef(null);
3400
- const [value, setValue] = useState(props.input.props.defaultValue);
3401
- useEvents({ "form:reset": (event) => {
3402
- if (event.id === props.input?.form.id && ref.current) setValue(props.input.props.defaultValue);
3403
- } }, [props.input]);
3369
+ const form = useFormState(props.input);
3370
+ const [value, setValue] = useFieldValue(props.input);
3371
+ const { inputProps, id, icon } = parseInput(props, form);
3404
3372
  if (!props.input?.props) return null;
3405
- const { type, ...inputPropsWithoutType } = props.input.props;
3406
3373
  if (props.sliderProps) {
3407
3374
  const min = props.sliderProps.min ?? inputProps.minimum ?? 0;
3408
3375
  const max = props.sliderProps.max ?? inputProps.maximum ?? 100;
@@ -3415,38 +3382,28 @@ const ControlNumber = (props) => {
3415
3382
  },
3416
3383
  children: /* @__PURE__ */ jsx(Slider, {
3417
3384
  ...inputProps,
3418
- ref,
3419
3385
  id,
3420
- ...inputPropsWithoutType,
3421
3386
  ...props.sliderProps,
3422
- value,
3387
+ value: value ?? 0,
3423
3388
  min,
3424
3389
  max,
3425
3390
  label: () => value,
3426
- onChange: (val) => {
3427
- setValue(val);
3428
- props.input.set(val);
3429
- }
3391
+ onChange: (val) => setValue(val)
3430
3392
  })
3431
3393
  })
3432
3394
  });
3433
3395
  }
3434
3396
  return /* @__PURE__ */ jsx(NumberInput, {
3435
3397
  ...inputProps,
3436
- ref,
3437
3398
  id,
3438
3399
  leftSection: icon,
3439
- ...inputPropsWithoutType,
3440
3400
  ...props.numberInputProps,
3441
3401
  value: value ?? "",
3442
3402
  onChange: (val) => {
3443
- const newValue = val !== null ? Number(val) : void 0;
3444
- setValue(newValue);
3445
- props.input.set(newValue);
3403
+ setValue(val !== null ? Number(val) : void 0);
3446
3404
  }
3447
3405
  });
3448
3406
  };
3449
-
3450
3407
  //#endregion
3451
3408
  //#region ../../src/core/form/components/ControlObject.tsx
3452
3409
  /**
@@ -3523,94 +3480,10 @@ const ControlObject = (props) => {
3523
3480
  })
3524
3481
  });
3525
3482
  };
3526
-
3527
3483
  //#endregion
3528
- //#region ../../src/core/form/components/ControlQueryBuilder.tsx
3529
- /**
3530
- * Query builder with text input and help popover.
3531
- * Generates query strings for parseQueryString syntax.
3532
- */
3533
- const ControlQueryBuilder = ({ schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps }) => {
3534
- const [helpOpened, setHelpOpened] = useState(false);
3535
- const [textValue, setTextValue] = useState(value);
3536
- const inputRef = useRef(null);
3537
- const fields = schema ? extractSchemaFields(schema) : [];
3538
- const [error, setError] = useState(null);
3539
- const isValid = (value) => {
3540
- try {
3541
- parseQueryString(value.trim());
3542
- } catch (e) {
3543
- setError(e.message);
3544
- return false;
3545
- }
3546
- setError(null);
3547
- return true;
3548
- };
3549
- const handleTextChange = (newValue) => {
3550
- setTextValue(newValue);
3551
- if (isValid(newValue)) onChange?.(newValue);
3552
- };
3553
- const handleClear = () => {
3554
- setTextValue("");
3555
- onChange?.("");
3556
- isValid("");
3557
- };
3558
- const handleInsert = (text) => {
3559
- const newValue = textValue ? `${textValue}${text} ` : `${text} `;
3560
- setTextValue(newValue);
3561
- if (isValid(newValue)) onChange?.(newValue);
3562
- setTimeout(() => {
3563
- inputRef.current?.focus();
3564
- const length = inputRef.current?.value.length || 0;
3565
- inputRef.current?.setSelectionRange(length, length);
3566
- }, 0);
3567
- };
3568
- useEvents({ "form:change": (event) => {
3569
- if (event.id === inputRef.current?.form?.id) {
3570
- if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
3571
- }
3572
- } }, []);
3573
- return /* @__PURE__ */ jsxs(Popover, {
3574
- width: 800,
3575
- position: "bottom-start",
3576
- shadow: "md",
3577
- opened: helpOpened,
3578
- onChange: setHelpOpened,
3579
- closeOnClickOutside: true,
3580
- closeOnEscape: true,
3581
- transitionProps: {
3582
- transition: "fade-up",
3583
- duration: 200,
3584
- timingFunction: "ease"
3585
- },
3586
- children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
3587
- ref: inputRef,
3588
- placeholder,
3589
- value: textValue,
3590
- onChange: (e) => handleTextChange(e.currentTarget.value),
3591
- onFocus: () => setHelpOpened(true),
3592
- leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
3593
- rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
3594
- size: "sm",
3595
- variant: "subtle",
3596
- color: "gray",
3597
- onClick: handleClear,
3598
- children: /* @__PURE__ */ jsx(IconX, { size: 14 })
3599
- }),
3600
- ...textInputProps
3601
- }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
3602
- bg: "transparent",
3603
- p: "xs",
3604
- bd: `1px solid ${ui.colors.border}`,
3605
- style: { backdropFilter: "blur(20px)" },
3606
- children: /* @__PURE__ */ jsx(QueryHelp, {
3607
- fields,
3608
- onInsert: handleInsert
3609
- })
3610
- })]
3611
- });
3612
- };
3613
- function QueryHelp({ fields, onInsert }) {
3484
+ //#region ../../src/core/form/components/ControlQueryBuilderHelp.tsx
3485
+ const ControlQueryBuilderHelp = (props) => {
3486
+ const { fields, onInsert } = props;
3614
3487
  return /* @__PURE__ */ jsxs(Flex$1, {
3615
3488
  gap: "md",
3616
3489
  align: "flex-start",
@@ -3771,114 +3644,314 @@ function QueryHelp({ fields, onInsert }) {
3771
3644
  }, field.path))
3772
3645
  })]
3773
3646
  })
3774
- ]
3647
+ ]
3648
+ });
3649
+ };
3650
+ //#endregion
3651
+ //#region ../../src/core/form/components/ControlQueryBuilder.tsx
3652
+ /**
3653
+ * Query builder with text input and help popover.
3654
+ * Generates query strings for parseQueryString syntax.
3655
+ */
3656
+ const ControlQueryBuilder = (props) => {
3657
+ const { schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps } = props;
3658
+ const [helpOpened, setHelpOpened] = useState(false);
3659
+ const [textValue, setTextValue] = useState(value);
3660
+ const inputRef = useRef(null);
3661
+ const fields = schema ? extractSchemaFields(schema) : [];
3662
+ const [error, setError] = useState(null);
3663
+ const isValid = (value) => {
3664
+ try {
3665
+ parseQueryString(value.trim());
3666
+ } catch (e) {
3667
+ setError(e.message);
3668
+ return false;
3669
+ }
3670
+ setError(null);
3671
+ return true;
3672
+ };
3673
+ const handleTextChange = (newValue) => {
3674
+ setTextValue(newValue);
3675
+ if (isValid(newValue)) onChange?.(newValue);
3676
+ };
3677
+ const handleClear = () => {
3678
+ setTextValue("");
3679
+ onChange?.("");
3680
+ isValid("");
3681
+ };
3682
+ const handleInsert = (text) => {
3683
+ const newValue = textValue ? `${textValue}${text} ` : `${text} `;
3684
+ setTextValue(newValue);
3685
+ if (isValid(newValue)) onChange?.(newValue);
3686
+ setTimeout(() => {
3687
+ inputRef.current?.focus();
3688
+ const length = inputRef.current?.value.length || 0;
3689
+ inputRef.current?.setSelectionRange(length, length);
3690
+ }, 0);
3691
+ };
3692
+ useEvents({ "form:change": (event) => {
3693
+ if (event.id === inputRef.current?.form?.id) {
3694
+ if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
3695
+ }
3696
+ } }, []);
3697
+ return /* @__PURE__ */ jsxs(Popover, {
3698
+ width: 800,
3699
+ position: "bottom-start",
3700
+ shadow: "md",
3701
+ opened: helpOpened,
3702
+ onChange: setHelpOpened,
3703
+ closeOnClickOutside: true,
3704
+ closeOnEscape: true,
3705
+ transitionProps: {
3706
+ transition: "fade-up",
3707
+ duration: 200,
3708
+ timingFunction: "ease"
3709
+ },
3710
+ children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
3711
+ ref: inputRef,
3712
+ placeholder,
3713
+ value: textValue,
3714
+ onChange: (e) => handleTextChange(e.currentTarget.value),
3715
+ onFocus: () => setHelpOpened(true),
3716
+ leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
3717
+ rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
3718
+ size: "sm",
3719
+ variant: "subtle",
3720
+ color: "gray",
3721
+ onClick: handleClear,
3722
+ children: /* @__PURE__ */ jsx(IconX, { size: 14 })
3723
+ }),
3724
+ ...textInputProps
3725
+ }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
3726
+ bg: "transparent",
3727
+ p: "xs",
3728
+ bd: `1px solid ${ui.colors.border}`,
3729
+ style: { backdropFilter: "blur(20px)" },
3730
+ children: /* @__PURE__ */ jsx(ControlQueryBuilderHelp, {
3731
+ fields,
3732
+ onInsert: handleInsert
3733
+ })
3734
+ })]
3775
3735
  });
3776
- }
3777
-
3736
+ };
3778
3737
  //#endregion
3779
3738
  //#region ../../src/core/form/components/ControlSelect.tsx
3780
3739
  /**
3781
- * ControlSelect component for handling Select, MultiSelect, and TagsInput.
3740
+ * ControlSelect component for handling Select, MultiSelect, Autocomplete, and TagsInput.
3782
3741
  *
3783
3742
  * Features:
3784
3743
  * - Basic Select with enum support
3785
3744
  * - MultiSelect for array of enums
3786
- * - TagsInput for array of strings (no enum)
3787
- * - Future: Lazy loading
3788
- * - Future: Searchable/filterable options
3789
- * - Future: Custom option rendering
3745
+ * - Autocomplete for creatable single values
3746
+ * - TagsInput for creatable array values
3747
+ * - Async lazy loading with auto short/long mode detection
3748
+ * - Short mode: client-side filtering with cached data
3749
+ * - Long mode: debounced server search
3790
3750
  *
3791
3751
  * Automatically detects enum values and array types from schema.
3792
3752
  */
3793
3753
  const ControlSelect = (props) => {
3794
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
3754
+ const form = useFormState(props.input);
3755
+ const [value, setValue] = useFieldValue(props.input);
3756
+ const { inputProps, id, icon } = parseInput(props, form);
3795
3757
  const isArray = props.input.schema && "type" in props.input.schema && props.input.schema.type === "array";
3796
- let itemsEnum;
3797
- if (isArray && "items" in props.input.schema && props.input.schema.items) {
3798
- const items = props.input.schema.items;
3799
- if ("enum" in items && Array.isArray(items.enum)) itemsEnum = items.enum;
3800
- }
3758
+ const isNumeric = props.input.schema && "type" in props.input.schema && (props.input.schema.type === "integer" || props.input.schema.type === "number");
3759
+ const isBoolean = props.input.schema && "type" in props.input.schema && props.input.schema.type === "boolean";
3801
3760
  const enumValues = props.input.schema && "enum" in props.input.schema && Array.isArray(props.input.schema.enum) ? props.input.schema.enum : [];
3802
- const [data, setData] = useState([]);
3761
+ const { data: asyncData, loading, mode, search } = useAsyncLoader(props.loader, props.loaderThreshold ?? 100, props.loaderDebounce ?? 300, props.input.initialValue);
3762
+ const [staticData, setStaticData] = useState([]);
3763
+ const enumKey = JSON.stringify(enumValues);
3803
3764
  useEffect(() => {
3804
- if (!props.input?.props) return;
3805
- if (props.loader) props.loader().then(setData);
3806
- else setData(enumValues);
3807
- }, [props.input, props.loader]);
3765
+ if (!props.input?.props || props.loader) return;
3766
+ if (isBoolean && enumValues.length === 0) setStaticData([{
3767
+ value: "true",
3768
+ label: "True"
3769
+ }, {
3770
+ value: "false",
3771
+ label: "False"
3772
+ }]);
3773
+ else setStaticData(enumValues);
3774
+ }, [
3775
+ props.input,
3776
+ props.loader,
3777
+ enumKey,
3778
+ isBoolean
3779
+ ]);
3780
+ const data = props.loader ? asyncData : staticData;
3808
3781
  if (!props.input?.props) return null;
3809
- if (props.segmented) {
3810
- const segmentedControlProps = typeof props.segmented === "object" ? props.segmented : {};
3782
+ /**
3783
+ * Coerce value for numeric schemas Select values are always strings.
3784
+ */
3785
+ const coerceValue = (val) => {
3786
+ if (val == null) return val;
3787
+ if (isNumeric) return Number(val);
3788
+ if (isBoolean) return val === "true";
3789
+ return val;
3790
+ };
3791
+ if (props.segmentedProps) {
3792
+ const segmentedControlProps = typeof props.segmentedProps === "object" ? props.segmentedProps : {};
3793
+ const segmentedData = segmentedControlProps.data ?? data.slice(0, 10);
3811
3794
  return /* @__PURE__ */ jsx(Input.Wrapper, {
3812
3795
  ...inputProps,
3813
- children: /* @__PURE__ */ jsx(Flex$1, { children: /* @__PURE__ */ jsx(SegmentedControl, {
3814
- disabled: inputProps.disabled,
3815
- defaultValue: String(props.input.props.defaultValue),
3816
- ...segmentedControlProps,
3817
- onChange: (value) => {
3818
- props.input.set(value);
3819
- },
3820
- data: data.slice(0, 10)
3821
- }) })
3796
+ children: /* @__PURE__ */ jsx(Flex$1, {
3797
+ my: "calc(var(--mantine-spacing-xs) / 2)",
3798
+ children: /* @__PURE__ */ jsx(SegmentedControl, {
3799
+ disabled: inputProps.disabled,
3800
+ value: value != null ? String(value) : "",
3801
+ ...segmentedControlProps,
3802
+ onChange: (val) => {
3803
+ setValue(coerceValue(val));
3804
+ },
3805
+ data: segmentedData
3806
+ })
3807
+ })
3822
3808
  });
3823
3809
  }
3824
- if (props.autocomplete) {
3825
- const autocompleteProps = typeof props.autocomplete === "object" ? props.autocomplete : {};
3826
- return /* @__PURE__ */ jsx(Autocomplete, {
3810
+ const sharedProps = {
3811
+ size: props.size,
3812
+ id,
3813
+ leftSection: loading ? /* @__PURE__ */ jsx(Loader, {
3814
+ color: "gray",
3815
+ size: 10
3816
+ }) : icon,
3817
+ data
3818
+ };
3819
+ const selectableProps = {
3820
+ ...sharedProps,
3821
+ searchable: true,
3822
+ rightSection: /* @__PURE__ */ jsx("span", {})
3823
+ };
3824
+ const longModeProps = mode === "long" ? {
3825
+ filter: ({ options }) => options,
3826
+ onSearchChange: search.run
3827
+ } : {};
3828
+ if (props.creatable && (isArray || props.tagsInputProps)) {
3829
+ const tagsInputExtraProps = props.tagsInputProps ?? {};
3830
+ return /* @__PURE__ */ jsx(TagsInput, {
3827
3831
  ...inputProps,
3828
- size: props.size,
3829
- id,
3830
- leftSection: icon,
3831
- data,
3832
- ...props.input.props,
3833
- ...autocompleteProps
3832
+ ...sharedProps,
3833
+ ...longModeProps,
3834
+ value: Array.isArray(value) ? value : [],
3835
+ onChange: (val) => {
3836
+ setValue(val);
3837
+ },
3838
+ ...tagsInputExtraProps
3834
3839
  });
3835
3840
  }
3836
- if (isArray && !itemsEnum || props.tags) {
3837
- const tagsInputProps = typeof props.tags === "object" ? props.tags : {};
3838
- return /* @__PURE__ */ jsx(TagsInput, {
3841
+ if (props.creatable) {
3842
+ const autocompleteExtraProps = props.autocompleteProps ?? {};
3843
+ return /* @__PURE__ */ jsx(Autocomplete, {
3839
3844
  ...inputProps,
3840
- size: props.size,
3841
- id,
3842
- leftSection: icon,
3843
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
3844
- onChange: (value) => {
3845
- props.input.set(value);
3845
+ ...sharedProps,
3846
+ ...longModeProps,
3847
+ value: value != null ? String(value) : "",
3848
+ onChange: (val) => {
3849
+ setValue(coerceValue(val));
3846
3850
  },
3847
- ...tagsInputProps
3851
+ ...autocompleteExtraProps
3848
3852
  });
3849
3853
  }
3850
- if (isArray && itemsEnum || props.multi) {
3851
- const data = itemsEnum?.map((value) => ({
3852
- value,
3853
- label: value
3854
- })) || [];
3855
- const multiSelectProps = typeof props.multi === "object" ? props.multi : {};
3854
+ if (isArray || props.multiSelectProps) {
3855
+ const multiSelectExtraProps = typeof props.multiSelectProps === "object" ? props.multiSelectProps : {};
3856
3856
  return /* @__PURE__ */ jsx(MultiSelect, {
3857
3857
  ...inputProps,
3858
- size: props.size,
3859
- id,
3860
- leftSection: icon,
3861
- data,
3862
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
3863
- onChange: (value) => {
3864
- props.input.set(value);
3858
+ ...selectableProps,
3859
+ ...longModeProps,
3860
+ value: Array.isArray(value) ? value : [],
3861
+ onChange: (val) => {
3862
+ setValue(val);
3865
3863
  },
3866
- ...multiSelectProps
3864
+ ...multiSelectExtraProps
3867
3865
  });
3868
3866
  }
3869
- const selectProps = typeof props.select === "object" ? props.select : {};
3867
+ const selectExtraProps = typeof props.selectProps === "object" ? props.selectProps : {};
3868
+ if (mode === "static") return /* @__PURE__ */ jsx(Select, {
3869
+ ...inputProps,
3870
+ ...selectableProps,
3871
+ value: value != null ? String(value) : null,
3872
+ onChange: (val) => {
3873
+ setValue(coerceValue(val));
3874
+ },
3875
+ ...selectExtraProps
3876
+ });
3870
3877
  return /* @__PURE__ */ jsx(Select, {
3871
3878
  ...inputProps,
3872
- size: props.size,
3873
- id,
3874
- leftSection: icon,
3875
- rightSection: null,
3876
- data,
3877
- ...props.input.props,
3878
- ...selectProps
3879
+ ...selectableProps,
3880
+ ...longModeProps,
3881
+ value: value != null ? String(value) : null,
3882
+ onChange: (val) => {
3883
+ setValue(coerceValue(val));
3884
+ },
3885
+ ...selectExtraProps
3879
3886
  });
3880
3887
  };
3881
-
3888
+ /**
3889
+ * Hook for async select data loading with auto short/long mode detection.
3890
+ */
3891
+ const useAsyncLoader = (loader, threshold, debounceMs, defaultValue) => {
3892
+ const [data, setData] = useState([]);
3893
+ const [loading, setLoading] = useState(false);
3894
+ const [mode, setMode] = useState("static");
3895
+ const cache = useRef(/* @__PURE__ */ new Map());
3896
+ useAction({
3897
+ name: "select:loader:init",
3898
+ runOnInit: true,
3899
+ handler: async () => {
3900
+ if (!loader) {
3901
+ setMode("static");
3902
+ return;
3903
+ }
3904
+ setLoading(true);
3905
+ try {
3906
+ const result = await loader("");
3907
+ const isShort = result.length <= threshold;
3908
+ setMode(isShort ? "short" : "long");
3909
+ cache.current.set("", result);
3910
+ setData(result);
3911
+ if (!isShort && defaultValue != null && String(defaultValue) !== "") {
3912
+ const resolved = await loader("", [String(defaultValue)]);
3913
+ if (resolved.length > 0) setData((prev) => {
3914
+ const existing = new Set(prev.map((d) => typeof d === "string" ? d : d.value));
3915
+ const newItems = resolved.filter((r) => {
3916
+ const val = typeof r === "string" ? r : r.value;
3917
+ return !existing.has(val);
3918
+ });
3919
+ return [...prev, ...newItems];
3920
+ });
3921
+ }
3922
+ } finally {
3923
+ setLoading(false);
3924
+ }
3925
+ }
3926
+ }, [loader, threshold]);
3927
+ return {
3928
+ data,
3929
+ loading,
3930
+ mode,
3931
+ search: useAction({
3932
+ debounce: debounceMs,
3933
+ handler: async (text) => {
3934
+ if (!loader || mode !== "long") return;
3935
+ if (cache.current.has(text)) {
3936
+ setData(cache.current.get(text));
3937
+ return;
3938
+ }
3939
+ setLoading(true);
3940
+ try {
3941
+ const result = await loader(text);
3942
+ cache.current.set(text, result);
3943
+ setData(result);
3944
+ } finally {
3945
+ setLoading(false);
3946
+ }
3947
+ }
3948
+ }, [
3949
+ loader,
3950
+ mode,
3951
+ debounceMs
3952
+ ])
3953
+ };
3954
+ };
3882
3955
  //#endregion
3883
3956
  //#region ../../src/core/form/components/Control.tsx
3884
3957
  /**
@@ -3907,6 +3980,7 @@ const ControlSelect = (props) => {
3907
3980
  */
3908
3981
  const Control = (_props) => {
3909
3982
  const form = useFormState(_props.input, ["error"]);
3983
+ const [value, setValue] = useFieldValue(_props.input);
3910
3984
  if (!_props.input?.props) return null;
3911
3985
  const { inputProps, id, icon, format, schema } = parseInput(_props, form);
3912
3986
  const props = {
@@ -3914,12 +3988,11 @@ const Control = (_props) => {
3914
3988
  ...schema.$control
3915
3989
  };
3916
3990
  if (props.query) return /* @__PURE__ */ jsx(ControlQueryBuilder, {
3917
- ...props.input.props,
3918
3991
  ...inputProps,
3919
3992
  schema: props.query,
3920
- value: props.input.props.value,
3921
- onChange: (value) => {
3922
- props.input.set(value);
3993
+ value,
3994
+ onChange: (val) => {
3995
+ setValue(val);
3923
3996
  }
3924
3997
  });
3925
3998
  if (props.custom) {
@@ -3930,9 +4003,9 @@ const Control = (_props) => {
3930
4003
  flex: 1,
3931
4004
  mt: "calc(var(--mantine-spacing-xs) / 2)",
3932
4005
  children: /* @__PURE__ */ jsx(Custom, {
3933
- defaultValue: props.input.props.defaultValue,
3934
- onChange: (value) => {
3935
- props.input.set(value);
4006
+ value,
4007
+ onChange: (val) => {
4008
+ setValue(val);
3936
4009
  }
3937
4010
  })
3938
4011
  })
@@ -3943,7 +4016,7 @@ const Control = (_props) => {
3943
4016
  const controlObjectProps = typeof props.object === "object" ? props.object : {};
3944
4017
  return /* @__PURE__ */ jsx(ControlObject, {
3945
4018
  input: props.input,
3946
- title: props.title,
4019
+ label: props.label,
3947
4020
  description: props.description,
3948
4021
  ...controlObjectProps
3949
4022
  });
@@ -3954,18 +4027,18 @@ const Control = (_props) => {
3954
4027
  const controlArrayProps = typeof props.array === "object" ? props.array : {};
3955
4028
  return /* @__PURE__ */ jsx(ControlArray, {
3956
4029
  input: props.input,
3957
- title: props.title,
4030
+ label: props.label,
3958
4031
  description: props.description,
3959
4032
  ...controlArrayProps
3960
4033
  });
3961
4034
  }
3962
- if (props.number || props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
4035
+ if (props.number || !props.select && props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
3963
4036
  const controlNumberProps = typeof props.number === "object" ? props.number : {};
3964
4037
  if (props.slider) controlNumberProps.sliderProps ??= {};
3965
4038
  return /* @__PURE__ */ jsx(ControlNumber, {
3966
4039
  size: props.size,
3967
4040
  input: props.input,
3968
- title: props.title,
4041
+ label: props.label,
3969
4042
  description: props.description,
3970
4043
  icon,
3971
4044
  ...controlNumberProps
@@ -3978,9 +4051,7 @@ const Control = (_props) => {
3978
4051
  size: props.size,
3979
4052
  id,
3980
4053
  leftSection: icon,
3981
- onChange: (file) => {
3982
- props.input.set(file);
3983
- },
4054
+ onChange: (file) => setValue(file),
3984
4055
  ...fileInputProps
3985
4056
  });
3986
4057
  }
@@ -3991,17 +4062,18 @@ const Control = (_props) => {
3991
4062
  size: props.size,
3992
4063
  id,
3993
4064
  leftSection: icon,
3994
- ...props.input.props,
4065
+ value: value ?? "",
4066
+ onChange: (val) => setValue(val),
3995
4067
  ...colorInputProps
3996
4068
  });
3997
4069
  }
3998
4070
  if (props.input.schema && "enum" in props.input.schema && props.input.schema.enum || isArray && !isArrayOfObjects || props.select) {
3999
4071
  const opts = typeof props.select === "object" ? props.select : {};
4000
- if (props.segmented) opts.segmented ??= {};
4072
+ if (props.segmented) opts.segmentedProps ??= {};
4001
4073
  return /* @__PURE__ */ jsx(ControlSelect, {
4002
4074
  size: props.size,
4003
4075
  input: props.input,
4004
- title: props.title,
4076
+ label: props.label,
4005
4077
  description: props.description,
4006
4078
  icon,
4007
4079
  ...opts
@@ -4015,16 +4087,16 @@ const Control = (_props) => {
4015
4087
  size: props.size,
4016
4088
  id,
4017
4089
  color: "blue",
4018
- defaultChecked: props.input.props.defaultValue,
4090
+ checked: Boolean(value),
4019
4091
  onChange: (event) => {
4020
- props.input.set(event.currentTarget.checked);
4092
+ setValue(event.currentTarget.checked);
4021
4093
  },
4022
4094
  ...switchProps
4023
4095
  });
4024
4096
  }
4025
4097
  const opts = {
4026
4098
  input: props.input,
4027
- select: { data: [{
4099
+ selectProps: { data: [{
4028
4100
  value: "true",
4029
4101
  label: "Yes"
4030
4102
  }, {
@@ -4034,7 +4106,7 @@ const Control = (_props) => {
4034
4106
  };
4035
4107
  return /* @__PURE__ */ jsx(ControlSelect, {
4036
4108
  size: props.size,
4037
- title: props.title,
4109
+ label: props.label,
4038
4110
  description: props.description,
4039
4111
  icon,
4040
4112
  ...opts
@@ -4047,7 +4119,8 @@ const Control = (_props) => {
4047
4119
  size: props.size,
4048
4120
  id,
4049
4121
  leftSection: icon,
4050
- ...props.input.props,
4122
+ value: value ?? "",
4123
+ onChange: (ev) => setValue(ev.target.value),
4051
4124
  ...passwordInputProps
4052
4125
  });
4053
4126
  }
@@ -4058,14 +4131,15 @@ const Control = (_props) => {
4058
4131
  size: props.size,
4059
4132
  id,
4060
4133
  leftSection: icon,
4061
- ...props.input.props,
4134
+ value: value ?? "",
4135
+ onChange: (ev) => setValue(ev.target.value),
4062
4136
  ...textAreaProps
4063
4137
  });
4064
4138
  }
4065
4139
  if (props.date || props.datetime || props.time || format === "date" || format === "date-time" || format === "time") return /* @__PURE__ */ jsx(ControlDate, {
4066
4140
  size: props.size,
4067
4141
  input: props.input,
4068
- title: props.title,
4142
+ label: props.label,
4069
4143
  description: props.description,
4070
4144
  icon,
4071
4145
  date: props.date,
@@ -4080,7 +4154,7 @@ const Control = (_props) => {
4080
4154
  case "uri": return "url";
4081
4155
  case "tel":
4082
4156
  case "phone": return "tel";
4083
- default: return;
4157
+ default: return props.input.props.type ?? "text";
4084
4158
  }
4085
4159
  };
4086
4160
  return /* @__PURE__ */ jsx(TextInput, {
@@ -4089,17 +4163,11 @@ const Control = (_props) => {
4089
4163
  id,
4090
4164
  leftSection: icon,
4091
4165
  type: getInputType(),
4092
- ...props.input.props,
4093
- ...textInputProps,
4094
- inputWrapperOrder: [
4095
- "label",
4096
- "input",
4097
- "description",
4098
- "error"
4099
- ]
4166
+ value: value ?? "",
4167
+ onChange: (ev) => setValue(ev.target.value),
4168
+ ...textInputProps
4100
4169
  });
4101
4170
  };
4102
-
4103
4171
  //#endregion
4104
4172
  //#region ../../src/core/form/components/TypeForm.tsx
4105
4173
  /**
@@ -4145,6 +4213,7 @@ const Control = (_props) => {
4145
4213
  */
4146
4214
  const TypeForm = (props) => {
4147
4215
  const { form, columns = 3, children, controlProps, fieldControlProps, skipFormElement = false, skipSubmitButton = false, submitButtonProps, fill = true, size } = props;
4216
+ const { dirty } = useFormState(form, ["dirty"]);
4148
4217
  const schema = props.schema || form.options.schema;
4149
4218
  if (!schema?.properties) return null;
4150
4219
  const supportedFields = Object.keys(schema.properties);
@@ -4207,10 +4276,12 @@ const TypeForm = (props) => {
4207
4276
  children: [/* @__PURE__ */ jsx(ActionButton, {
4208
4277
  variant: "subtle",
4209
4278
  type: "reset",
4279
+ disabled: !dirty,
4210
4280
  children: "Reset"
4211
4281
  }), /* @__PURE__ */ jsx(ActionButton, {
4212
4282
  intent: "primary",
4213
4283
  form,
4284
+ disabled: !dirty,
4214
4285
  ...submitButtonProps,
4215
4286
  children: submitButtonProps?.children ?? "Submit"
4216
4287
  })]
@@ -4228,7 +4299,6 @@ const TypeForm = (props) => {
4228
4299
  children: content
4229
4300
  });
4230
4301
  };
4231
-
4232
4302
  //#endregion
4233
4303
  //#region ../../src/core/form/factories/dialogForm.tsx
4234
4304
  /**
@@ -4247,18 +4317,27 @@ const dialogForm = (form, options) => ({
4247
4317
  ...options?.typeFormProps
4248
4318
  })
4249
4319
  });
4250
-
4251
4320
  //#endregion
4252
- //#region ../../src/core/helpers/renderIcon.tsx
4253
- const renderIcon = (icon, size) => {
4254
- if (!icon) return null;
4255
- if (isValidElement(icon)) return icon;
4256
- if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
4257
- return icon;
4321
+ //#region ../../src/core/json/components/JsonViewerCopyButton.tsx
4322
+ const JsonViewerCopyButton = (props) => {
4323
+ const [copied, setCopied] = useState(false);
4324
+ const handleCopy = useCallback((e) => {
4325
+ e.stopPropagation();
4326
+ navigator.clipboard.writeText(props.value);
4327
+ setCopied(true);
4328
+ setTimeout(() => setCopied(false), 1500);
4329
+ }, [props.value]);
4330
+ return /* @__PURE__ */ jsx(ActionIcon, {
4331
+ size: props.iconSize + 4,
4332
+ variant: "transparent",
4333
+ c: copied ? "green" : "dimmed",
4334
+ onClick: handleCopy,
4335
+ className: "alepha-json-viewer-copy",
4336
+ children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: props.iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: props.iconSize })
4337
+ });
4258
4338
  };
4259
-
4260
4339
  //#endregion
4261
- //#region ../../src/core/json/components/JsonViewer.tsx
4340
+ //#region ../../src/core/json/components/JsonViewerShared.ts
4262
4341
  const SIZE_CONFIG = {
4263
4342
  xs: {
4264
4343
  icon: 14,
@@ -4307,77 +4386,20 @@ const getValueType = (val) => {
4307
4386
  if (Array.isArray(val)) return "array";
4308
4387
  return typeof val;
4309
4388
  };
4310
- function buildTreeNodes(data, path = [], key, isArrayItem = false, maxDepth = 10) {
4311
- const currentPath = key !== void 0 ? [...path, key] : path;
4312
- const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
4313
- if (currentPath.length > maxDepth) return {
4314
- value: nodeId,
4315
- label: key ?? "",
4316
- nodeValue: data,
4317
- nodeKey: key,
4318
- path: currentPath,
4319
- isArrayItem
4320
- };
4321
- const type = getValueType(data);
4322
- if (type === "object" || type === "array") {
4323
- const children = (type === "array" ? data.map((v, i) => [String(i), v]) : Object.entries(data)).map(([k, v]) => buildTreeNodes(v, currentPath, k, type === "array", maxDepth)).filter((n) => n !== null);
4324
- return {
4325
- value: nodeId,
4326
- label: key ?? "",
4327
- nodeValue: data,
4328
- nodeKey: key,
4329
- path: currentPath,
4330
- isArrayItem,
4331
- children: children.length > 0 ? children : void 0
4332
- };
4333
- }
4334
- return {
4335
- value: nodeId,
4336
- label: key ?? "",
4337
- nodeValue: data,
4338
- nodeKey: key,
4339
- path: currentPath,
4340
- isArrayItem
4341
- };
4342
- }
4343
- function getExpandedIds(nodes, targetDepth, currentDepth = 0) {
4344
- if (currentDepth >= targetDepth) return [];
4345
- const ids = [];
4346
- for (const node of nodes) if (node.children) {
4347
- ids.push(node.value);
4348
- ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
4349
- }
4350
- return ids;
4351
- }
4352
- const CopyButton$1 = ({ value, iconSize }) => {
4353
- const [copied, setCopied] = useState(false);
4354
- const handleCopy = useCallback((e) => {
4355
- e.stopPropagation();
4356
- navigator.clipboard.writeText(value);
4357
- setCopied(true);
4358
- setTimeout(() => setCopied(false), 1500);
4359
- }, [value]);
4360
- return /* @__PURE__ */ jsx(ActionIcon, {
4361
- size: iconSize + 4,
4362
- variant: "transparent",
4363
- c: copied ? "green" : "dimmed",
4364
- onClick: handleCopy,
4365
- className: "alepha-json-viewer-copy",
4366
- children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: iconSize })
4367
- });
4368
- };
4369
- const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, showQuotes, showCopyButton, renderValue }) => {
4370
- const { nodeValue, nodeKey, path, isArrayItem, isRoot } = node;
4389
+ //#endregion
4390
+ //#region ../../src/core/json/components/JsonViewerRowNode.tsx
4391
+ const JsonViewerRowNode = (props) => {
4392
+ const { nodeValue, nodeKey, path, isArrayItem } = props.node;
4371
4393
  const type = getValueType(nodeValue);
4372
4394
  const isExpandable = type === "object" || type === "array";
4373
4395
  const getPreview = () => {
4374
4396
  if (!isExpandable) return null;
4375
4397
  const count = (type === "array" ? nodeValue : Object.keys(nodeValue)).length;
4376
4398
  const label = type === "array" ? "item" : "key";
4377
- if (!expanded) return /* @__PURE__ */ jsx(Text$1, {
4399
+ if (!props.expanded) return /* @__PURE__ */ jsx(Text$1, {
4378
4400
  fs: "italic",
4379
4401
  component: "span",
4380
- size,
4402
+ size: props.size,
4381
4403
  style: STYLES.preview,
4382
4404
  children: count === 0 ? type === "array" ? "[]" : "{}" : type === "array" ? `[ ${count} ${count === 1 ? label : `${label}s`} ]` : `{ ${count} ${count === 1 ? label : `${label}s`} }`
4383
4405
  });
@@ -4387,25 +4409,25 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4387
4409
  return /* @__PURE__ */ jsxs(Flex$1, {
4388
4410
  gap: 6,
4389
4411
  wrap: "nowrap",
4390
- ...elementProps,
4391
- className: `alepha-json-viewer-row ${elementProps.className || ""}`,
4412
+ ...props.elementProps,
4413
+ className: `alepha-json-viewer-row ${props.elementProps.className || ""}`,
4392
4414
  children: [
4393
- hasChildren ? expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
4394
- size: config.icon,
4415
+ props.hasChildren ? props.expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
4416
+ size: props.config.icon,
4395
4417
  style: STYLES.chevron
4396
4418
  }) : /* @__PURE__ */ jsx(IconChevronRight, {
4397
- size: config.icon,
4419
+ size: props.config.icon,
4398
4420
  style: STYLES.chevron
4399
4421
  }) : /* @__PURE__ */ jsx("span", { style: {
4400
- width: config.icon,
4422
+ width: props.config.icon,
4401
4423
  flexShrink: 0
4402
4424
  } }),
4403
4425
  nodeKey !== void 0 && !isArrayItem && /* @__PURE__ */ jsxs(Text$1, {
4404
4426
  component: "span",
4405
- size,
4427
+ size: props.size,
4406
4428
  children: [/* @__PURE__ */ jsx("span", {
4407
4429
  style: STYLES.key,
4408
- children: showQuotes ? `"${nodeKey}"` : nodeKey
4430
+ children: props.showQuotes ? `"${nodeKey}"` : nodeKey
4409
4431
  }), /* @__PURE__ */ jsx("span", {
4410
4432
  style: STYLES.colon,
4411
4433
  children: ":"
@@ -4413,7 +4435,7 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4413
4435
  }),
4414
4436
  nodeKey !== void 0 && isArrayItem && /* @__PURE__ */ jsxs(Text$1, {
4415
4437
  component: "span",
4416
- size,
4438
+ size: props.size,
4417
4439
  children: [/* @__PURE__ */ jsx("span", {
4418
4440
  style: STYLES.key,
4419
4441
  children: nodeKey
@@ -4422,25 +4444,28 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4422
4444
  children: ":"
4423
4445
  })]
4424
4446
  }),
4425
- hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text$1, {
4447
+ props.hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text$1, {
4426
4448
  component: "span",
4427
- size,
4449
+ size: props.size,
4428
4450
  style: STYLES.preview,
4429
4451
  children: "[]"
4430
4452
  }) : /* @__PURE__ */ jsx(Text$1, {
4431
4453
  component: "span",
4432
- size,
4454
+ size: props.size,
4433
4455
  style: STYLES.preview,
4434
4456
  children: "{}"
4435
- }) : renderValue(nodeValue, nodeKey, path),
4436
- showCopyButton && /* @__PURE__ */ jsx(CopyButton$1, {
4457
+ }) : props.renderValue(nodeValue, nodeKey, path),
4458
+ props.showCopyButton && /* @__PURE__ */ jsx(JsonViewerCopyButton, {
4437
4459
  value: getCopyValue(),
4438
- iconSize: config.icon
4460
+ iconSize: props.config.icon
4439
4461
  })
4440
4462
  ]
4441
4463
  });
4442
4464
  };
4443
- const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue }) => {
4465
+ //#endregion
4466
+ //#region ../../src/core/json/components/JsonViewer.tsx
4467
+ const JsonViewer = (props) => {
4468
+ const { data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue } = props;
4444
4469
  const config = SIZE_CONFIG[size] || SIZE_CONFIG.sm;
4445
4470
  const treeData = useMemo(() => {
4446
4471
  const type = getValueType(data);
@@ -4520,7 +4545,7 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
4520
4545
  size
4521
4546
  ]);
4522
4547
  const renderNode = useCallback(({ node, expanded, hasChildren, elementProps }) => {
4523
- return /* @__PURE__ */ jsx(RowNode, {
4548
+ return /* @__PURE__ */ jsx(JsonViewerRowNode, {
4524
4549
  node,
4525
4550
  expanded,
4526
4551
  hasChildren,
@@ -4552,7 +4577,54 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
4552
4577
  styles: { root: STYLES.root }
4553
4578
  });
4554
4579
  };
4555
-
4580
+ /**
4581
+ * Convert JSON to tree data structure.
4582
+ */
4583
+ const buildTreeNodes = (data, path = [], key, isArrayItem = false, maxDepth = 10) => {
4584
+ const currentPath = key !== void 0 ? [...path, key] : path;
4585
+ const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
4586
+ if (currentPath.length > maxDepth) return {
4587
+ value: nodeId,
4588
+ label: key ?? "",
4589
+ nodeValue: data,
4590
+ nodeKey: key,
4591
+ path: currentPath,
4592
+ isArrayItem
4593
+ };
4594
+ const type = getValueType(data);
4595
+ if (type === "object" || type === "array") {
4596
+ const children = (type === "array" ? data.map((v, i) => [String(i), v]) : Object.entries(data)).map(([k, v]) => buildTreeNodes(v, currentPath, k, type === "array", maxDepth)).filter((n) => n !== null);
4597
+ return {
4598
+ value: nodeId,
4599
+ label: key ?? "",
4600
+ nodeValue: data,
4601
+ nodeKey: key,
4602
+ path: currentPath,
4603
+ isArrayItem,
4604
+ children: children.length > 0 ? children : void 0
4605
+ };
4606
+ }
4607
+ return {
4608
+ value: nodeId,
4609
+ label: key ?? "",
4610
+ nodeValue: data,
4611
+ nodeKey: key,
4612
+ path: currentPath,
4613
+ isArrayItem
4614
+ };
4615
+ };
4616
+ /**
4617
+ * Get all expandable node IDs up to a certain depth.
4618
+ */
4619
+ const getExpandedIds = (nodes, targetDepth, currentDepth = 0) => {
4620
+ if (currentDepth >= targetDepth) return [];
4621
+ const ids = [];
4622
+ for (const node of nodes) if (node.children) {
4623
+ ids.push(node.value);
4624
+ ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
4625
+ }
4626
+ return ids;
4627
+ };
4556
4628
  //#endregion
4557
4629
  //#region ../../src/core/json/factories/dialogJson.tsx
4558
4630
  /**
@@ -4577,7 +4649,6 @@ const dialogJson = (data, options) => ({
4577
4649
  })
4578
4650
  })
4579
4651
  });
4580
-
4581
4652
  //#endregion
4582
4653
  //#region ../../src/core/primitives/$ui.ts
4583
4654
  /**
@@ -4588,14 +4659,10 @@ const $ui = (options = {}) => {
4588
4659
  if (options.themes) alepha.store.set(alephaThemeListAtom, options.themes);
4589
4660
  return alepha.inject(UiRouter);
4590
4661
  };
4591
-
4592
- //#endregion
4593
- //#region ../../src/core/table/interfaces/types.ts
4594
- const DEFAULT_MAX_VISIBLE_COLUMNS = 8;
4595
-
4596
4662
  //#endregion
4597
4663
  //#region ../../src/core/table/components/DataTableFilters.tsx
4598
- const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) => {
4664
+ const DataTableFilters = (props) => {
4665
+ const { schema, form, typeFormProps, filterVisibility } = props;
4599
4666
  const visibleSchema = useMemo(() => {
4600
4667
  const visibleKeys = Object.keys(schema.properties).filter((key) => filterVisibility[key] !== false);
4601
4668
  if (visibleKeys.length === 0) return null;
@@ -4606,14 +4673,14 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
4606
4673
  return t.object(visibleProps);
4607
4674
  }, [schema, filterVisibility]);
4608
4675
  if (!visibleSchema) return null;
4609
- return /* @__PURE__ */ jsx(Flex$1, {
4610
- w: "100%",
4676
+ return /* @__PURE__ */ jsx(Flex, {
4677
+ surface: true,
4678
+ flex: 1,
4679
+ mt: -4,
4611
4680
  p: "xs",
4612
4681
  m: "xs",
4613
4682
  bdrs: "md",
4614
- bg: ui.colors.surface,
4615
4683
  children: /* @__PURE__ */ jsx(TypeForm, {
4616
- size: "xs",
4617
4684
  ...typeFormProps,
4618
4685
  skipSubmitButton: true,
4619
4686
  fill: true,
@@ -4624,17 +4691,17 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
4624
4691
  sm: 2,
4625
4692
  md: 3,
4626
4693
  lg: 4,
4627
- xl: 6
4694
+ xl: 5
4628
4695
  }
4629
4696
  })
4630
4697
  });
4631
4698
  };
4632
-
4633
4699
  //#endregion
4634
4700
  //#region ../../src/core/table/components/DataTablePagination.tsx
4635
- const DataTablePagination = ({ page, size, totalPages, totalElements, offset, numberOfElements, onPageChange, onSizeChange }) => {
4701
+ const DataTablePagination = ({ page, size, totalPages, totalElements, isFirst, isLast, offset, numberOfElements, onPageChange, onSizeChange }) => {
4636
4702
  const from = numberOfElements > 0 ? offset + 1 : 0;
4637
4703
  const to = offset + numberOfElements;
4704
+ const hasTotal = totalPages != null;
4638
4705
  return /* @__PURE__ */ jsxs(Flex, {
4639
4706
  align: "center",
4640
4707
  justify: "space-between",
@@ -4682,15 +4749,15 @@ const DataTablePagination = ({ page, size, totalPages, totalElements, offset, nu
4682
4749
  ]
4683
4750
  }) }), /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(Pagination, {
4684
4751
  size: "sm",
4685
- withEdges: true,
4686
- total: totalPages,
4752
+ withEdges: hasTotal,
4753
+ withPages: hasTotal,
4754
+ total: hasTotal ? totalPages : isLast !== false ? page : page + 1,
4687
4755
  value: page,
4688
4756
  onChange: onPageChange
4689
4757
  }) })]
4690
4758
  })]
4691
4759
  });
4692
4760
  };
4693
-
4694
4761
  //#endregion
4695
4762
  //#region ../../src/core/table/components/ColumnPicker.tsx
4696
4763
  const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
@@ -4706,7 +4773,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4706
4773
  let count = 0;
4707
4774
  onVisibilityChange(columnEntries.reduce((acc, [key, col]) => {
4708
4775
  if (col.defaultHidden) acc[key] = false;
4709
- else if (count < DEFAULT_MAX_VISIBLE_COLUMNS) {
4776
+ else if (count < 8) {
4710
4777
  acc[key] = true;
4711
4778
  count++;
4712
4779
  } else acc[key] = false;
@@ -4734,7 +4801,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4734
4801
  timingFunction: "ease"
4735
4802
  },
4736
4803
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
4737
- variant: "subtle",
4804
+ variant: "minimal",
4738
4805
  icon: IconColumns,
4739
4806
  onClick: () => setOpened((o) => !o)
4740
4807
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -4764,12 +4831,12 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4764
4831
  gap: 4,
4765
4832
  children: [/* @__PURE__ */ jsx(ActionButton, {
4766
4833
  size: "compact-xs",
4767
- variant: "subtle",
4834
+ variant: "minimal",
4768
4835
  onClick: handleShowAll,
4769
4836
  children: "All"
4770
4837
  }), /* @__PURE__ */ jsx(ActionButton, {
4771
4838
  size: "compact-xs",
4772
- variant: "subtle",
4839
+ variant: "minimal",
4773
4840
  onClick: handleDefault,
4774
4841
  children: "Default"
4775
4842
  })]
@@ -4791,7 +4858,6 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4791
4858
  })]
4792
4859
  });
4793
4860
  };
4794
-
4795
4861
  //#endregion
4796
4862
  //#region ../../src/core/table/components/FilterPicker.tsx
4797
4863
  const getFieldLabel = (schema, key) => {
@@ -4835,7 +4901,7 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4835
4901
  timingFunction: "ease"
4836
4902
  },
4837
4903
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
4838
- variant: "subtle",
4904
+ variant: "minimal",
4839
4905
  icon: IconFilter,
4840
4906
  onClick: () => setOpened((o) => !o)
4841
4907
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -4865,12 +4931,12 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4865
4931
  gap: 4,
4866
4932
  children: [/* @__PURE__ */ jsx(ActionButton, {
4867
4933
  size: "compact-xs",
4868
- variant: "subtle",
4934
+ variant: "minimal",
4869
4935
  onClick: handleShowAll,
4870
4936
  children: "All"
4871
4937
  }), /* @__PURE__ */ jsx(ActionButton, {
4872
4938
  size: "compact-xs",
4873
- variant: "subtle",
4939
+ variant: "minimal",
4874
4940
  onClick: handleHideAll,
4875
4941
  children: "None"
4876
4942
  })]
@@ -4892,7 +4958,6 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4892
4958
  })]
4893
4959
  });
4894
4960
  };
4895
-
4896
4961
  //#endregion
4897
4962
  //#region ../../src/core/table/components/DataTableToolbar.tsx
4898
4963
  const escapeCsvField = (value) => {
@@ -4964,7 +5029,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4964
5029
  onVisibilityChange: onColumnVisibilityChange
4965
5030
  }),
4966
5031
  withExport && /* @__PURE__ */ jsx(ActionButton, {
4967
- variant: "subtle",
5032
+ variant: "minimal",
4968
5033
  icon: IconDownload,
4969
5034
  menu: { items: [{
4970
5035
  label: "Export as CSV",
@@ -4987,7 +5052,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4987
5052
  children: [selectedItems.length, " selected"]
4988
5053
  }),
4989
5054
  /* @__PURE__ */ jsx(ActionButton, {
4990
- variant: "subtle",
5055
+ variant: "minimal",
4991
5056
  size: "compact-sm",
4992
5057
  icon: IconX,
4993
5058
  onClick: onClearSelection,
@@ -5011,7 +5076,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
5011
5076
  ...props,
5012
5077
  children: props.label
5013
5078
  }, index) : props), /* @__PURE__ */ jsx(ActionButton, {
5014
- variant: "subtle",
5079
+ variant: "minimal",
5015
5080
  icon: IconRefresh,
5016
5081
  onClick: onRefresh
5017
5082
  })]
@@ -5019,7 +5084,6 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
5019
5084
  ]
5020
5085
  });
5021
5086
  };
5022
-
5023
5087
  //#endregion
5024
5088
  //#region ../../src/core/table/components/useTableSelection.ts
5025
5089
  const useTableSelection = (items, getItemKey, enabled) => {
@@ -5082,7 +5146,6 @@ const useTableSelection = (items, getItemKey, enabled) => {
5082
5146
  isSelected: useCallback((item) => selectedKeys.has(getItemKey(item)), [selectedKeys, getItemKey])
5083
5147
  };
5084
5148
  };
5085
-
5086
5149
  //#endregion
5087
5150
  //#region ../../src/core/table/components/DataTable.tsx
5088
5151
  /**
@@ -5120,18 +5183,22 @@ const FIT_STYLE = {
5120
5183
  };
5121
5184
  const DataTable = (props) => {
5122
5185
  const [items, setItems] = useState(typeof props.items === "function" ? { content: [] } : props.items);
5123
- const defaultSize = props.infinityScroll ? 100 : props.defaultSize || 10;
5186
+ const itemsRef = useRef(items);
5187
+ const [loaded, setLoaded] = useState(typeof props.items !== "function" || !props.submitOnInit);
5188
+ const defaultSize = props.defaultSize || (props.infinityScroll ? 100 : 10);
5124
5189
  const [page, setPage] = useState(1);
5125
5190
  const [size, setSize] = useState(String(defaultSize));
5126
5191
  const [currentPage, setCurrentPage] = useState(0);
5127
5192
  const alepha = useInject(Alepha);
5193
+ itemsRef.current = items;
5128
5194
  const sentinelRef = useRef(null);
5195
+ const debounceRef = useRef(null);
5129
5196
  const [columnVisibility, setColumnVisibility] = useState(() => {
5130
5197
  const entries = Object.entries(props.columns);
5131
5198
  let visibleCount = 0;
5132
5199
  return entries.reduce((acc, [key, col]) => {
5133
5200
  if (col.defaultHidden) acc[key] = false;
5134
- else if (visibleCount < DEFAULT_MAX_VISIBLE_COLUMNS) {
5201
+ else if (visibleCount < 8) {
5135
5202
  acc[key] = true;
5136
5203
  visibleCount++;
5137
5204
  } else acc[key] = false;
@@ -5198,13 +5265,14 @@ const DataTable = (props) => {
5198
5265
  }),
5199
5266
  handler: async (values) => {
5200
5267
  if (typeof props.items === "function") {
5201
- const response = await props.items(values, { items: items.content });
5268
+ const response = await props.items(values, { items: itemsRef.current.content });
5202
5269
  if (props.infinityScroll && values.page > 0) setItems((prev) => ({
5203
5270
  ...response,
5204
5271
  content: [...prev.content, ...response.content]
5205
5272
  }));
5206
5273
  else setItems(response);
5207
5274
  setCurrentPage(values.page);
5275
+ if (!loaded) setLoaded(true);
5208
5276
  }
5209
5277
  },
5210
5278
  onReset: async () => {
@@ -5224,9 +5292,23 @@ const DataTable = (props) => {
5224
5292
  return;
5225
5293
  }
5226
5294
  props.onFilterChange?.(key, value, form);
5295
+ if (props.skipSubmitOnChange) return;
5296
+ form.input.page.set(0);
5297
+ const delay = props.debounce ?? 300;
5298
+ if (delay > 0) {
5299
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5300
+ debounceRef.current = setTimeout(() => {
5301
+ form.submit();
5302
+ }, delay);
5303
+ } else await form.submit();
5227
5304
  }
5228
- }, [items]);
5305
+ }, []);
5229
5306
  const dt = useInject(DateTimeProvider);
5307
+ useEffect(() => {
5308
+ return () => {
5309
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5310
+ };
5311
+ }, []);
5230
5312
  useEffect(() => {
5231
5313
  if (props.submitOnInit) form.submit();
5232
5314
  if (props.submitEvery) {
@@ -5291,9 +5373,9 @@ const DataTable = (props) => {
5291
5373
  }), col.sortable && /* @__PURE__ */ jsxs(Flex, {
5292
5374
  c: "dimmed",
5293
5375
  children: [
5294
- sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.sm }),
5295
- sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.sm }),
5296
- sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.sm })
5376
+ sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.xs }),
5377
+ sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.xs }),
5378
+ sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.xs })
5297
5379
  ]
5298
5380
  })]
5299
5381
  })
@@ -5353,9 +5435,15 @@ const DataTable = (props) => {
5353
5435
  form,
5354
5436
  alepha
5355
5437
  };
5438
+ const content = col.value?.(item, ctx);
5356
5439
  return /* @__PURE__ */ jsx(Table.Td, {
5357
5440
  style: col.fit ? FIT_STYLE : void 0,
5358
- children: col.value?.(item, ctx)
5441
+ children: col.action ? /* @__PURE__ */ jsx(ActionButton, {
5442
+ td: "inherit",
5443
+ unstyled: true,
5444
+ ...col.action(item),
5445
+ children: content
5446
+ }) : content
5359
5447
  }, key);
5360
5448
  }),
5361
5449
  props.rowActions && (() => {
@@ -5372,7 +5460,7 @@ const DataTable = (props) => {
5372
5460
  style: FIT_STYLE,
5373
5461
  onClick: (e) => e.stopPropagation(),
5374
5462
  children: /* @__PURE__ */ jsx(ActionButton, {
5375
- variant: "subtle",
5463
+ variant: "minimal",
5376
5464
  size: "xs",
5377
5465
  icon: IconDotsVertical,
5378
5466
  menu: { items: actions.map((action) => {
@@ -5380,7 +5468,10 @@ const DataTable = (props) => {
5380
5468
  return {
5381
5469
  label: action.label ?? (typeof action.tooltip === "string" ? action.tooltip : void 0),
5382
5470
  icon: Icon && isComponentType(Icon) ? /* @__PURE__ */ jsx(Icon, { size: 14 }) : Icon,
5383
- onClick: action.onClick,
5471
+ onClick: action.onClick ? async () => {
5472
+ await action.onClick();
5473
+ if (!action.skipRefresh) await form.submit();
5474
+ } : void 0,
5384
5475
  color: action.color
5385
5476
  };
5386
5477
  }) }
@@ -5442,15 +5533,21 @@ const DataTable = (props) => {
5442
5533
  bordered: true,
5443
5534
  elevated: true,
5444
5535
  shadowed: "xs",
5536
+ flex: 1,
5537
+ style: { minHeight: 0 },
5445
5538
  children: [
5446
5539
  /* @__PURE__ */ jsx(Flex, {
5447
5540
  className: "overflow-auto",
5541
+ flex: 1,
5542
+ style: { minHeight: 0 },
5543
+ col: true,
5448
5544
  children: /* @__PURE__ */ jsxs(Table, {
5449
5545
  "aria-label": "Data table",
5450
5546
  withRowBorders: true,
5451
5547
  highlightOnHover: true,
5452
5548
  ...props.tableProps,
5453
5549
  children: [/* @__PURE__ */ jsx(Table.Thead, {
5550
+ bdrs: "md",
5454
5551
  style: {
5455
5552
  position: "sticky",
5456
5553
  top: 0,
@@ -5462,30 +5559,39 @@ const DataTable = (props) => {
5462
5559
  head,
5463
5560
  props.rowActions && /* @__PURE__ */ jsx(Table.Th, { style: FIT_STYLE })
5464
5561
  ] })
5465
- }), /* @__PURE__ */ jsxs(Table.Tbody, {
5466
- style: {
5467
- opacity: form.submitting ? .5 : 1,
5468
- transition: "opacity 150ms ease"
5469
- },
5470
- children: [rows, items.content.length === 0 && /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5471
- colSpan: totalColumns || 1,
5472
- py: "xl",
5473
- style: { textAlign: "center" },
5562
+ }), /* @__PURE__ */ jsx(Table.Tbody, { children: !loaded || form.submitting ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5563
+ colSpan: totalColumns || 1,
5564
+ py: "sm",
5565
+ children: /* @__PURE__ */ jsx(Flex, {
5566
+ justify: "center",
5567
+ p: "md",
5568
+ children: /* @__PURE__ */ jsx(Loader, {
5569
+ size: "sm",
5570
+ type: "dots"
5571
+ })
5572
+ })
5573
+ }) }) : rows.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5574
+ colSpan: totalColumns || 1,
5575
+ py: "xl",
5576
+ children: /* @__PURE__ */ jsx(Flex, {
5577
+ justify: "center",
5474
5578
  children: /* @__PURE__ */ jsx(Text, {
5475
5579
  c: "dimmed",
5476
5580
  size: "sm",
5477
- children: form.submitting ? "Loading…" : "No results"
5581
+ children: props.emptyLabel ?? "No results"
5478
5582
  })
5479
- }) })]
5480
- })]
5583
+ })
5584
+ }) }) : rows })]
5481
5585
  })
5482
5586
  }),
5483
5587
  props.infinityScroll && /* @__PURE__ */ jsx("div", { ref: sentinelRef }),
5484
5588
  !props.infinityScroll && /* @__PURE__ */ jsx(DataTablePagination, {
5485
5589
  page,
5486
5590
  size,
5487
- totalPages: items.page?.totalPages ?? 1,
5591
+ totalPages: items.page?.totalPages,
5488
5592
  totalElements: items.page?.totalElements,
5593
+ isFirst: items.page?.isFirst,
5594
+ isLast: items.page?.isLast,
5489
5595
  offset: items.page?.offset ?? 0,
5490
5596
  numberOfElements: items.content.length,
5491
5597
  onPageChange: (value) => {
@@ -5507,7 +5613,6 @@ const DataTable = (props) => {
5507
5613
  })]
5508
5614
  });
5509
5615
  };
5510
-
5511
5616
  //#endregion
5512
5617
  //#region ../../src/core/utils/extractSchemaFields.ts
5513
5618
  /**
@@ -5625,15 +5730,14 @@ const OPERATOR_INFO = {
5625
5730
  example: "status=[active,pending]"
5626
5731
  }
5627
5732
  };
5628
-
5629
5733
  //#endregion
5630
5734
  //#region ../../src/core/utils/icons.tsx
5631
5735
  /**
5632
5736
  * Get the default icon for an input based on its type, format, or name.
5633
5737
  */
5634
5738
  const getDefaultIcon = (params) => {
5635
- const { type, format, name, isEnum, isArray, size = "sm" } = params;
5636
- const iconSize = ui.sizes.icon[size];
5739
+ const { type, format, name, isEnum, isArray, size = "xs" } = params;
5740
+ const iconSize = ui.sizes.icon[size] - 4;
5637
5741
  if (format) switch (format) {
5638
5742
  case "email": return /* @__PURE__ */ jsx(IconMail, { size: iconSize });
5639
5743
  case "url":
@@ -5667,7 +5771,6 @@ const getDefaultIcon = (params) => {
5667
5771
  }
5668
5772
  return /* @__PURE__ */ jsx(IconAt, { size: iconSize });
5669
5773
  };
5670
-
5671
5774
  //#endregion
5672
5775
  //#region ../../src/core/utils/string.ts
5673
5776
  /**
@@ -5705,7 +5808,6 @@ const prettyName = (name) => {
5705
5808
  const segments = name.split("/").filter((s) => s && !/^\d+$/.test(s));
5706
5809
  return toTitleCase(segments[segments.length - 1] || name.replaceAll("/", ""));
5707
5810
  };
5708
-
5709
5811
  //#endregion
5710
5812
  //#region ../../src/core/index.ts
5711
5813
  /**
@@ -5744,7 +5846,7 @@ const AlephaUI = $module({
5744
5846
  alepha.with(ToastService);
5745
5847
  }
5746
5848
  });
5747
-
5748
5849
  //#endregion
5749
- export { $ui, ActionButton, DashboardShell as AdminShell, DashboardShell, AlephaMantineProvider, AlephaUI, AlertDialog, AppBar, Breadcrumb as Breadcrumbs, BurgerButton, ClipboardButton, ConfirmDialog, Container, Control, ControlArray, ControlDate, ControlNumber, ControlObject, ControlQueryBuilder, ControlSelect, DarkModeButton, DataTable, DetailDrawer, DetailList, DialogService, Flex, Heading, JsonViewer, LanguageButton, OPERATOR_INFO, Omnibar, OmnibarButton, PromptDialog, Sidebar, ToggleSidebarButton as SidebarCollapseButton, StatCards, Text, ThemeButton, ThemeProvider, ToastService, TypeForm, UiRouter, alephaSidebarAtom, alephaThemeAtom, alephaThemeListAtom, alephaThemeOverridesAtom, capitalize, defaultTheme, dialogForm, dialogJson, extractSchemaFields, getDefaultIcon, getOperatorsForField, isComponentType, midnightTheme, prettyName, renderIcon, toTitleCase, ui, useDialog, useTheme, useToast };
5850
+ export { $ui, ActionButton, DashboardShell as AdminShell, DashboardShell, AlephaMantineProvider, AlephaUI, AlertDialog, AppBar, Breadcrumbs, BurgerButton, ClipboardButton, ConfirmDialog, Container, Control, ControlArray, ControlDate, ControlNumber, ControlObject, ControlQueryBuilder, ControlSelect, DarkModeButton, DataTable, DetailDrawer, DetailList, DialogService, Flex, Heading, JsonViewer, LanguageButton, OPERATOR_INFO, Omnibar, OmnibarButton, PromptDialog, Sidebar, ToggleSidebarButton as SidebarCollapseButton, SidebarCollapsedItem, SidebarItem, StatCards, Text, ThemeButton, ThemeProvider, ToastService, TypeForm, UiRouter, alephaSidebarAtom, alephaThemeAtom, alephaThemeListAtom, alephaThemeOverridesAtom, capitalize, defaultTheme, dialogForm, dialogJson, extractSchemaFields, getDefaultIcon, getOperatorsForField, isComponentType, midnightTheme, prettyName, renderIcon, toTitleCase, ui, useDialog, useTheme, useToast };
5851
+
5750
5852
  //# sourceMappingURL=index.js.map