@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
- import { $atom, $context, $inject, $module, Alepha, AlephaError, TypeBoxError, t } from "alepha";
2
- import { AlephaReactForm, FormValidationError, useForm, useFormState } from "alepha/react/form";
1
+ import { $atom, $inject, $module, Alepha, AlephaError, TypeBoxError, t } from "alepha";
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, {
@@ -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, {
@@ -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, {
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, { 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, { 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/DarkModeButton.tsx
1846
1822
  /**
@@ -1872,7 +1848,6 @@ const DarkModeButton = (props) => {
1872
1848
  ...props
1873
1849
  });
1874
1850
  };
1875
-
1876
1851
  //#endregion
1877
1852
  //#region ../../src/core/components/buttons/LanguageButton.tsx
1878
1853
  const LanguageButton = (props) => {
@@ -1888,7 +1863,6 @@ const LanguageButton = (props) => {
1888
1863
  ...props
1889
1864
  });
1890
1865
  };
1891
-
1892
1866
  //#endregion
1893
1867
  //#region ../../src/core/components/buttons/OmnibarButton.tsx
1894
1868
  const OmnibarButton = (props) => {
@@ -1933,7 +1907,6 @@ const OmnibarButton = (props) => {
1933
1907
  })
1934
1908
  });
1935
1909
  };
1936
-
1937
1910
  //#endregion
1938
1911
  //#region ../../src/core/hooks/useDialog.ts
1939
1912
  /**
@@ -1950,7 +1923,6 @@ const OmnibarButton = (props) => {
1950
1923
  const useDialog = () => {
1951
1924
  return useInject(DialogService);
1952
1925
  };
1953
-
1954
1926
  //#endregion
1955
1927
  //#region ../../src/core/components/buttons/ThemeExpertModal.tsx
1956
1928
  const MANTINE_COLORS = [
@@ -2159,7 +2131,6 @@ const ThemeExpertModal = () => {
2159
2131
  ]
2160
2132
  });
2161
2133
  };
2162
-
2163
2134
  //#endregion
2164
2135
  //#region ../../src/core/components/buttons/ThemeButton.tsx
2165
2136
  const ThemeButton = (props) => {
@@ -2188,7 +2159,6 @@ const ThemeButton = (props) => {
2188
2159
  ...actionProps
2189
2160
  });
2190
2161
  };
2191
-
2192
2162
  //#endregion
2193
2163
  //#region ../../src/core/components/buttons/ToggleSidebarButton.tsx
2194
2164
  const ToggleSidebarButton = (props) => {
@@ -2210,11 +2180,10 @@ const ToggleSidebarButton = (props) => {
2210
2180
  ...props
2211
2181
  });
2212
2182
  };
2213
-
2214
2183
  //#endregion
2215
2184
  //#region ../../src/core/components/Flex.tsx
2216
2185
  const Flex$1 = forwardRef((props, ref) => {
2217
- const { fill, center, centerX, centerY, col, ground, surface, elevated, rounded, bordered, borderedTop, borderedBottom, shadowed, ...rest } = props;
2186
+ const { fill, center, centerX, centerY, col, ground, surface, elevated, rounded, bordered, borderedTop, borderedBottom, shadowed, overflow, form, ...rest } = props;
2218
2187
  if (fill) rest.flex ??= 1;
2219
2188
  if (col) rest.direction ??= "column";
2220
2189
  if (center) {
@@ -2237,19 +2206,28 @@ const Flex$1 = forwardRef((props, ref) => {
2237
2206
  ...rest.style ?? {}
2238
2207
  };
2239
2208
  if (shadowed) rest.className = `${rest.className ?? ""} shadow-${shadowed === true ? "md" : shadowed}`.trim();
2209
+ if (overflow) rest.className = `${rest.className ?? ""} overflow-auto`.trim();
2210
+ if (form) {
2211
+ let formProps = typeof form === "object" ? form : {};
2212
+ if (formProps instanceof FormModel) formProps = formProps.props;
2213
+ return /* @__PURE__ */ jsx(Flex, {
2214
+ ref,
2215
+ component: "form",
2216
+ ...formProps,
2217
+ ...rest
2218
+ });
2219
+ }
2240
2220
  return /* @__PURE__ */ jsx(Flex, {
2241
2221
  ref,
2242
2222
  ...rest
2243
2223
  });
2244
2224
  });
2245
2225
  Flex$1.displayName = "Flex";
2246
-
2247
2226
  //#endregion
2248
2227
  //#region ../../src/core/components/Heading.tsx
2249
2228
  const Heading = (props) => {
2250
2229
  return /* @__PURE__ */ jsx("h1", { children: "Heading" });
2251
2230
  };
2252
-
2253
2231
  //#endregion
2254
2232
  //#region ../../src/core/components/layout/AppBar.tsx
2255
2233
  const AppBar = (props) => {
@@ -2364,7 +2342,6 @@ const AppBar = (props) => {
2364
2342
  });
2365
2343
  return content;
2366
2344
  };
2367
-
2368
2345
  //#endregion
2369
2346
  //#region ../../src/core/components/layout/Breadcrumb.tsx
2370
2347
  /**
@@ -2374,7 +2351,8 @@ const AppBar = (props) => {
2374
2351
  * Pages should define a `label` in their `$page()` options for best results.
2375
2352
  * Falls back to the page name converted to Title Case.
2376
2353
  */
2377
- const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) => {
2354
+ const Breadcrumbs = (props) => {
2355
+ const { home = "Home", separator, size = "sm", ...groupProps } = props;
2378
2356
  const state = useRouterState();
2379
2357
  const router = useRouter();
2380
2358
  const crumbs = [];
@@ -2418,7 +2396,6 @@ const Breadcrumb = ({ home = "Home", separator, size = "sm", ...groupProps }) =>
2418
2396
  }, crumb.href))
2419
2397
  });
2420
2398
  };
2421
-
2422
2399
  //#endregion
2423
2400
  //#region ../../src/core/components/layout/Container.tsx
2424
2401
  const Container$1 = forwardRef((props, ref) => {
@@ -2428,12 +2405,171 @@ const Container$1 = forwardRef((props, ref) => {
2428
2405
  });
2429
2406
  });
2430
2407
  Container$1.displayName = "Container";
2431
-
2408
+ //#endregion
2409
+ //#region ../../src/core/helpers/renderIcon.tsx
2410
+ const renderIcon = (icon, size) => {
2411
+ if (!icon) return null;
2412
+ if (isValidElement(icon)) return icon;
2413
+ if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
2414
+ return icon;
2415
+ };
2416
+ //#endregion
2417
+ //#region ../../src/core/components/Text.tsx
2418
+ const INTENT_COLORS = {
2419
+ primary: "blue",
2420
+ info: "cyan",
2421
+ success: "green",
2422
+ warning: "yellow",
2423
+ danger: "red"
2424
+ };
2425
+ const Text$1 = forwardRef((props, ref) => {
2426
+ const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
2427
+ if (intent) rest.c ??= INTENT_COLORS[intent];
2428
+ if (bold) rest.fw ??= 700;
2429
+ if (light) rest.fw ??= 300;
2430
+ if (italic) rest.fs ??= "italic";
2431
+ if (muted) rest.c ??= "dimmed";
2432
+ if (small) rest.size ??= "xs";
2433
+ if (uppercase) rest.tt ??= "uppercase";
2434
+ if (capitalize) rest.tt ??= "capitalize";
2435
+ if (center) rest.ta ??= "center";
2436
+ if (monospace) rest.ff ??= "monospace";
2437
+ if (title) rest.size ??= "xl";
2438
+ return /* @__PURE__ */ jsx(Text, {
2439
+ ref,
2440
+ ...rest
2441
+ });
2442
+ });
2443
+ Text$1.displayName = "Text";
2444
+ //#endregion
2445
+ //#region ../../src/core/components/layout/SidebarCollapsedItem.tsx
2446
+ const SidebarCollapsedItem = (props) => {
2447
+ const router = useRouter();
2448
+ const handleItemClick = () => {
2449
+ props.onItemClick?.(props.item);
2450
+ props.item.onClick?.();
2451
+ };
2452
+ const hasChildren = props.item.children && props.item.children.length > 0;
2453
+ const menu = hasChildren ? {
2454
+ on: "hover",
2455
+ position: "right",
2456
+ menuProps: {
2457
+ arrowPosition: "center",
2458
+ arrowSize: 10,
2459
+ withArrow: true
2460
+ },
2461
+ items: [{
2462
+ type: "label",
2463
+ label: props.item.label
2464
+ }, ...props.item.children.filter((child) => !child.can || child.can()).map((child) => ({
2465
+ label: child.label,
2466
+ icon: renderIcon(child.icon, ui.sizes.icon.sm),
2467
+ href: child.href,
2468
+ active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
2469
+ }))]
2470
+ } : void 0;
2471
+ return /* @__PURE__ */ jsx(Flex$1, {
2472
+ w: "100%",
2473
+ justify: "center",
2474
+ pos: "relative",
2475
+ children: /* @__PURE__ */ jsx(ActionButton, {
2476
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2477
+ bd: 0,
2478
+ variant: "default",
2479
+ propsActive: { variant: "outline" },
2480
+ tooltip: hasChildren ? void 0 : {
2481
+ label: props.item.label,
2482
+ position: "right"
2483
+ },
2484
+ onClick: hasChildren ? void 0 : handleItemClick,
2485
+ icon: renderIcon(props.item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
2486
+ href: hasChildren ? void 0 : props.item.href,
2487
+ target: hasChildren ? void 0 : props.item.target,
2488
+ menu,
2489
+ ...props.item.actionProps
2490
+ })
2491
+ });
2492
+ };
2493
+ //#endregion
2494
+ //#region ../../src/core/components/layout/SidebarItem.tsx
2495
+ const SidebarItem = (props) => {
2496
+ const maxLevel = 2;
2497
+ const router = useRouter();
2498
+ const isActive = useCallback((item) => {
2499
+ if (!item.children) return false;
2500
+ for (const child of item.children) {
2501
+ if (child.href) {
2502
+ if (router.isActive(child.href)) return true;
2503
+ }
2504
+ if (isActive(child)) return true;
2505
+ }
2506
+ return false;
2507
+ }, []);
2508
+ const [isOpen, setIsOpen] = useState(isActive(props.item));
2509
+ useEvents({ "react:transition:end": () => {
2510
+ if (isActive(props.item)) setIsOpen(true);
2511
+ } }, []);
2512
+ if (props.level > maxLevel) return null;
2513
+ const handleItemClick = (e) => {
2514
+ if (!props.item.target) e.preventDefault();
2515
+ if (props.item.children && props.item.children.length > 0) setIsOpen(!isOpen);
2516
+ else {
2517
+ props.onItemClick?.(props.item);
2518
+ props.item.onClick?.();
2519
+ }
2520
+ };
2521
+ return /* @__PURE__ */ jsxs(Flex$1, {
2522
+ direction: "column",
2523
+ ps: props.level === 0 ? 0 : 32,
2524
+ pos: "relative",
2525
+ children: [/* @__PURE__ */ jsx(ActionButton, {
2526
+ w: "100%",
2527
+ justify: "space-between",
2528
+ href: props.item.href,
2529
+ target: props.item.target,
2530
+ size: props.item.theme?.size ?? props.theme.button?.size ?? (props.level === 0 ? "sm" : "xs"),
2531
+ bd: 0,
2532
+ fw: "normal",
2533
+ variant: "default",
2534
+ propsActive: { variant: "outline" },
2535
+ radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
2536
+ onClick: handleItemClick,
2537
+ leftSection: /* @__PURE__ */ jsxs(Flex$1, {
2538
+ w: "100%",
2539
+ align: "center",
2540
+ gap: "sm",
2541
+ children: [renderIcon(props.item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex$1, {
2542
+ direction: "column",
2543
+ children: /* @__PURE__ */ jsx(Flex$1, { children: props.item.label })
2544
+ })]
2545
+ }),
2546
+ rightSection: props.item.children ? /* @__PURE__ */ jsx(Flex$1, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
2547
+ ...props.item.actionProps
2548
+ }), props.item.children && isOpen && /* @__PURE__ */ jsxs(Flex$1, {
2549
+ direction: "column",
2550
+ "data-parent-level": props.level,
2551
+ gap: 2,
2552
+ py: 2,
2553
+ children: [/* @__PURE__ */ jsx(Flex$1, { style: {
2554
+ position: "absolute",
2555
+ width: 1,
2556
+ background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
2557
+ top: 48,
2558
+ left: 20 + 32 * props.level,
2559
+ bottom: 16
2560
+ } }), props.item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
2561
+ item: child,
2562
+ level: props.level + 1,
2563
+ onItemClick: props.onItemClick,
2564
+ theme: props.theme
2565
+ }, index))]
2566
+ })]
2567
+ });
2568
+ };
2432
2569
  //#endregion
2433
2570
  //#region ../../src/core/components/layout/Sidebar.tsx
2434
2571
  const Sidebar = (props) => {
2435
2572
  const router = useRouter();
2436
- const { onItemClick } = props;
2437
2573
  const divider = (key, fill, collapsed) => {
2438
2574
  return /* @__PURE__ */ jsx(Flex$1, {
2439
2575
  h: 1,
@@ -2484,13 +2620,13 @@ const Sidebar = (props) => {
2484
2620
  if (collapsed) return /* @__PURE__ */ jsx(SidebarCollapsedItem, {
2485
2621
  item,
2486
2622
  level: 0,
2487
- onItemClick,
2623
+ onItemClick: props.onItemClick,
2488
2624
  theme: props.theme ?? {}
2489
2625
  }, key);
2490
2626
  return /* @__PURE__ */ jsx(SidebarItem, {
2491
2627
  item,
2492
2628
  level: 0,
2493
- onItemClick,
2629
+ onItemClick: props.onItemClick,
2494
2630
  theme: props.theme ?? {}
2495
2631
  }, key);
2496
2632
  };
@@ -2553,133 +2689,9 @@ const Sidebar = (props) => {
2553
2689
  })] });
2554
2690
  return renderSidebar(false);
2555
2691
  };
2556
- const SidebarItem = (props) => {
2557
- const { item, level } = props;
2558
- const maxLevel = 2;
2559
- const router = useRouter();
2560
- const isActive = useCallback((item) => {
2561
- if (!item.children) return false;
2562
- for (const child of item.children) {
2563
- if (child.href) {
2564
- if (router.isActive(child.href)) return true;
2565
- }
2566
- if (isActive(child)) return true;
2567
- }
2568
- return false;
2569
- }, []);
2570
- const [isOpen, setIsOpen] = useState(isActive(item));
2571
- useEvents({ "react:transition:end": () => {
2572
- if (isActive(item)) setIsOpen(true);
2573
- } }, []);
2574
- if (level > maxLevel) return null;
2575
- const handleItemClick = (e) => {
2576
- if (!props.item.target) e.preventDefault();
2577
- if (item.children && item.children.length > 0) setIsOpen(!isOpen);
2578
- else {
2579
- props.onItemClick?.(item);
2580
- item.onClick?.();
2581
- }
2582
- };
2583
- return /* @__PURE__ */ jsxs(Flex$1, {
2584
- direction: "column",
2585
- ps: level === 0 ? 0 : 32,
2586
- pos: "relative",
2587
- children: [/* @__PURE__ */ jsx(ActionButton, {
2588
- w: "100%",
2589
- justify: "space-between",
2590
- href: props.item.href,
2591
- target: props.item.target,
2592
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
2593
- bd: 0,
2594
- fw: "normal",
2595
- variant: "default",
2596
- propsActive: { variant: "outline" },
2597
- radius: props.item.theme?.radius ?? props.theme.button?.radius ?? "md",
2598
- onClick: handleItemClick,
2599
- leftSection: /* @__PURE__ */ jsxs(Flex$1, {
2600
- w: "100%",
2601
- align: "center",
2602
- gap: "sm",
2603
- children: [renderIcon(item.icon, ui.sizes.icon.sm), /* @__PURE__ */ jsx(Flex$1, {
2604
- direction: "column",
2605
- children: /* @__PURE__ */ jsx(Flex$1, { children: item.label })
2606
- })]
2607
- }),
2608
- rightSection: item.children ? /* @__PURE__ */ jsx(Flex$1, { children: isOpen ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14 }) }) : props.item.rightSection,
2609
- ...props.item.actionProps
2610
- }), item.children && isOpen && /* @__PURE__ */ jsxs(Flex$1, {
2611
- direction: "column",
2612
- "data-parent-level": level,
2613
- gap: 2,
2614
- py: 2,
2615
- children: [/* @__PURE__ */ jsx(Flex$1, { style: {
2616
- position: "absolute",
2617
- width: 1,
2618
- background: "linear-gradient(to bottom, transparent, var(--mantine-color-default-border), transparent)",
2619
- top: 48,
2620
- left: 20 + 32 * level,
2621
- bottom: 16
2622
- } }), item.children.filter((child) => !child.can || child.can()).map((child, index) => /* @__PURE__ */ jsx(SidebarItem, {
2623
- item: child,
2624
- level: level + 1,
2625
- onItemClick: props.onItemClick,
2626
- theme: props.theme
2627
- }, index))]
2628
- })]
2629
- });
2630
- };
2631
- const SidebarCollapsedItem = (props) => {
2632
- const { item, level } = props;
2633
- const router = useRouter();
2634
- const handleItemClick = () => {
2635
- props.onItemClick?.(item);
2636
- item.onClick?.();
2637
- };
2638
- const hasChildren = item.children && item.children.length > 0;
2639
- const menu = hasChildren ? {
2640
- on: "hover",
2641
- position: "right",
2642
- menuProps: {
2643
- arrowPosition: "center",
2644
- arrowSize: 10,
2645
- withArrow: true
2646
- },
2647
- items: [{
2648
- type: "label",
2649
- label: item.label
2650
- }, ...item.children.filter((child) => !child.can || child.can()).map((child) => ({
2651
- label: child.label,
2652
- icon: renderIcon(child.icon, ui.sizes.icon.sm),
2653
- href: child.href,
2654
- active: child.href ? router.isActive(child.href, { startWith: child.activeStartsWith }) : void 0
2655
- }))]
2656
- } : void 0;
2657
- return /* @__PURE__ */ jsx(Flex$1, {
2658
- w: "100%",
2659
- justify: "center",
2660
- pos: "relative",
2661
- children: /* @__PURE__ */ jsx(ActionButton, {
2662
- size: props.item.theme?.size ?? props.theme.button?.size ?? (level === 0 ? "sm" : "xs"),
2663
- bd: 0,
2664
- variant: "default",
2665
- propsActive: { variant: "outline" },
2666
- tooltip: hasChildren ? void 0 : {
2667
- label: item.label,
2668
- position: "right"
2669
- },
2670
- onClick: hasChildren ? void 0 : handleItemClick,
2671
- icon: renderIcon(item.icon, ui.sizes.icon.sm) ?? /* @__PURE__ */ jsx(IconSquareRounded, { size: ui.sizes.icon.sm }),
2672
- href: hasChildren ? void 0 : props.item.href,
2673
- target: hasChildren ? void 0 : props.item.target,
2674
- menu,
2675
- ...props.item.actionProps
2676
- })
2677
- });
2678
- };
2679
-
2680
- //#endregion
2681
- //#region ../../src/core/components/layout/DashboardShell.tsx
2682
- const DashboardShell = (props) => {
2692
+ //#endregion
2693
+ //#region ../../src/core/components/layout/DashboardShell.tsx
2694
+ const DashboardShell = (props) => {
2683
2695
  const router = useRouter();
2684
2696
  const [sidebar, setSidebar] = useStore(alephaSidebarAtom);
2685
2697
  const collapsed = props.sidebarProps?.collapsed !== void 0 ? props.sidebarProps.collapsed : sidebar.collapsed;
@@ -2716,6 +2728,8 @@ const DashboardShell = (props) => {
2716
2728
  const fHeight = props.footerHeight ?? 24;
2717
2729
  const headerHeight = hasAppBar ? hHeight : 0;
2718
2730
  const footerHeight = footerElement ? fHeight : 0;
2731
+ const navbarWidth = collapsed ? collapsedWidth : expandedWidth;
2732
+ const mainContent = props.children ?? /* @__PURE__ */ jsx(NestedView, {});
2719
2733
  return /* @__PURE__ */ jsxs(AppShell, {
2720
2734
  layout: "alt",
2721
2735
  w: "100%",
@@ -2723,7 +2737,7 @@ const DashboardShell = (props) => {
2723
2737
  flex: 1,
2724
2738
  header: hasAppBar ? { height: hHeight } : void 0,
2725
2739
  navbar: hasSidebar ? {
2726
- width: { base: collapsed ? collapsedWidth : expandedWidth },
2740
+ width: { base: navbarWidth },
2727
2741
  breakpoint: "md",
2728
2742
  collapsed: { mobile: sidebar.closed }
2729
2743
  } : void 0,
@@ -2760,8 +2774,12 @@ const DashboardShell = (props) => {
2760
2774
  display: "flex",
2761
2775
  bg: "var(--alepha-ground)",
2762
2776
  pos: "relative",
2777
+ h: props.fill ? "100%" : "inherit",
2763
2778
  ...props.appShellMainProps,
2764
- children: props.children ?? /* @__PURE__ */ jsx(NestedView, {})
2779
+ children: props.container ? /* @__PURE__ */ jsx(Container$1, {
2780
+ ...typeof props.container === "boolean" ? {} : props.container,
2781
+ children: mainContent
2782
+ }) : mainContent
2765
2783
  }),
2766
2784
  footerElement && /* @__PURE__ */ jsx(AppShell.Footer, {
2767
2785
  ...props.appShellFooterProps,
@@ -2770,42 +2788,12 @@ const DashboardShell = (props) => {
2770
2788
  ]
2771
2789
  });
2772
2790
  };
2773
-
2774
- //#endregion
2775
- //#region ../../src/core/components/Text.tsx
2776
- const INTENT_COLORS = {
2777
- primary: "blue",
2778
- info: "cyan",
2779
- success: "green",
2780
- warning: "yellow",
2781
- danger: "red"
2782
- };
2783
- const Text$1 = forwardRef((props, ref) => {
2784
- const { intent, bold, italic, light, muted, small, uppercase, capitalize, center, monospace, title, ...rest } = props;
2785
- if (intent) rest.c ??= INTENT_COLORS[intent];
2786
- if (bold) rest.fw ??= 700;
2787
- if (light) rest.fw ??= 300;
2788
- if (italic) rest.fs ??= "italic";
2789
- if (muted) rest.c ??= "dimmed";
2790
- if (small) rest.size ??= "xs";
2791
- if (uppercase) rest.tt ??= "uppercase";
2792
- if (capitalize) rest.tt ??= "capitalize";
2793
- if (center) rest.ta ??= "center";
2794
- if (monospace) rest.ff ??= "monospace";
2795
- if (title) rest.size ??= "xl";
2796
- return /* @__PURE__ */ jsx(Text, {
2797
- ref,
2798
- ...rest
2799
- });
2800
- });
2801
- Text$1.displayName = "Text";
2802
-
2803
2791
  //#endregion
2804
2792
  //#region ../../src/core/form/utils/parseInput.ts
2805
2793
  const parseInput = (props, form) => {
2806
2794
  const disabled = false;
2807
2795
  const id = props.input.props.id;
2808
- 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);
2796
+ 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);
2809
2797
  const description = props.description ?? ("description" in props.input.schema && typeof props.input.schema.description === "string" ? props.input.schema.description : void 0);
2810
2798
  const error = form.error && form.error instanceof TypeBoxError ? form.error.value.message : void 0;
2811
2799
  const icon = !props.icon ? getDefaultIcon({
@@ -2813,17 +2801,20 @@ const parseInput = (props, form) => {
2813
2801
  format: props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0,
2814
2802
  name: props.input.props.name,
2815
2803
  isEnum: props.input.schema && "enum" in props.input.schema && Boolean(props.input.schema.enum),
2816
- isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array"
2817
- }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.md });
2804
+ isArray: props.input.schema && "type" in props.input.schema && props.input.schema.type === "array",
2805
+ size: props.size
2806
+ }) : isValidElement(props.icon) ? props.icon : createElement(props.icon, { size: ui.sizes.icon.sm });
2818
2807
  const format = props.input.schema && "format" in props.input.schema && typeof props.input.schema.format === "string" ? props.input.schema.format : void 0;
2819
2808
  const required = props.input.required;
2820
2809
  const schema = props.input.schema;
2810
+ const testId = props.input.props?.["data-testid"];
2821
2811
  const inputProps = {
2822
2812
  label,
2823
2813
  description,
2824
2814
  error,
2825
2815
  required,
2826
- disabled
2816
+ disabled,
2817
+ ...testId ? { "data-testid": testId } : {}
2827
2818
  };
2828
2819
  if ("minLength" in schema && typeof schema.minLength === "number") inputProps.minLength = schema.minLength;
2829
2820
  if ("maxLength" in schema && typeof schema.maxLength === "number") inputProps.maxLength = schema.maxLength;
@@ -2837,7 +2828,6 @@ const parseInput = (props, form) => {
2837
2828
  inputProps
2838
2829
  };
2839
2830
  };
2840
-
2841
2831
  //#endregion
2842
2832
  //#region ../../src/core/form/components/ControlArray.tsx
2843
2833
  /**
@@ -2848,8 +2838,8 @@ const useArrayItems = (input) => {
2848
2838
  const alepha = useAlepha();
2849
2839
  const keyCounter = useRef(0);
2850
2840
  const [items, setItemsState] = useState(() => {
2851
- const defaultValue = input?.props?.defaultValue;
2852
- if (Array.isArray(defaultValue)) return defaultValue.map((value) => ({
2841
+ const initial = input?.initialValue;
2842
+ if (Array.isArray(initial)) return initial.map((value) => ({
2853
2843
  key: keyCounter.current++,
2854
2844
  value
2855
2845
  }));
@@ -2875,22 +2865,9 @@ const useArrayItems = (input) => {
2875
2865
  if (!input?.form) return;
2876
2866
  const formId = input.form.id;
2877
2867
  const fieldPath = input.path;
2878
- const listeners = [alepha.events.on("form:reset", (event) => {
2879
- if (event.id === formId) {
2880
- const defaultValue = input.props?.defaultValue;
2881
- keyCounter.current = 0;
2882
- if (Array.isArray(defaultValue)) setItemsState(defaultValue.map((value) => ({
2883
- key: keyCounter.current++,
2884
- value
2885
- })));
2886
- else setItemsState([]);
2887
- }
2888
- }), alepha.events.on("form:change", (event) => {
2868
+ return alepha.events.on("form:change", (event) => {
2889
2869
  if (event.id === formId && event.path === fieldPath) syncFromFormValue(event.value);
2890
- })];
2891
- return () => {
2892
- for (const unsub of listeners) unsub();
2893
- };
2870
+ });
2894
2871
  }, [
2895
2872
  alepha,
2896
2873
  input,
@@ -2915,10 +2892,10 @@ const createArrayItemInput = (parentInput, itemSchema, index, _itemKey, value, o
2915
2892
  path: `${parentInput.path}/${index}`,
2916
2893
  required: false,
2917
2894
  form: parentInput.form,
2895
+ initialValue: value,
2918
2896
  props: {
2919
2897
  id: `${parentInput.props.id}-${index}`,
2920
- name: `${parentInput.props.name}[${index}]`,
2921
- defaultValue: value
2898
+ name: `${parentInput.props.name}[${index}]`
2922
2899
  },
2923
2900
  set: onValueChange
2924
2901
  };
@@ -2933,10 +2910,10 @@ const createArrayItemFieldInput = (parentInput, itemSchema, fieldName, index, _i
2933
2910
  path: `${parentInput.path}/${index}/${fieldName}`,
2934
2911
  required: itemSchema.required?.includes(fieldName) ?? false,
2935
2912
  form: parentInput.form,
2913
+ initialValue: itemValue?.[fieldName],
2936
2914
  props: {
2937
2915
  id: `${parentInput.props.id}-${index}-${fieldName}`,
2938
- name: `${parentInput.props.name}[${index}].${fieldName}`,
2939
- defaultValue: itemValue?.[fieldName]
2916
+ name: `${parentInput.props.name}[${index}].${fieldName}`
2940
2917
  },
2941
2918
  set: (value) => onFieldChange(fieldName, value)
2942
2919
  };
@@ -3140,7 +3117,6 @@ const ControlArray = (props) => {
3140
3117
  })
3141
3118
  });
3142
3119
  };
3143
-
3144
3120
  //#endregion
3145
3121
  //#region ../../src/core/form/components/ControlDate.tsx
3146
3122
  /**
@@ -3154,7 +3130,9 @@ const ControlArray = (props) => {
3154
3130
  * Automatically detects date formats from schema and renders appropriate picker.
3155
3131
  */
3156
3132
  const ControlDate = (props) => {
3157
- const { inputProps, id, icon, format } = parseInput(props, useFormState(props.input));
3133
+ const form = useFormState(props.input);
3134
+ const [value, setValue] = useFieldValue(props.input);
3135
+ const { inputProps, id, icon, format } = parseInput(props, form);
3158
3136
  if (!props.input?.props) return null;
3159
3137
  if (props.datetime || format === "date-time") {
3160
3138
  const dateTimePickerProps = typeof props.datetime === "object" ? props.datetime : {};
@@ -3162,10 +3140,8 @@ const ControlDate = (props) => {
3162
3140
  ...inputProps,
3163
3141
  id,
3164
3142
  leftSection: icon,
3165
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
3166
- onChange: (value) => {
3167
- props.input.set(value ? new Date(value).toISOString() : void 0);
3168
- },
3143
+ value: value ? new Date(value) : null,
3144
+ onChange: (val) => setValue(val ? new Date(val).toISOString() : void 0),
3169
3145
  ...dateTimePickerProps
3170
3146
  });
3171
3147
  }
@@ -3175,10 +3151,8 @@ const ControlDate = (props) => {
3175
3151
  ...inputProps,
3176
3152
  id,
3177
3153
  leftSection: icon,
3178
- defaultValue: props.input.props.defaultValue ? new Date(props.input.props.defaultValue) : void 0,
3179
- onChange: (value) => {
3180
- props.input.set(value ? new Date(value).toISOString().slice(0, 10) : void 0);
3181
- },
3154
+ value: value ? new Date(value) : null,
3155
+ onChange: (val) => setValue(val ? new Date(val).toISOString().slice(0, 10) : void 0),
3182
3156
  ...dateInputProps
3183
3157
  });
3184
3158
  }
@@ -3188,30 +3162,23 @@ const ControlDate = (props) => {
3188
3162
  ...inputProps,
3189
3163
  id,
3190
3164
  leftSection: icon,
3191
- defaultValue: props.input.props.defaultValue,
3192
- onChange: (event) => {
3193
- props.input.set(event.currentTarget.value);
3194
- },
3165
+ value: value ?? "",
3166
+ onChange: (event) => setValue(event.currentTarget.value),
3195
3167
  ...timeInputProps
3196
3168
  });
3197
3169
  }
3198
3170
  return null;
3199
3171
  };
3200
-
3201
3172
  //#endregion
3202
3173
  //#region ../../src/core/form/components/ControlNumber.tsx
3203
3174
  /**
3204
3175
  *
3205
3176
  */
3206
3177
  const ControlNumber = (props) => {
3207
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
3208
- const ref = useRef(null);
3209
- const [value, setValue] = useState(props.input.props.defaultValue);
3210
- useEvents({ "form:reset": (event) => {
3211
- if (event.id === props.input?.form.id && ref.current) setValue(props.input.props.defaultValue);
3212
- } }, [props.input]);
3178
+ const form = useFormState(props.input);
3179
+ const [value, setValue] = useFieldValue(props.input);
3180
+ const { inputProps, id, icon } = parseInput(props, form);
3213
3181
  if (!props.input?.props) return null;
3214
- const { type, ...inputPropsWithoutType } = props.input.props;
3215
3182
  if (props.sliderProps) {
3216
3183
  const min = props.sliderProps.min ?? inputProps.minimum ?? 0;
3217
3184
  const max = props.sliderProps.max ?? inputProps.maximum ?? 100;
@@ -3224,38 +3191,28 @@ const ControlNumber = (props) => {
3224
3191
  },
3225
3192
  children: /* @__PURE__ */ jsx(Slider, {
3226
3193
  ...inputProps,
3227
- ref,
3228
3194
  id,
3229
- ...inputPropsWithoutType,
3230
3195
  ...props.sliderProps,
3231
- value,
3196
+ value: value ?? 0,
3232
3197
  min,
3233
3198
  max,
3234
3199
  label: () => value,
3235
- onChange: (val) => {
3236
- setValue(val);
3237
- props.input.set(val);
3238
- }
3200
+ onChange: (val) => setValue(val)
3239
3201
  })
3240
3202
  })
3241
3203
  });
3242
3204
  }
3243
3205
  return /* @__PURE__ */ jsx(NumberInput, {
3244
3206
  ...inputProps,
3245
- ref,
3246
3207
  id,
3247
3208
  leftSection: icon,
3248
- ...inputPropsWithoutType,
3249
3209
  ...props.numberInputProps,
3250
3210
  value: value ?? "",
3251
3211
  onChange: (val) => {
3252
- const newValue = val !== null ? Number(val) : void 0;
3253
- setValue(newValue);
3254
- props.input.set(newValue);
3212
+ setValue(val !== null ? Number(val) : void 0);
3255
3213
  }
3256
3214
  });
3257
3215
  };
3258
-
3259
3216
  //#endregion
3260
3217
  //#region ../../src/core/form/components/ControlObject.tsx
3261
3218
  /**
@@ -3332,94 +3289,10 @@ const ControlObject = (props) => {
3332
3289
  })
3333
3290
  });
3334
3291
  };
3335
-
3336
3292
  //#endregion
3337
- //#region ../../src/core/form/components/ControlQueryBuilder.tsx
3338
- /**
3339
- * Query builder with text input and help popover.
3340
- * Generates query strings for parseQueryString syntax.
3341
- */
3342
- const ControlQueryBuilder = ({ schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps }) => {
3343
- const [helpOpened, setHelpOpened] = useState(false);
3344
- const [textValue, setTextValue] = useState(value);
3345
- const inputRef = useRef(null);
3346
- const fields = schema ? extractSchemaFields(schema) : [];
3347
- const [error, setError] = useState(null);
3348
- const isValid = (value) => {
3349
- try {
3350
- parseQueryString(value.trim());
3351
- } catch (e) {
3352
- setError(e.message);
3353
- return false;
3354
- }
3355
- setError(null);
3356
- return true;
3357
- };
3358
- const handleTextChange = (newValue) => {
3359
- setTextValue(newValue);
3360
- if (isValid(newValue)) onChange?.(newValue);
3361
- };
3362
- const handleClear = () => {
3363
- setTextValue("");
3364
- onChange?.("");
3365
- isValid("");
3366
- };
3367
- const handleInsert = (text) => {
3368
- const newValue = textValue ? `${textValue}${text} ` : `${text} `;
3369
- setTextValue(newValue);
3370
- if (isValid(newValue)) onChange?.(newValue);
3371
- setTimeout(() => {
3372
- inputRef.current?.focus();
3373
- const length = inputRef.current?.value.length || 0;
3374
- inputRef.current?.setSelectionRange(length, length);
3375
- }, 0);
3376
- };
3377
- useEvents({ "form:change": (event) => {
3378
- if (event.id === inputRef.current?.form?.id) {
3379
- if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
3380
- }
3381
- } }, []);
3382
- return /* @__PURE__ */ jsxs(Popover, {
3383
- width: 800,
3384
- position: "bottom-start",
3385
- shadow: "md",
3386
- opened: helpOpened,
3387
- onChange: setHelpOpened,
3388
- closeOnClickOutside: true,
3389
- closeOnEscape: true,
3390
- transitionProps: {
3391
- transition: "fade-up",
3392
- duration: 200,
3393
- timingFunction: "ease"
3394
- },
3395
- children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
3396
- ref: inputRef,
3397
- placeholder,
3398
- value: textValue,
3399
- onChange: (e) => handleTextChange(e.currentTarget.value),
3400
- onFocus: () => setHelpOpened(true),
3401
- leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
3402
- rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
3403
- size: "sm",
3404
- variant: "subtle",
3405
- color: "gray",
3406
- onClick: handleClear,
3407
- children: /* @__PURE__ */ jsx(IconX, { size: 14 })
3408
- }),
3409
- ...textInputProps
3410
- }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
3411
- bg: "transparent",
3412
- p: "xs",
3413
- bd: `1px solid ${ui.colors.border}`,
3414
- style: { backdropFilter: "blur(20px)" },
3415
- children: /* @__PURE__ */ jsx(QueryHelp, {
3416
- fields,
3417
- onInsert: handleInsert
3418
- })
3419
- })]
3420
- });
3421
- };
3422
- function QueryHelp({ fields, onInsert }) {
3293
+ //#region ../../src/core/form/components/ControlQueryBuilderHelp.tsx
3294
+ const ControlQueryBuilderHelp = (props) => {
3295
+ const { fields, onInsert } = props;
3423
3296
  return /* @__PURE__ */ jsxs(Flex, {
3424
3297
  gap: "md",
3425
3298
  align: "flex-start",
@@ -3580,114 +3453,314 @@ function QueryHelp({ fields, onInsert }) {
3580
3453
  }, field.path))
3581
3454
  })]
3582
3455
  })
3583
- ]
3456
+ ]
3457
+ });
3458
+ };
3459
+ //#endregion
3460
+ //#region ../../src/core/form/components/ControlQueryBuilder.tsx
3461
+ /**
3462
+ * Query builder with text input and help popover.
3463
+ * Generates query strings for parseQueryString syntax.
3464
+ */
3465
+ const ControlQueryBuilder = (props) => {
3466
+ const { schema, value = "", onChange, placeholder = "Enter query or click for assistance...", ...textInputProps } = props;
3467
+ const [helpOpened, setHelpOpened] = useState(false);
3468
+ const [textValue, setTextValue] = useState(value);
3469
+ const inputRef = useRef(null);
3470
+ const fields = schema ? extractSchemaFields(schema) : [];
3471
+ const [error, setError] = useState(null);
3472
+ const isValid = (value) => {
3473
+ try {
3474
+ parseQueryString(value.trim());
3475
+ } catch (e) {
3476
+ setError(e.message);
3477
+ return false;
3478
+ }
3479
+ setError(null);
3480
+ return true;
3481
+ };
3482
+ const handleTextChange = (newValue) => {
3483
+ setTextValue(newValue);
3484
+ if (isValid(newValue)) onChange?.(newValue);
3485
+ };
3486
+ const handleClear = () => {
3487
+ setTextValue("");
3488
+ onChange?.("");
3489
+ isValid("");
3490
+ };
3491
+ const handleInsert = (text) => {
3492
+ const newValue = textValue ? `${textValue}${text} ` : `${text} `;
3493
+ setTextValue(newValue);
3494
+ if (isValid(newValue)) onChange?.(newValue);
3495
+ setTimeout(() => {
3496
+ inputRef.current?.focus();
3497
+ const length = inputRef.current?.value.length || 0;
3498
+ inputRef.current?.setSelectionRange(length, length);
3499
+ }, 0);
3500
+ };
3501
+ useEvents({ "form:change": (event) => {
3502
+ if (event.id === inputRef.current?.form?.id) {
3503
+ if (event.path === textInputProps["data-path"]) setTextValue(event.value ?? "");
3504
+ }
3505
+ } }, []);
3506
+ return /* @__PURE__ */ jsxs(Popover, {
3507
+ width: 800,
3508
+ position: "bottom-start",
3509
+ shadow: "md",
3510
+ opened: helpOpened,
3511
+ onChange: setHelpOpened,
3512
+ closeOnClickOutside: true,
3513
+ closeOnEscape: true,
3514
+ transitionProps: {
3515
+ transition: "fade-up",
3516
+ duration: 200,
3517
+ timingFunction: "ease"
3518
+ },
3519
+ children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(TextInput, {
3520
+ ref: inputRef,
3521
+ placeholder,
3522
+ value: textValue,
3523
+ onChange: (e) => handleTextChange(e.currentTarget.value),
3524
+ onFocus: () => setHelpOpened(true),
3525
+ leftSection: error ? /* @__PURE__ */ jsx(IconInfoTriangle, { size: 16 }) : /* @__PURE__ */ jsx(IconFilter, { size: 16 }),
3526
+ rightSection: textValue && /* @__PURE__ */ jsx(ActionIcon, {
3527
+ size: "sm",
3528
+ variant: "subtle",
3529
+ color: "gray",
3530
+ onClick: handleClear,
3531
+ children: /* @__PURE__ */ jsx(IconX, { size: 14 })
3532
+ }),
3533
+ ...textInputProps
3534
+ }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
3535
+ bg: "transparent",
3536
+ p: "xs",
3537
+ bd: `1px solid ${ui.colors.border}`,
3538
+ style: { backdropFilter: "blur(20px)" },
3539
+ children: /* @__PURE__ */ jsx(ControlQueryBuilderHelp, {
3540
+ fields,
3541
+ onInsert: handleInsert
3542
+ })
3543
+ })]
3584
3544
  });
3585
- }
3586
-
3545
+ };
3587
3546
  //#endregion
3588
3547
  //#region ../../src/core/form/components/ControlSelect.tsx
3589
3548
  /**
3590
- * ControlSelect component for handling Select, MultiSelect, and TagsInput.
3549
+ * ControlSelect component for handling Select, MultiSelect, Autocomplete, and TagsInput.
3591
3550
  *
3592
3551
  * Features:
3593
3552
  * - Basic Select with enum support
3594
3553
  * - MultiSelect for array of enums
3595
- * - TagsInput for array of strings (no enum)
3596
- * - Future: Lazy loading
3597
- * - Future: Searchable/filterable options
3598
- * - Future: Custom option rendering
3554
+ * - Autocomplete for creatable single values
3555
+ * - TagsInput for creatable array values
3556
+ * - Async lazy loading with auto short/long mode detection
3557
+ * - Short mode: client-side filtering with cached data
3558
+ * - Long mode: debounced server search
3599
3559
  *
3600
3560
  * Automatically detects enum values and array types from schema.
3601
3561
  */
3602
3562
  const ControlSelect = (props) => {
3603
- const { inputProps, id, icon } = parseInput(props, useFormState(props.input));
3563
+ const form = useFormState(props.input);
3564
+ const [value, setValue] = useFieldValue(props.input);
3565
+ const { inputProps, id, icon } = parseInput(props, form);
3604
3566
  const isArray = props.input.schema && "type" in props.input.schema && props.input.schema.type === "array";
3605
- let itemsEnum;
3606
- if (isArray && "items" in props.input.schema && props.input.schema.items) {
3607
- const items = props.input.schema.items;
3608
- if ("enum" in items && Array.isArray(items.enum)) itemsEnum = items.enum;
3609
- }
3567
+ const isNumeric = props.input.schema && "type" in props.input.schema && (props.input.schema.type === "integer" || props.input.schema.type === "number");
3568
+ const isBoolean = props.input.schema && "type" in props.input.schema && props.input.schema.type === "boolean";
3610
3569
  const enumValues = props.input.schema && "enum" in props.input.schema && Array.isArray(props.input.schema.enum) ? props.input.schema.enum : [];
3611
- const [data, setData] = useState([]);
3570
+ const { data: asyncData, loading, mode, search } = useAsyncLoader(props.loader, props.loaderThreshold ?? 100, props.loaderDebounce ?? 300, props.input.initialValue);
3571
+ const [staticData, setStaticData] = useState([]);
3572
+ const enumKey = JSON.stringify(enumValues);
3612
3573
  useEffect(() => {
3613
- if (!props.input?.props) return;
3614
- if (props.loader) props.loader().then(setData);
3615
- else setData(enumValues);
3616
- }, [props.input, props.loader]);
3574
+ if (!props.input?.props || props.loader) return;
3575
+ if (isBoolean && enumValues.length === 0) setStaticData([{
3576
+ value: "true",
3577
+ label: "True"
3578
+ }, {
3579
+ value: "false",
3580
+ label: "False"
3581
+ }]);
3582
+ else setStaticData(enumValues);
3583
+ }, [
3584
+ props.input,
3585
+ props.loader,
3586
+ enumKey,
3587
+ isBoolean
3588
+ ]);
3589
+ const data = props.loader ? asyncData : staticData;
3617
3590
  if (!props.input?.props) return null;
3618
- if (props.segmented) {
3619
- const segmentedControlProps = typeof props.segmented === "object" ? props.segmented : {};
3591
+ /**
3592
+ * Coerce value for numeric schemas Select values are always strings.
3593
+ */
3594
+ const coerceValue = (val) => {
3595
+ if (val == null) return val;
3596
+ if (isNumeric) return Number(val);
3597
+ if (isBoolean) return val === "true";
3598
+ return val;
3599
+ };
3600
+ if (props.segmentedProps) {
3601
+ const segmentedControlProps = typeof props.segmentedProps === "object" ? props.segmentedProps : {};
3602
+ const segmentedData = segmentedControlProps.data ?? data.slice(0, 10);
3620
3603
  return /* @__PURE__ */ jsx(Input.Wrapper, {
3621
3604
  ...inputProps,
3622
- children: /* @__PURE__ */ jsx(Flex, { children: /* @__PURE__ */ jsx(SegmentedControl, {
3623
- disabled: inputProps.disabled,
3624
- defaultValue: String(props.input.props.defaultValue),
3625
- ...segmentedControlProps,
3626
- onChange: (value) => {
3627
- props.input.set(value);
3628
- },
3629
- data: data.slice(0, 10)
3630
- }) })
3605
+ children: /* @__PURE__ */ jsx(Flex, {
3606
+ my: "calc(var(--mantine-spacing-xs) / 2)",
3607
+ children: /* @__PURE__ */ jsx(SegmentedControl, {
3608
+ disabled: inputProps.disabled,
3609
+ value: value != null ? String(value) : "",
3610
+ ...segmentedControlProps,
3611
+ onChange: (val) => {
3612
+ setValue(coerceValue(val));
3613
+ },
3614
+ data: segmentedData
3615
+ })
3616
+ })
3631
3617
  });
3632
3618
  }
3633
- if (props.autocomplete) {
3634
- const autocompleteProps = typeof props.autocomplete === "object" ? props.autocomplete : {};
3635
- return /* @__PURE__ */ jsx(Autocomplete, {
3619
+ const sharedProps = {
3620
+ size: props.size,
3621
+ id,
3622
+ leftSection: loading ? /* @__PURE__ */ jsx(Loader, {
3623
+ color: "gray",
3624
+ size: 10
3625
+ }) : icon,
3626
+ data
3627
+ };
3628
+ const selectableProps = {
3629
+ ...sharedProps,
3630
+ searchable: true,
3631
+ rightSection: /* @__PURE__ */ jsx("span", {})
3632
+ };
3633
+ const longModeProps = mode === "long" ? {
3634
+ filter: ({ options }) => options,
3635
+ onSearchChange: search.run
3636
+ } : {};
3637
+ if (props.creatable && (isArray || props.tagsInputProps)) {
3638
+ const tagsInputExtraProps = props.tagsInputProps ?? {};
3639
+ return /* @__PURE__ */ jsx(TagsInput, {
3636
3640
  ...inputProps,
3637
- size: props.size,
3638
- id,
3639
- leftSection: icon,
3640
- data,
3641
- ...props.input.props,
3642
- ...autocompleteProps
3641
+ ...sharedProps,
3642
+ ...longModeProps,
3643
+ value: Array.isArray(value) ? value : [],
3644
+ onChange: (val) => {
3645
+ setValue(val);
3646
+ },
3647
+ ...tagsInputExtraProps
3643
3648
  });
3644
3649
  }
3645
- if (isArray && !itemsEnum || props.tags) {
3646
- const tagsInputProps = typeof props.tags === "object" ? props.tags : {};
3647
- return /* @__PURE__ */ jsx(TagsInput, {
3650
+ if (props.creatable) {
3651
+ const autocompleteExtraProps = props.autocompleteProps ?? {};
3652
+ return /* @__PURE__ */ jsx(Autocomplete, {
3648
3653
  ...inputProps,
3649
- size: props.size,
3650
- id,
3651
- leftSection: icon,
3652
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
3653
- onChange: (value) => {
3654
- props.input.set(value);
3654
+ ...sharedProps,
3655
+ ...longModeProps,
3656
+ value: value != null ? String(value) : "",
3657
+ onChange: (val) => {
3658
+ setValue(coerceValue(val));
3655
3659
  },
3656
- ...tagsInputProps
3660
+ ...autocompleteExtraProps
3657
3661
  });
3658
3662
  }
3659
- if (isArray && itemsEnum || props.multi) {
3660
- const data = itemsEnum?.map((value) => ({
3661
- value,
3662
- label: value
3663
- })) || [];
3664
- const multiSelectProps = typeof props.multi === "object" ? props.multi : {};
3663
+ if (isArray || props.multiSelectProps) {
3664
+ const multiSelectExtraProps = typeof props.multiSelectProps === "object" ? props.multiSelectProps : {};
3665
3665
  return /* @__PURE__ */ jsx(MultiSelect, {
3666
3666
  ...inputProps,
3667
- size: props.size,
3668
- id,
3669
- leftSection: icon,
3670
- data,
3671
- defaultValue: Array.isArray(props.input.props.defaultValue) ? props.input.props.defaultValue : [],
3672
- onChange: (value) => {
3673
- props.input.set(value);
3667
+ ...selectableProps,
3668
+ ...longModeProps,
3669
+ value: Array.isArray(value) ? value : [],
3670
+ onChange: (val) => {
3671
+ setValue(val);
3674
3672
  },
3675
- ...multiSelectProps
3673
+ ...multiSelectExtraProps
3676
3674
  });
3677
3675
  }
3678
- const selectProps = typeof props.select === "object" ? props.select : {};
3676
+ const selectExtraProps = typeof props.selectProps === "object" ? props.selectProps : {};
3677
+ if (mode === "static") return /* @__PURE__ */ jsx(Select, {
3678
+ ...inputProps,
3679
+ ...selectableProps,
3680
+ value: value != null ? String(value) : null,
3681
+ onChange: (val) => {
3682
+ setValue(coerceValue(val));
3683
+ },
3684
+ ...selectExtraProps
3685
+ });
3679
3686
  return /* @__PURE__ */ jsx(Select, {
3680
3687
  ...inputProps,
3681
- size: props.size,
3682
- id,
3683
- leftSection: icon,
3684
- rightSection: null,
3685
- data,
3686
- ...props.input.props,
3687
- ...selectProps
3688
+ ...selectableProps,
3689
+ ...longModeProps,
3690
+ value: value != null ? String(value) : null,
3691
+ onChange: (val) => {
3692
+ setValue(coerceValue(val));
3693
+ },
3694
+ ...selectExtraProps
3688
3695
  });
3689
3696
  };
3690
-
3697
+ /**
3698
+ * Hook for async select data loading with auto short/long mode detection.
3699
+ */
3700
+ const useAsyncLoader = (loader, threshold, debounceMs, defaultValue) => {
3701
+ const [data, setData] = useState([]);
3702
+ const [loading, setLoading] = useState(false);
3703
+ const [mode, setMode] = useState("static");
3704
+ const cache = useRef(/* @__PURE__ */ new Map());
3705
+ useAction({
3706
+ name: "select:loader:init",
3707
+ runOnInit: true,
3708
+ handler: async () => {
3709
+ if (!loader) {
3710
+ setMode("static");
3711
+ return;
3712
+ }
3713
+ setLoading(true);
3714
+ try {
3715
+ const result = await loader("");
3716
+ const isShort = result.length <= threshold;
3717
+ setMode(isShort ? "short" : "long");
3718
+ cache.current.set("", result);
3719
+ setData(result);
3720
+ if (!isShort && defaultValue != null && String(defaultValue) !== "") {
3721
+ const resolved = await loader("", [String(defaultValue)]);
3722
+ if (resolved.length > 0) setData((prev) => {
3723
+ const existing = new Set(prev.map((d) => typeof d === "string" ? d : d.value));
3724
+ const newItems = resolved.filter((r) => {
3725
+ const val = typeof r === "string" ? r : r.value;
3726
+ return !existing.has(val);
3727
+ });
3728
+ return [...prev, ...newItems];
3729
+ });
3730
+ }
3731
+ } finally {
3732
+ setLoading(false);
3733
+ }
3734
+ }
3735
+ }, [loader, threshold]);
3736
+ return {
3737
+ data,
3738
+ loading,
3739
+ mode,
3740
+ search: useAction({
3741
+ debounce: debounceMs,
3742
+ handler: async (text) => {
3743
+ if (!loader || mode !== "long") return;
3744
+ if (cache.current.has(text)) {
3745
+ setData(cache.current.get(text));
3746
+ return;
3747
+ }
3748
+ setLoading(true);
3749
+ try {
3750
+ const result = await loader(text);
3751
+ cache.current.set(text, result);
3752
+ setData(result);
3753
+ } finally {
3754
+ setLoading(false);
3755
+ }
3756
+ }
3757
+ }, [
3758
+ loader,
3759
+ mode,
3760
+ debounceMs
3761
+ ])
3762
+ };
3763
+ };
3691
3764
  //#endregion
3692
3765
  //#region ../../src/core/form/components/Control.tsx
3693
3766
  /**
@@ -3716,6 +3789,7 @@ const ControlSelect = (props) => {
3716
3789
  */
3717
3790
  const Control = (_props) => {
3718
3791
  const form = useFormState(_props.input, ["error"]);
3792
+ const [value, setValue] = useFieldValue(_props.input);
3719
3793
  if (!_props.input?.props) return null;
3720
3794
  const { inputProps, id, icon, format, schema } = parseInput(_props, form);
3721
3795
  const props = {
@@ -3723,12 +3797,11 @@ const Control = (_props) => {
3723
3797
  ...schema.$control
3724
3798
  };
3725
3799
  if (props.query) return /* @__PURE__ */ jsx(ControlQueryBuilder, {
3726
- ...props.input.props,
3727
3800
  ...inputProps,
3728
3801
  schema: props.query,
3729
- value: props.input.props.value,
3730
- onChange: (value) => {
3731
- props.input.set(value);
3802
+ value,
3803
+ onChange: (val) => {
3804
+ setValue(val);
3732
3805
  }
3733
3806
  });
3734
3807
  if (props.custom) {
@@ -3739,9 +3812,9 @@ const Control = (_props) => {
3739
3812
  flex: 1,
3740
3813
  mt: "calc(var(--mantine-spacing-xs) / 2)",
3741
3814
  children: /* @__PURE__ */ jsx(Custom, {
3742
- defaultValue: props.input.props.defaultValue,
3743
- onChange: (value) => {
3744
- props.input.set(value);
3815
+ value,
3816
+ onChange: (val) => {
3817
+ setValue(val);
3745
3818
  }
3746
3819
  })
3747
3820
  })
@@ -3752,7 +3825,7 @@ const Control = (_props) => {
3752
3825
  const controlObjectProps = typeof props.object === "object" ? props.object : {};
3753
3826
  return /* @__PURE__ */ jsx(ControlObject, {
3754
3827
  input: props.input,
3755
- title: props.title,
3828
+ label: props.label,
3756
3829
  description: props.description,
3757
3830
  ...controlObjectProps
3758
3831
  });
@@ -3763,18 +3836,18 @@ const Control = (_props) => {
3763
3836
  const controlArrayProps = typeof props.array === "object" ? props.array : {};
3764
3837
  return /* @__PURE__ */ jsx(ControlArray, {
3765
3838
  input: props.input,
3766
- title: props.title,
3839
+ label: props.label,
3767
3840
  description: props.description,
3768
3841
  ...controlArrayProps
3769
3842
  });
3770
3843
  }
3771
- if (props.number || props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
3844
+ if (props.number || !props.select && props.input.schema && "type" in props.input.schema && (props.input.schema.type === "number" || props.input.schema.type === "integer")) {
3772
3845
  const controlNumberProps = typeof props.number === "object" ? props.number : {};
3773
3846
  if (props.slider) controlNumberProps.sliderProps ??= {};
3774
3847
  return /* @__PURE__ */ jsx(ControlNumber, {
3775
3848
  size: props.size,
3776
3849
  input: props.input,
3777
- title: props.title,
3850
+ label: props.label,
3778
3851
  description: props.description,
3779
3852
  icon,
3780
3853
  ...controlNumberProps
@@ -3787,9 +3860,7 @@ const Control = (_props) => {
3787
3860
  size: props.size,
3788
3861
  id,
3789
3862
  leftSection: icon,
3790
- onChange: (file) => {
3791
- props.input.set(file);
3792
- },
3863
+ onChange: (file) => setValue(file),
3793
3864
  ...fileInputProps
3794
3865
  });
3795
3866
  }
@@ -3800,17 +3871,18 @@ const Control = (_props) => {
3800
3871
  size: props.size,
3801
3872
  id,
3802
3873
  leftSection: icon,
3803
- ...props.input.props,
3874
+ value: value ?? "",
3875
+ onChange: (val) => setValue(val),
3804
3876
  ...colorInputProps
3805
3877
  });
3806
3878
  }
3807
3879
  if (props.input.schema && "enum" in props.input.schema && props.input.schema.enum || isArray && !isArrayOfObjects || props.select) {
3808
3880
  const opts = typeof props.select === "object" ? props.select : {};
3809
- if (props.segmented) opts.segmented ??= {};
3881
+ if (props.segmented) opts.segmentedProps ??= {};
3810
3882
  return /* @__PURE__ */ jsx(ControlSelect, {
3811
3883
  size: props.size,
3812
3884
  input: props.input,
3813
- title: props.title,
3885
+ label: props.label,
3814
3886
  description: props.description,
3815
3887
  icon,
3816
3888
  ...opts
@@ -3824,16 +3896,16 @@ const Control = (_props) => {
3824
3896
  size: props.size,
3825
3897
  id,
3826
3898
  color: "blue",
3827
- defaultChecked: props.input.props.defaultValue,
3899
+ checked: Boolean(value),
3828
3900
  onChange: (event) => {
3829
- props.input.set(event.currentTarget.checked);
3901
+ setValue(event.currentTarget.checked);
3830
3902
  },
3831
3903
  ...switchProps
3832
3904
  });
3833
3905
  }
3834
3906
  const opts = {
3835
3907
  input: props.input,
3836
- select: { data: [{
3908
+ selectProps: { data: [{
3837
3909
  value: "true",
3838
3910
  label: "Yes"
3839
3911
  }, {
@@ -3843,7 +3915,7 @@ const Control = (_props) => {
3843
3915
  };
3844
3916
  return /* @__PURE__ */ jsx(ControlSelect, {
3845
3917
  size: props.size,
3846
- title: props.title,
3918
+ label: props.label,
3847
3919
  description: props.description,
3848
3920
  icon,
3849
3921
  ...opts
@@ -3856,7 +3928,8 @@ const Control = (_props) => {
3856
3928
  size: props.size,
3857
3929
  id,
3858
3930
  leftSection: icon,
3859
- ...props.input.props,
3931
+ value: value ?? "",
3932
+ onChange: (ev) => setValue(ev.target.value),
3860
3933
  ...passwordInputProps
3861
3934
  });
3862
3935
  }
@@ -3867,14 +3940,15 @@ const Control = (_props) => {
3867
3940
  size: props.size,
3868
3941
  id,
3869
3942
  leftSection: icon,
3870
- ...props.input.props,
3943
+ value: value ?? "",
3944
+ onChange: (ev) => setValue(ev.target.value),
3871
3945
  ...textAreaProps
3872
3946
  });
3873
3947
  }
3874
3948
  if (props.date || props.datetime || props.time || format === "date" || format === "date-time" || format === "time") return /* @__PURE__ */ jsx(ControlDate, {
3875
3949
  size: props.size,
3876
3950
  input: props.input,
3877
- title: props.title,
3951
+ label: props.label,
3878
3952
  description: props.description,
3879
3953
  icon,
3880
3954
  date: props.date,
@@ -3889,7 +3963,7 @@ const Control = (_props) => {
3889
3963
  case "uri": return "url";
3890
3964
  case "tel":
3891
3965
  case "phone": return "tel";
3892
- default: return;
3966
+ default: return props.input.props.type ?? "text";
3893
3967
  }
3894
3968
  };
3895
3969
  return /* @__PURE__ */ jsx(TextInput, {
@@ -3898,17 +3972,11 @@ const Control = (_props) => {
3898
3972
  id,
3899
3973
  leftSection: icon,
3900
3974
  type: getInputType(),
3901
- ...props.input.props,
3902
- ...textInputProps,
3903
- inputWrapperOrder: [
3904
- "label",
3905
- "input",
3906
- "description",
3907
- "error"
3908
- ]
3975
+ value: value ?? "",
3976
+ onChange: (ev) => setValue(ev.target.value),
3977
+ ...textInputProps
3909
3978
  });
3910
3979
  };
3911
-
3912
3980
  //#endregion
3913
3981
  //#region ../../src/core/form/components/TypeForm.tsx
3914
3982
  /**
@@ -3954,6 +4022,7 @@ const Control = (_props) => {
3954
4022
  */
3955
4023
  const TypeForm = (props) => {
3956
4024
  const { form, columns = 3, children, controlProps, fieldControlProps, skipFormElement = false, skipSubmitButton = false, submitButtonProps, fill = true, size } = props;
4025
+ const { dirty } = useFormState(form, ["dirty"]);
3957
4026
  const schema = props.schema || form.options.schema;
3958
4027
  if (!schema?.properties) return null;
3959
4028
  const supportedFields = Object.keys(schema.properties);
@@ -4016,10 +4085,12 @@ const TypeForm = (props) => {
4016
4085
  children: [/* @__PURE__ */ jsx(ActionButton, {
4017
4086
  variant: "subtle",
4018
4087
  type: "reset",
4088
+ disabled: !dirty,
4019
4089
  children: "Reset"
4020
4090
  }), /* @__PURE__ */ jsx(ActionButton, {
4021
4091
  intent: "primary",
4022
4092
  form,
4093
+ disabled: !dirty,
4023
4094
  ...submitButtonProps,
4024
4095
  children: submitButtonProps?.children ?? "Submit"
4025
4096
  })]
@@ -4037,18 +4108,27 @@ const TypeForm = (props) => {
4037
4108
  children: content
4038
4109
  });
4039
4110
  };
4040
-
4041
4111
  //#endregion
4042
- //#region ../../src/core/helpers/renderIcon.tsx
4043
- const renderIcon = (icon, size) => {
4044
- if (!icon) return null;
4045
- if (isValidElement(icon)) return icon;
4046
- if (isComponentType(icon)) return /* @__PURE__ */ jsx(icon, { size: size ?? ui.sizes.icon.md });
4047
- return icon;
4112
+ //#region ../../src/core/json/components/JsonViewerCopyButton.tsx
4113
+ const JsonViewerCopyButton = (props) => {
4114
+ const [copied, setCopied] = useState(false);
4115
+ const handleCopy = useCallback((e) => {
4116
+ e.stopPropagation();
4117
+ navigator.clipboard.writeText(props.value);
4118
+ setCopied(true);
4119
+ setTimeout(() => setCopied(false), 1500);
4120
+ }, [props.value]);
4121
+ return /* @__PURE__ */ jsx(ActionIcon, {
4122
+ size: props.iconSize + 4,
4123
+ variant: "transparent",
4124
+ c: copied ? "green" : "dimmed",
4125
+ onClick: handleCopy,
4126
+ className: "alepha-json-viewer-copy",
4127
+ children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: props.iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: props.iconSize })
4128
+ });
4048
4129
  };
4049
-
4050
4130
  //#endregion
4051
- //#region ../../src/core/json/components/JsonViewer.tsx
4131
+ //#region ../../src/core/json/components/JsonViewerShared.ts
4052
4132
  const SIZE_CONFIG = {
4053
4133
  xs: {
4054
4134
  icon: 14,
@@ -4097,77 +4177,20 @@ const getValueType = (val) => {
4097
4177
  if (Array.isArray(val)) return "array";
4098
4178
  return typeof val;
4099
4179
  };
4100
- function buildTreeNodes(data, path = [], key, isArrayItem = false, maxDepth = 10) {
4101
- const currentPath = key !== void 0 ? [...path, key] : path;
4102
- const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
4103
- if (currentPath.length > maxDepth) return {
4104
- value: nodeId,
4105
- label: key ?? "",
4106
- nodeValue: data,
4107
- nodeKey: key,
4108
- path: currentPath,
4109
- isArrayItem
4110
- };
4111
- const type = getValueType(data);
4112
- if (type === "object" || type === "array") {
4113
- 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);
4114
- return {
4115
- value: nodeId,
4116
- label: key ?? "",
4117
- nodeValue: data,
4118
- nodeKey: key,
4119
- path: currentPath,
4120
- isArrayItem,
4121
- children: children.length > 0 ? children : void 0
4122
- };
4123
- }
4124
- return {
4125
- value: nodeId,
4126
- label: key ?? "",
4127
- nodeValue: data,
4128
- nodeKey: key,
4129
- path: currentPath,
4130
- isArrayItem
4131
- };
4132
- }
4133
- function getExpandedIds(nodes, targetDepth, currentDepth = 0) {
4134
- if (currentDepth >= targetDepth) return [];
4135
- const ids = [];
4136
- for (const node of nodes) if (node.children) {
4137
- ids.push(node.value);
4138
- ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
4139
- }
4140
- return ids;
4141
- }
4142
- const CopyButton = ({ value, iconSize }) => {
4143
- const [copied, setCopied] = useState(false);
4144
- const handleCopy = useCallback((e) => {
4145
- e.stopPropagation();
4146
- navigator.clipboard.writeText(value);
4147
- setCopied(true);
4148
- setTimeout(() => setCopied(false), 1500);
4149
- }, [value]);
4150
- return /* @__PURE__ */ jsx(ActionIcon, {
4151
- size: iconSize + 4,
4152
- variant: "transparent",
4153
- c: copied ? "green" : "dimmed",
4154
- onClick: handleCopy,
4155
- className: "alepha-json-viewer-copy",
4156
- children: copied ? /* @__PURE__ */ jsx(IconCheck, { size: iconSize }) : /* @__PURE__ */ jsx(IconCopy, { size: iconSize })
4157
- });
4158
- };
4159
- const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, showQuotes, showCopyButton, renderValue }) => {
4160
- const { nodeValue, nodeKey, path, isArrayItem, isRoot } = node;
4180
+ //#endregion
4181
+ //#region ../../src/core/json/components/JsonViewerRowNode.tsx
4182
+ const JsonViewerRowNode = (props) => {
4183
+ const { nodeValue, nodeKey, path, isArrayItem } = props.node;
4161
4184
  const type = getValueType(nodeValue);
4162
4185
  const isExpandable = type === "object" || type === "array";
4163
4186
  const getPreview = () => {
4164
4187
  if (!isExpandable) return null;
4165
4188
  const count = (type === "array" ? nodeValue : Object.keys(nodeValue)).length;
4166
4189
  const label = type === "array" ? "item" : "key";
4167
- if (!expanded) return /* @__PURE__ */ jsx(Text, {
4190
+ if (!props.expanded) return /* @__PURE__ */ jsx(Text, {
4168
4191
  fs: "italic",
4169
4192
  component: "span",
4170
- size,
4193
+ size: props.size,
4171
4194
  style: STYLES.preview,
4172
4195
  children: count === 0 ? type === "array" ? "[]" : "{}" : type === "array" ? `[ ${count} ${count === 1 ? label : `${label}s`} ]` : `{ ${count} ${count === 1 ? label : `${label}s`} }`
4173
4196
  });
@@ -4177,25 +4200,25 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4177
4200
  return /* @__PURE__ */ jsxs(Flex, {
4178
4201
  gap: 6,
4179
4202
  wrap: "nowrap",
4180
- ...elementProps,
4181
- className: `alepha-json-viewer-row ${elementProps.className || ""}`,
4203
+ ...props.elementProps,
4204
+ className: `alepha-json-viewer-row ${props.elementProps.className || ""}`,
4182
4205
  children: [
4183
- hasChildren ? expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
4184
- size: config.icon,
4206
+ props.hasChildren ? props.expanded ? /* @__PURE__ */ jsx(IconChevronDown, {
4207
+ size: props.config.icon,
4185
4208
  style: STYLES.chevron
4186
4209
  }) : /* @__PURE__ */ jsx(IconChevronRight, {
4187
- size: config.icon,
4210
+ size: props.config.icon,
4188
4211
  style: STYLES.chevron
4189
4212
  }) : /* @__PURE__ */ jsx("span", { style: {
4190
- width: config.icon,
4213
+ width: props.config.icon,
4191
4214
  flexShrink: 0
4192
4215
  } }),
4193
4216
  nodeKey !== void 0 && !isArrayItem && /* @__PURE__ */ jsxs(Text, {
4194
4217
  component: "span",
4195
- size,
4218
+ size: props.size,
4196
4219
  children: [/* @__PURE__ */ jsx("span", {
4197
4220
  style: STYLES.key,
4198
- children: showQuotes ? `"${nodeKey}"` : nodeKey
4221
+ children: props.showQuotes ? `"${nodeKey}"` : nodeKey
4199
4222
  }), /* @__PURE__ */ jsx("span", {
4200
4223
  style: STYLES.colon,
4201
4224
  children: ":"
@@ -4203,7 +4226,7 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4203
4226
  }),
4204
4227
  nodeKey !== void 0 && isArrayItem && /* @__PURE__ */ jsxs(Text, {
4205
4228
  component: "span",
4206
- size,
4229
+ size: props.size,
4207
4230
  children: [/* @__PURE__ */ jsx("span", {
4208
4231
  style: STYLES.key,
4209
4232
  children: nodeKey
@@ -4212,25 +4235,28 @@ const RowNode = ({ node, expanded, hasChildren, elementProps, size, config, show
4212
4235
  children: ":"
4213
4236
  })]
4214
4237
  }),
4215
- hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text, {
4238
+ props.hasChildren ? getPreview() : isExpandable ? type === "array" ? /* @__PURE__ */ jsx(Text, {
4216
4239
  component: "span",
4217
- size,
4240
+ size: props.size,
4218
4241
  style: STYLES.preview,
4219
4242
  children: "[]"
4220
4243
  }) : /* @__PURE__ */ jsx(Text, {
4221
4244
  component: "span",
4222
- size,
4245
+ size: props.size,
4223
4246
  style: STYLES.preview,
4224
4247
  children: "{}"
4225
- }) : renderValue(nodeValue, nodeKey, path),
4226
- showCopyButton && /* @__PURE__ */ jsx(CopyButton, {
4248
+ }) : props.renderValue(nodeValue, nodeKey, path),
4249
+ props.showCopyButton && /* @__PURE__ */ jsx(JsonViewerCopyButton, {
4227
4250
  value: getCopyValue(),
4228
- iconSize: config.icon
4251
+ iconSize: props.config.icon
4229
4252
  })
4230
4253
  ]
4231
4254
  });
4232
4255
  };
4233
- const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue }) => {
4256
+ //#endregion
4257
+ //#region ../../src/core/json/components/JsonViewer.tsx
4258
+ const JsonViewer = (props) => {
4259
+ const { data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm", showQuotes = false, showCopyButton = true, formatValue } = props;
4234
4260
  const config = SIZE_CONFIG[size] || SIZE_CONFIG.sm;
4235
4261
  const treeData = useMemo(() => {
4236
4262
  const type = getValueType(data);
@@ -4310,7 +4336,7 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
4310
4336
  size
4311
4337
  ]);
4312
4338
  const renderNode = useCallback(({ node, expanded, hasChildren, elementProps }) => {
4313
- return /* @__PURE__ */ jsx(RowNode, {
4339
+ return /* @__PURE__ */ jsx(JsonViewerRowNode, {
4314
4340
  node,
4315
4341
  expanded,
4316
4342
  hasChildren,
@@ -4342,14 +4368,58 @@ const JsonViewer = ({ data, defaultExpandedDepth = 2, maxDepth = 10, size = "sm"
4342
4368
  styles: { root: STYLES.root }
4343
4369
  });
4344
4370
  };
4345
-
4346
- //#endregion
4347
- //#region ../../src/core/table/interfaces/types.ts
4348
- const DEFAULT_MAX_VISIBLE_COLUMNS = 8;
4349
-
4371
+ /**
4372
+ * Convert JSON to tree data structure.
4373
+ */
4374
+ const buildTreeNodes = (data, path = [], key, isArrayItem = false, maxDepth = 10) => {
4375
+ const currentPath = key !== void 0 ? [...path, key] : path;
4376
+ const nodeId = currentPath.length > 0 ? currentPath.join(".") : "root";
4377
+ if (currentPath.length > maxDepth) return {
4378
+ value: nodeId,
4379
+ label: key ?? "",
4380
+ nodeValue: data,
4381
+ nodeKey: key,
4382
+ path: currentPath,
4383
+ isArrayItem
4384
+ };
4385
+ const type = getValueType(data);
4386
+ if (type === "object" || type === "array") {
4387
+ 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);
4388
+ return {
4389
+ value: nodeId,
4390
+ label: key ?? "",
4391
+ nodeValue: data,
4392
+ nodeKey: key,
4393
+ path: currentPath,
4394
+ isArrayItem,
4395
+ children: children.length > 0 ? children : void 0
4396
+ };
4397
+ }
4398
+ return {
4399
+ value: nodeId,
4400
+ label: key ?? "",
4401
+ nodeValue: data,
4402
+ nodeKey: key,
4403
+ path: currentPath,
4404
+ isArrayItem
4405
+ };
4406
+ };
4407
+ /**
4408
+ * Get all expandable node IDs up to a certain depth.
4409
+ */
4410
+ const getExpandedIds = (nodes, targetDepth, currentDepth = 0) => {
4411
+ if (currentDepth >= targetDepth) return [];
4412
+ const ids = [];
4413
+ for (const node of nodes) if (node.children) {
4414
+ ids.push(node.value);
4415
+ ids.push(...getExpandedIds(node.children, targetDepth, currentDepth + 1));
4416
+ }
4417
+ return ids;
4418
+ };
4350
4419
  //#endregion
4351
4420
  //#region ../../src/core/table/components/DataTableFilters.tsx
4352
- const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) => {
4421
+ const DataTableFilters = (props) => {
4422
+ const { schema, form, typeFormProps, filterVisibility } = props;
4353
4423
  const visibleSchema = useMemo(() => {
4354
4424
  const visibleKeys = Object.keys(schema.properties).filter((key) => filterVisibility[key] !== false);
4355
4425
  if (visibleKeys.length === 0) return null;
@@ -4360,14 +4430,14 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
4360
4430
  return t.object(visibleProps);
4361
4431
  }, [schema, filterVisibility]);
4362
4432
  if (!visibleSchema) return null;
4363
- return /* @__PURE__ */ jsx(Flex, {
4364
- w: "100%",
4433
+ return /* @__PURE__ */ jsx(Flex$1, {
4434
+ surface: true,
4435
+ flex: 1,
4436
+ mt: -4,
4365
4437
  p: "xs",
4366
4438
  m: "xs",
4367
4439
  bdrs: "md",
4368
- bg: ui.colors.surface,
4369
4440
  children: /* @__PURE__ */ jsx(TypeForm, {
4370
- size: "xs",
4371
4441
  ...typeFormProps,
4372
4442
  skipSubmitButton: true,
4373
4443
  fill: true,
@@ -4378,17 +4448,17 @@ const DataTableFilters = ({ schema, form, typeFormProps, filterVisibility }) =>
4378
4448
  sm: 2,
4379
4449
  md: 3,
4380
4450
  lg: 4,
4381
- xl: 6
4451
+ xl: 5
4382
4452
  }
4383
4453
  })
4384
4454
  });
4385
4455
  };
4386
-
4387
4456
  //#endregion
4388
4457
  //#region ../../src/core/table/components/DataTablePagination.tsx
4389
- const DataTablePagination = ({ page, size, totalPages, totalElements, offset, numberOfElements, onPageChange, onSizeChange }) => {
4458
+ const DataTablePagination = ({ page, size, totalPages, totalElements, isFirst, isLast, offset, numberOfElements, onPageChange, onSizeChange }) => {
4390
4459
  const from = numberOfElements > 0 ? offset + 1 : 0;
4391
4460
  const to = offset + numberOfElements;
4461
+ const hasTotal = totalPages != null;
4392
4462
  return /* @__PURE__ */ jsxs(Flex$1, {
4393
4463
  align: "center",
4394
4464
  justify: "space-between",
@@ -4436,15 +4506,15 @@ const DataTablePagination = ({ page, size, totalPages, totalElements, offset, nu
4436
4506
  ]
4437
4507
  }) }), /* @__PURE__ */ jsx(Flex$1, { children: /* @__PURE__ */ jsx(Pagination, {
4438
4508
  size: "sm",
4439
- withEdges: true,
4440
- total: totalPages,
4509
+ withEdges: hasTotal,
4510
+ withPages: hasTotal,
4511
+ total: hasTotal ? totalPages : isLast !== false ? page : page + 1,
4441
4512
  value: page,
4442
4513
  onChange: onPageChange
4443
4514
  }) })]
4444
4515
  })]
4445
4516
  });
4446
4517
  };
4447
-
4448
4518
  //#endregion
4449
4519
  //#region ../../src/core/table/components/ColumnPicker.tsx
4450
4520
  const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
@@ -4460,7 +4530,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4460
4530
  let count = 0;
4461
4531
  onVisibilityChange(columnEntries.reduce((acc, [key, col]) => {
4462
4532
  if (col.defaultHidden) acc[key] = false;
4463
- else if (count < DEFAULT_MAX_VISIBLE_COLUMNS) {
4533
+ else if (count < 8) {
4464
4534
  acc[key] = true;
4465
4535
  count++;
4466
4536
  } else acc[key] = false;
@@ -4488,7 +4558,7 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4488
4558
  timingFunction: "ease"
4489
4559
  },
4490
4560
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
4491
- variant: "subtle",
4561
+ variant: "minimal",
4492
4562
  icon: IconColumns,
4493
4563
  onClick: () => setOpened((o) => !o)
4494
4564
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -4518,12 +4588,12 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4518
4588
  gap: 4,
4519
4589
  children: [/* @__PURE__ */ jsx(ActionButton, {
4520
4590
  size: "compact-xs",
4521
- variant: "subtle",
4591
+ variant: "minimal",
4522
4592
  onClick: handleShowAll,
4523
4593
  children: "All"
4524
4594
  }), /* @__PURE__ */ jsx(ActionButton, {
4525
4595
  size: "compact-xs",
4526
- variant: "subtle",
4596
+ variant: "minimal",
4527
4597
  onClick: handleDefault,
4528
4598
  children: "Default"
4529
4599
  })]
@@ -4545,7 +4615,6 @@ const ColumnPicker = ({ columns, visibility, onVisibilityChange }) => {
4545
4615
  })]
4546
4616
  });
4547
4617
  };
4548
-
4549
4618
  //#endregion
4550
4619
  //#region ../../src/core/table/components/FilterPicker.tsx
4551
4620
  const getFieldLabel = (schema, key) => {
@@ -4589,7 +4658,7 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4589
4658
  timingFunction: "ease"
4590
4659
  },
4591
4660
  children: [/* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ActionButton, {
4592
- variant: "subtle",
4661
+ variant: "minimal",
4593
4662
  icon: IconFilter,
4594
4663
  onClick: () => setOpened((o) => !o)
4595
4664
  }) }) }), /* @__PURE__ */ jsx(Popover.Dropdown, {
@@ -4619,12 +4688,12 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4619
4688
  gap: 4,
4620
4689
  children: [/* @__PURE__ */ jsx(ActionButton, {
4621
4690
  size: "compact-xs",
4622
- variant: "subtle",
4691
+ variant: "minimal",
4623
4692
  onClick: handleShowAll,
4624
4693
  children: "All"
4625
4694
  }), /* @__PURE__ */ jsx(ActionButton, {
4626
4695
  size: "compact-xs",
4627
- variant: "subtle",
4696
+ variant: "minimal",
4628
4697
  onClick: handleHideAll,
4629
4698
  children: "None"
4630
4699
  })]
@@ -4646,7 +4715,6 @@ const FilterPicker = ({ schema, visibility, onVisibilityChange }) => {
4646
4715
  })]
4647
4716
  });
4648
4717
  };
4649
-
4650
4718
  //#endregion
4651
4719
  //#region ../../src/core/table/components/DataTableToolbar.tsx
4652
4720
  const escapeCsvField = (value) => {
@@ -4718,7 +4786,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4718
4786
  onVisibilityChange: onColumnVisibilityChange
4719
4787
  }),
4720
4788
  withExport && /* @__PURE__ */ jsx(ActionButton, {
4721
- variant: "subtle",
4789
+ variant: "minimal",
4722
4790
  icon: IconDownload,
4723
4791
  menu: { items: [{
4724
4792
  label: "Export as CSV",
@@ -4741,7 +4809,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4741
4809
  children: [selectedItems.length, " selected"]
4742
4810
  }),
4743
4811
  /* @__PURE__ */ jsx(ActionButton, {
4744
- variant: "subtle",
4812
+ variant: "minimal",
4745
4813
  size: "compact-sm",
4746
4814
  icon: IconX,
4747
4815
  onClick: onClearSelection,
@@ -4765,7 +4833,7 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4765
4833
  ...props,
4766
4834
  children: props.label
4767
4835
  }, index) : props), /* @__PURE__ */ jsx(ActionButton, {
4768
- variant: "subtle",
4836
+ variant: "minimal",
4769
4837
  icon: IconRefresh,
4770
4838
  onClick: onRefresh
4771
4839
  })]
@@ -4773,7 +4841,6 @@ const DataTableToolbar = ({ columns, filters, columnVisibility, filterVisibility
4773
4841
  ]
4774
4842
  });
4775
4843
  };
4776
-
4777
4844
  //#endregion
4778
4845
  //#region ../../src/core/table/components/useTableSelection.ts
4779
4846
  const useTableSelection = (items, getItemKey, enabled) => {
@@ -4836,7 +4903,6 @@ const useTableSelection = (items, getItemKey, enabled) => {
4836
4903
  isSelected: useCallback((item) => selectedKeys.has(getItemKey(item)), [selectedKeys, getItemKey])
4837
4904
  };
4838
4905
  };
4839
-
4840
4906
  //#endregion
4841
4907
  //#region ../../src/core/table/components/DataTable.tsx
4842
4908
  /**
@@ -4874,18 +4940,22 @@ const FIT_STYLE = {
4874
4940
  };
4875
4941
  const DataTable = (props) => {
4876
4942
  const [items, setItems] = useState(typeof props.items === "function" ? { content: [] } : props.items);
4877
- const defaultSize = props.infinityScroll ? 100 : props.defaultSize || 10;
4943
+ const itemsRef = useRef(items);
4944
+ const [loaded, setLoaded] = useState(typeof props.items !== "function" || !props.submitOnInit);
4945
+ const defaultSize = props.defaultSize || (props.infinityScroll ? 100 : 10);
4878
4946
  const [page, setPage] = useState(1);
4879
4947
  const [size, setSize] = useState(String(defaultSize));
4880
4948
  const [currentPage, setCurrentPage] = useState(0);
4881
4949
  const alepha = useInject(Alepha);
4950
+ itemsRef.current = items;
4882
4951
  const sentinelRef = useRef(null);
4952
+ const debounceRef = useRef(null);
4883
4953
  const [columnVisibility, setColumnVisibility] = useState(() => {
4884
4954
  const entries = Object.entries(props.columns);
4885
4955
  let visibleCount = 0;
4886
4956
  return entries.reduce((acc, [key, col]) => {
4887
4957
  if (col.defaultHidden) acc[key] = false;
4888
- else if (visibleCount < DEFAULT_MAX_VISIBLE_COLUMNS) {
4958
+ else if (visibleCount < 8) {
4889
4959
  acc[key] = true;
4890
4960
  visibleCount++;
4891
4961
  } else acc[key] = false;
@@ -4952,13 +5022,14 @@ const DataTable = (props) => {
4952
5022
  }),
4953
5023
  handler: async (values) => {
4954
5024
  if (typeof props.items === "function") {
4955
- const response = await props.items(values, { items: items.content });
5025
+ const response = await props.items(values, { items: itemsRef.current.content });
4956
5026
  if (props.infinityScroll && values.page > 0) setItems((prev) => ({
4957
5027
  ...response,
4958
5028
  content: [...prev.content, ...response.content]
4959
5029
  }));
4960
5030
  else setItems(response);
4961
5031
  setCurrentPage(values.page);
5032
+ if (!loaded) setLoaded(true);
4962
5033
  }
4963
5034
  },
4964
5035
  onReset: async () => {
@@ -4978,9 +5049,23 @@ const DataTable = (props) => {
4978
5049
  return;
4979
5050
  }
4980
5051
  props.onFilterChange?.(key, value, form);
5052
+ if (props.skipSubmitOnChange) return;
5053
+ form.input.page.set(0);
5054
+ const delay = props.debounce ?? 300;
5055
+ if (delay > 0) {
5056
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5057
+ debounceRef.current = setTimeout(() => {
5058
+ form.submit();
5059
+ }, delay);
5060
+ } else await form.submit();
4981
5061
  }
4982
- }, [items]);
5062
+ }, []);
4983
5063
  const dt = useInject(DateTimeProvider);
5064
+ useEffect(() => {
5065
+ return () => {
5066
+ if (debounceRef.current) clearTimeout(debounceRef.current);
5067
+ };
5068
+ }, []);
4984
5069
  useEffect(() => {
4985
5070
  if (props.submitOnInit) form.submit();
4986
5071
  if (props.submitEvery) {
@@ -5045,9 +5130,9 @@ const DataTable = (props) => {
5045
5130
  }), col.sortable && /* @__PURE__ */ jsxs(Flex$1, {
5046
5131
  c: "dimmed",
5047
5132
  children: [
5048
- sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.sm }),
5049
- sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.sm }),
5050
- sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.sm })
5133
+ sortDir === "asc" && /* @__PURE__ */ jsx(IconArrowUp, { size: ui.sizes.icon.xs }),
5134
+ sortDir === "desc" && /* @__PURE__ */ jsx(IconArrowDown, { size: ui.sizes.icon.xs }),
5135
+ sortDir === null && /* @__PURE__ */ jsx(IconArrowsSort, { size: ui.sizes.icon.xs })
5051
5136
  ]
5052
5137
  })]
5053
5138
  })
@@ -5107,9 +5192,15 @@ const DataTable = (props) => {
5107
5192
  form,
5108
5193
  alepha
5109
5194
  };
5195
+ const content = col.value?.(item, ctx);
5110
5196
  return /* @__PURE__ */ jsx(Table.Td, {
5111
5197
  style: col.fit ? FIT_STYLE : void 0,
5112
- children: col.value?.(item, ctx)
5198
+ children: col.action ? /* @__PURE__ */ jsx(ActionButton, {
5199
+ td: "inherit",
5200
+ unstyled: true,
5201
+ ...col.action(item),
5202
+ children: content
5203
+ }) : content
5113
5204
  }, key);
5114
5205
  }),
5115
5206
  props.rowActions && (() => {
@@ -5126,7 +5217,7 @@ const DataTable = (props) => {
5126
5217
  style: FIT_STYLE,
5127
5218
  onClick: (e) => e.stopPropagation(),
5128
5219
  children: /* @__PURE__ */ jsx(ActionButton, {
5129
- variant: "subtle",
5220
+ variant: "minimal",
5130
5221
  size: "xs",
5131
5222
  icon: IconDotsVertical,
5132
5223
  menu: { items: actions.map((action) => {
@@ -5134,7 +5225,10 @@ const DataTable = (props) => {
5134
5225
  return {
5135
5226
  label: action.label ?? (typeof action.tooltip === "string" ? action.tooltip : void 0),
5136
5227
  icon: Icon && isComponentType(Icon) ? /* @__PURE__ */ jsx(Icon, { size: 14 }) : Icon,
5137
- onClick: action.onClick,
5228
+ onClick: action.onClick ? async () => {
5229
+ await action.onClick();
5230
+ if (!action.skipRefresh) await form.submit();
5231
+ } : void 0,
5138
5232
  color: action.color
5139
5233
  };
5140
5234
  }) }
@@ -5196,15 +5290,21 @@ const DataTable = (props) => {
5196
5290
  bordered: true,
5197
5291
  elevated: true,
5198
5292
  shadowed: "xs",
5293
+ flex: 1,
5294
+ style: { minHeight: 0 },
5199
5295
  children: [
5200
5296
  /* @__PURE__ */ jsx(Flex$1, {
5201
5297
  className: "overflow-auto",
5298
+ flex: 1,
5299
+ style: { minHeight: 0 },
5300
+ col: true,
5202
5301
  children: /* @__PURE__ */ jsxs(Table, {
5203
5302
  "aria-label": "Data table",
5204
5303
  withRowBorders: true,
5205
5304
  highlightOnHover: true,
5206
5305
  ...props.tableProps,
5207
5306
  children: [/* @__PURE__ */ jsx(Table.Thead, {
5307
+ bdrs: "md",
5208
5308
  style: {
5209
5309
  position: "sticky",
5210
5310
  top: 0,
@@ -5216,30 +5316,39 @@ const DataTable = (props) => {
5216
5316
  head,
5217
5317
  props.rowActions && /* @__PURE__ */ jsx(Table.Th, { style: FIT_STYLE })
5218
5318
  ] })
5219
- }), /* @__PURE__ */ jsxs(Table.Tbody, {
5220
- style: {
5221
- opacity: form.submitting ? .5 : 1,
5222
- transition: "opacity 150ms ease"
5223
- },
5224
- children: [rows, items.content.length === 0 && /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5225
- colSpan: totalColumns || 1,
5226
- py: "xl",
5227
- style: { textAlign: "center" },
5319
+ }), /* @__PURE__ */ jsx(Table.Tbody, { children: !loaded || form.submitting ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5320
+ colSpan: totalColumns || 1,
5321
+ py: "sm",
5322
+ children: /* @__PURE__ */ jsx(Flex$1, {
5323
+ justify: "center",
5324
+ p: "md",
5325
+ children: /* @__PURE__ */ jsx(Loader, {
5326
+ size: "sm",
5327
+ type: "dots"
5328
+ })
5329
+ })
5330
+ }) }) : rows.length === 0 ? /* @__PURE__ */ jsx(Table.Tr, { children: /* @__PURE__ */ jsx(Table.Td, {
5331
+ colSpan: totalColumns || 1,
5332
+ py: "xl",
5333
+ children: /* @__PURE__ */ jsx(Flex$1, {
5334
+ justify: "center",
5228
5335
  children: /* @__PURE__ */ jsx(Text$1, {
5229
5336
  c: "dimmed",
5230
5337
  size: "sm",
5231
- children: form.submitting ? "Loading…" : "No results"
5338
+ children: props.emptyLabel ?? "No results"
5232
5339
  })
5233
- }) })]
5234
- })]
5340
+ })
5341
+ }) }) : rows })]
5235
5342
  })
5236
5343
  }),
5237
5344
  props.infinityScroll && /* @__PURE__ */ jsx("div", { ref: sentinelRef }),
5238
5345
  !props.infinityScroll && /* @__PURE__ */ jsx(DataTablePagination, {
5239
5346
  page,
5240
5347
  size,
5241
- totalPages: items.page?.totalPages ?? 1,
5348
+ totalPages: items.page?.totalPages,
5242
5349
  totalElements: items.page?.totalElements,
5350
+ isFirst: items.page?.isFirst,
5351
+ isLast: items.page?.isLast,
5243
5352
  offset: items.page?.offset ?? 0,
5244
5353
  numberOfElements: items.content.length,
5245
5354
  onPageChange: (value) => {
@@ -5261,7 +5370,6 @@ const DataTable = (props) => {
5261
5370
  })]
5262
5371
  });
5263
5372
  };
5264
-
5265
5373
  //#endregion
5266
5374
  //#region ../../src/core/utils/extractSchemaFields.ts
5267
5375
  /**
@@ -5350,15 +5458,14 @@ const OPERATOR_INFO = {
5350
5458
  example: "status=[active,pending]"
5351
5459
  }
5352
5460
  };
5353
-
5354
5461
  //#endregion
5355
5462
  //#region ../../src/core/utils/icons.tsx
5356
5463
  /**
5357
5464
  * Get the default icon for an input based on its type, format, or name.
5358
5465
  */
5359
5466
  const getDefaultIcon = (params) => {
5360
- const { type, format, name, isEnum, isArray, size = "sm" } = params;
5361
- const iconSize = ui.sizes.icon[size];
5467
+ const { type, format, name, isEnum, isArray, size = "xs" } = params;
5468
+ const iconSize = ui.sizes.icon[size] - 4;
5362
5469
  if (format) switch (format) {
5363
5470
  case "email": return /* @__PURE__ */ jsx(IconMail, { size: iconSize });
5364
5471
  case "url":
@@ -5392,7 +5499,6 @@ const getDefaultIcon = (params) => {
5392
5499
  }
5393
5500
  return /* @__PURE__ */ jsx(IconAt, { size: iconSize });
5394
5501
  };
5395
-
5396
5502
  //#endregion
5397
5503
  //#region ../../src/core/utils/string.ts
5398
5504
  /**
@@ -5430,7 +5536,6 @@ const prettyName = (name) => {
5430
5536
  const segments = name.split("/").filter((s) => s && !/^\d+$/.test(s));
5431
5537
  return toTitleCase(segments[segments.length - 1] || name.replaceAll("/", ""));
5432
5538
  };
5433
-
5434
5539
  //#endregion
5435
5540
  //#region ../../src/core/index.ts
5436
5541
  /**
@@ -5469,7 +5574,7 @@ const AlephaUI = $module({
5469
5574
  alepha.with(ToastService);
5470
5575
  }
5471
5576
  });
5472
-
5473
5577
  //#endregion
5474
- export { AlephaMantineProvider as _, TypeForm as a, DashboardShell as c, Heading as d, Flex$1 as f, ui as g, ActionButton as h, JsonViewer as i, Sidebar as l, useDialog as m, capitalize as n, Control as o, ToggleSidebarButton as p, DataTable as r, Text$1 as s, AlephaUI as t, Breadcrumb as u, useToast as v };
5475
- //# sourceMappingURL=core-B7LNjM78.js.map
5578
+ export { AlephaMantineProvider as _, TypeForm as a, Sidebar as c, Heading as d, Flex$1 as f, ui as g, ActionButton as h, JsonViewer as i, Text$1 as l, useDialog as m, capitalize as n, Control as o, ToggleSidebarButton as p, DataTable as r, DashboardShell as s, AlephaUI as t, Breadcrumbs as u, useToast as v };
5579
+
5580
+ //# sourceMappingURL=core-DRtQklr3.js.map